Skip to content

Commit

Permalink
#55 adding assign to VLA
Browse files Browse the repository at this point in the history
  • Loading branch information
thirtytwobits committed Aug 15, 2023
1 parent 64209d5 commit b6f1420
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 6 deletions.
6 changes: 4 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@
"strstream": "cpp",
"typeindex": "cpp",
"charconv": "cpp",
"csignal": "cpp"
}
"csignal": "cpp",
"format": "cpp"
},
"git-blame.gitWebUrl": ""
}
16 changes: 16 additions & 0 deletions cetlvast/suites/unittest/test_variable_length_array_bool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,19 @@ TYPED_TEST(VLABoolTests, TestBoolIterator)
ASSERT_EQ(true, *(foo.cend() - 1));
ASSERT_EQ(true, foo.cbegin()[2]);
}

TYPED_TEST(VLABoolTests, TestBoolResize)
{
auto array = TypeParam::make_bool_container();
array.resize(15);
ASSERT_EQ(15, array.size());
ASSERT_EQ(false, array[8]);
}

TYPED_TEST(VLABoolTests, TestBoolResizeWithDefault)
{
auto array = TypeParam::make_bool_container();
array.resize(22, true);
ASSERT_EQ(22, array.size());
ASSERT_EQ(true, array[8]);
}
124 changes: 123 additions & 1 deletion cetlvast/suites/unittest/test_variable_length_array_compat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ class CetlUnsynchronizedArrayMemoryResourceFactory
return delegate_.reallocate(p, old_size_bytes, new_size_bytes, alignment);
}

std::array<cetl::pf17::byte, ImplArraySizeBytes> memory_;
std::array<cetl::pf17::byte, ImplArraySizeBytes> memory_;
cetl::pmr::UnsynchronizedBufferMemoryResourceDelegate<cetl::pf17::pmr::memory_resource> delegate_;
};

Expand Down Expand Up @@ -662,6 +662,62 @@ TYPED_TEST(VLATestsGeneric, TestOverMaxSize)
#endif
}

// +-------------------------------------------------------------------------------------------------------------------+

TYPED_TEST(VLATestsGeneric, TestResize)
{
typename TestFixture::SubjectType subject{TestFixture::make_allocator()};

std::size_t clamped_max = std::min(this->get_expected_max_size(), 10UL);
ASSERT_GT(this->get_expected_max_size(), 0) << "This test is only valid if get_expected_max_size() > 0";
ASSERT_GT(clamped_max, subject.size());
subject.resize(clamped_max);
ASSERT_EQ(clamped_max, subject.size());

typename TestFixture::SubjectType::value_type default_constructed_value{};
ASSERT_EQ(subject[subject.size() - 1], default_constructed_value);
}

// +-------------------------------------------------------------------------------------------------------------------+

TYPED_TEST(VLATestsGeneric, TestResizeWithCopy)
{
if (std::is_same<typename TypeParam::container_type, cetlvast::SkipTag>::value)
{
GTEST_SKIP() << "Skipping test that requires CETL reallocation support.";
}

typename TestFixture::SubjectType subject{TestFixture::make_allocator()};

std::size_t clamped_max = std::min(this->get_expected_max_size(), 10UL);
ASSERT_GT(this->get_expected_max_size(), 1) << "This test is only valid if get_expected_max_size() > 1";
ASSERT_GT(clamped_max, subject.size());

subject.push_back(1);

const typename TestFixture::SubjectType::value_type copy_from_value{2};
subject.resize(clamped_max, copy_from_value);
ASSERT_EQ(clamped_max, subject.size());
ASSERT_EQ(1, subject[0]);

for (std::size_t i = 1; i < subject.size(); ++i)
{
ASSERT_EQ(subject[i], copy_from_value);
}
}

// +----------------------------------------------------------------------+

#ifdef __cpp_exceptions

TYPED_TEST(VLATestsGeneric, TestResizeExceptionLengthError)
{
typename TestFixture::SubjectType subject{TestFixture::make_allocator()};
ASSERT_THROW(subject.resize(subject.max_size() + 1), std::length_error);
}

#endif // __cpp_exceptions

