diff --git a/rtc_base/bounded_inline_vector.h b/rtc_base/bounded_inline_vector.h index 6e8eb23feb..f8b7eb3d86 100644 --- a/rtc_base/bounded_inline_vector.h +++ b/rtc_base/bounded_inline_vector.h @@ -34,6 +34,7 @@ class BoundedInlineVector { static_assert(fixed_capacity > 0, "Capacity must be strictly positive"); public: + using size_type = int; using value_type = T; using const_iterator = const T*; @@ -108,6 +109,22 @@ class BoundedInlineVector { int size() const { return storage_.size; } constexpr int capacity() const { return fixed_capacity; } + // Resizes the BoundedInlineVector to the given size, which must not exceed + // its constant capacity. If the size is increased, the added elements are + // default constructed. + void resize(int new_size) { + RTC_DCHECK_GE(new_size, 0); + RTC_DCHECK_LE(new_size, fixed_capacity); + if (new_size > storage_.size) { + bounded_inline_vector_impl::DefaultInitializeElements( + storage_.data + storage_.size, new_size - storage_.size); + } else if (new_size < storage_.size) { + bounded_inline_vector_impl::DestroyElements(storage_.data + new_size, + storage_.size - new_size); + } + storage_.size = new_size; + } + const T* data() const { return storage_.data; } T* data() { return storage_.data; } diff --git a/rtc_base/bounded_inline_vector_impl.h b/rtc_base/bounded_inline_vector_impl.h index ab5249444b..3539ace5bc 100644 --- a/rtc_base/bounded_inline_vector_impl.h +++ b/rtc_base/bounded_inline_vector_impl.h @@ -45,6 +45,16 @@ void InitializeElements(T* data, U&& element, Us&&... elements) { InitializeElements(data + 1, std::forward(elements)...); } +// Default initializes uninitialized array elements. +// TODO(kwiberg): Replace with std::uninitialized_default_construct_n() (C++17). +template +void DefaultInitializeElements(T* data, int size) { + for (int i = 0; i < size; ++i) { + // Placement new, because we construct a new object in uninitialized memory. + ::new (&data[i]) T; + } +} + // Copies from source to uninitialized destination. Caller is responsible for // ensuring that there is enough space in `dst_data`. template diff --git a/rtc_base/bounded_inline_vector_unittest.cc b/rtc_base/bounded_inline_vector_unittest.cc index e5855a485c..50cf2e3153 100644 --- a/rtc_base/bounded_inline_vector_unittest.cc +++ b/rtc_base/bounded_inline_vector_unittest.cc @@ -114,5 +114,20 @@ TYPED_TEST(BoundedInlineVectorTestAllTypes, Return) { EXPECT_EQ((Returns(TypeParam(), TypeParam()).size()), 2); } +TYPED_TEST(BoundedInlineVectorTestAllTypes, Resize) { + BoundedInlineVector x; + EXPECT_EQ(x.size(), 0); + x.resize(17); + EXPECT_EQ(x.size(), 17); + // Test one arbitrary element, mostly to give MSan a chance to scream. But if + // the type has a trivial default constructor we can't, because the element + // won't be initialized. + if (!std::is_trivially_default_constructible::value) { + EXPECT_EQ(x[4], TypeParam()); + } + x.resize(2); + EXPECT_EQ(x.size(), 2); +} + } // namespace } // namespace webrtc