// +----------------------------------------------------------------------+
/**
* Test suite to ensure non-trivial objects are properly handled. This one is both for bool and non-bool spec.
Expand Down Expand Up @@ -1036,3 +1092,69 @@ TEST(VLATestsNonTrivialSpecific, TestMoveAssignment)
ASSERT_NE(lhs, rhs);
ASSERT_EQ(std::string("three"), lhs[0]);
}

struct NoDefault
{
~NoDefault() = default;
NoDefault() = delete;
NoDefault(int value)
: data_{value} {};
NoDefault(const NoDefault&) = default;
NoDefault(NoDefault&&) noexcept = default;
NoDefault& operator=(const NoDefault&) = default;
NoDefault& operator=(NoDefault&&) noexcept = default;

int data() const noexcept
{
return data_;
}

private:
int data_;
};

TEST(VLATestsNonTrivialSpecific, TestResizeWithNoDefaultCtorData)
{
std::allocator<NoDefault> allocator{};
cetl::VariableLengthArray<NoDefault, std::allocator<NoDefault>> subject{{NoDefault{1}}, allocator};
ASSERT_EQ(1, subject.size());
subject.resize(10, NoDefault{2});
ASSERT_EQ(10, subject.size());
ASSERT_EQ(1, subject[0].data());
for (std::size_t i = 1; i < subject.size(); ++i)
{
ASSERT_EQ(2, subject[i].data());
}
}

#ifdef __cpp_exceptions

struct GrenadeError : public std::runtime_error
{
GrenadeError(const char* message)
: std::runtime_error(message)
{

}
};

struct Grenade
{
Grenade(int value)
{
if (value == 2)
{
throw GrenadeError("");
}
}
};

TYPED_TEST(VLATestsGeneric, TestResizeExceptionFromCtorOnResize)
{
std::allocator<Grenade> allocator{};
cetl::VariableLengthArray<Grenade, std::allocator<Grenade>> subject{{Grenade{1}}, allocator};
ASSERT_EQ(1, subject.size());
ASSERT_THROW(subject.resize(2, Grenade{2}), GrenadeError);
}

#endif // __cpp_exceptions
63 changes: 60 additions & 3 deletions include/cetl/variable_length_array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// Copyright Amazon.com Inc. or its affiliates.
/// SPDX-License-Identifier: MIT
///
/// cSpell:ignore cend cbegin rnext rend lnext lbegin pocca pocma
/// cSpell:ignore cend cbegin rnext rend lnext lbegin pocca pocma urvo

#ifndef CETL_VARIABLE_LENGTH_ARRAY_HPP_INCLUDED
#define CETL_VARIABLE_LENGTH_ARRAY_HPP_INCLUDED
Expand Down Expand Up @@ -1394,8 +1394,6 @@ class VariableLengthArray : protected VariableLengthArrayBase<T, Allocator>
data_[--size_].~value_type();
}
}

///
/// Like push_back but constructs the object directly in uninitialized memory.
/// @throw throw std::length_error if there was not enough storage for an additional element.
/// If exceptions are disabled then the caller must check the array size before and
Expand All @@ -1415,6 +1413,35 @@ class VariableLengthArray : protected VariableLengthArrayBase<T, Allocator>
size_++;
}

/// Resizes internal storage to count elements default initializing any added elements over the
/// current size() and deleting any elements under the current size(). If size() == `count` then
/// this method has no effect.
///
/// @param count The new size to set for this container.
/// @throw * If exceptions are enabled then any exceptions that `value_type` constructors or destructors
/// throw will escape this call
/// @throw std::length_error if the size requested is greater than `max_size()`.
/// @throw std::bad_alloc if the container cannot obtain enough memory to size up to `count`.
constexpr void resize(size_type count)
{
Base::resize(count, max_size());
}

/// Resizes internal storage to count elements copy-initializing any added elements over the
/// current size() and deleting any elements under the current size(). If size() == `count` then
/// this method has no effect.
///
/// @param count The new size to set for this container.
/// @param value The value to copy into any new elements created by the operation.
/// @throw * If exceptions are enabled then any exceptions that `value_type` constructors or destructors
/// throw will escape this call
/// @throw std::length_error if the size requested is greater than `max_size()`.
/// @throw std::bad_alloc if the container cannot obtain enough memory to size up to `count`.
constexpr void resize(size_type count, const value_type& value)
{
Base::resize(count, max_size(), value);
}

private:
// +----------------------------------------------------------------------+

Expand Down Expand Up @@ -2117,6 +2144,36 @@ class VariableLengthArray<bool, Allocator> : protected VariableLengthArrayBase<u
}
}

/// Resizes internal storage to count elements default initializing any added elements over the
/// current size() and deleting any elements under the current size(). If size() == `count` then
/// this method has no effect.
///
/// @param count The new size, in bits, to set for this container.
/// @throw * If exceptions are enabled then any exceptions that `value_type` constructors or destructors
/// throw will escape this call
/// @throw std::length_error if the size requested is greater than `max_size()`.
/// @throw std::bad_alloc if the container cannot obtain enough memory to size up to `count`.
constexpr void resize(size_type count)
{
Base::resize(bits2bytes(count), max_size());
}

/// Resizes internal storage to count elements copy-initializing any added elements over the
/// current size() and deleting any elements under the current size(). If size() == `count` then
/// this method has no effect.
///
/// @param count The new size, in bites, to set for this container.
/// @param value The value to copy into any new elements created by the operation.
/// @throw * If exceptions are enabled then any exceptions that `value_type` constructors or destructors
/// throw will escape this call
/// @throw std::length_error if the size requested is greater than `max_size()`.
/// @throw std::bad_alloc if the container cannot obtain enough memory to size up to `count`.
constexpr void resize(size_type count, const value_type& value)
{
Base::resize(bits2bytes(count), max_size(), value);
}


private:
constexpr bool ensure_size_plus_one()
{
Expand Down

0 comments on commit b6f1420

Please sign in to comment.