Move `VectorResizableTraits` from `resizable_writer.h` to an internal namespace in `vector_writer.h`. PiperOrigin-RevId: 888546224
diff --git a/riegeli/bytes/BUILD b/riegeli/bytes/BUILD index bdf6e6f..983b122 100644 --- a/riegeli/bytes/BUILD +++ b/riegeli/bytes/BUILD
@@ -899,6 +899,7 @@ hdrs = ["vector_writer.h"], deps = [ ":resizable_writer", + "//riegeli/base:assert", "//riegeli/base:dependency", "//riegeli/base:initializer", "//riegeli/base:object",
diff --git a/riegeli/bytes/resizable_writer.h b/riegeli/bytes/resizable_writer.h index 070a957..206f49e 100644 --- a/riegeli/bytes/resizable_writer.h +++ b/riegeli/bytes/resizable_writer.h
@@ -374,96 +374,6 @@ } }; -// `ResizableTraits` for `std::vector<T, Alloc>` including -// `UninitializedVector<T>`, `absl::InlinedVector<T, inlined_size, Alloc>` -// including `UninitializedInlinedVector<T, inlined_size>`, or a similar type. -// Its value type must be trivially copyable, usually `char`. -// -// The vector type must support at least the following members: -// -// ``` -// using value_type = ...; -// -// value_type* data(); -// size_t size() const; -// size_t max_size() const; -// size_t capacity() const; -// -// iterator begin(); -// iterator end(); -// -// void resize(size_t new_size); -// void reserve(size_t new_capacity); -// void erase(iterator first, iterator last); -// ``` -// -// Warning: byte contents are reinterpreted as values of type `T`, and the size -// is rounded up to a multiple of the element type. -template <typename VectorType> -struct VectorResizableTraits { - private: - using T = typename VectorType::value_type; - - public: - static_assert(std::is_trivially_copyable_v<T>, - "Value type of the parameter of VectorResizableTraits must be " - "trivially copyable"); - - using Resizable = VectorType; - static char* Data(Resizable& dest) { - return reinterpret_cast<char*>(dest.data()); - } - static size_t Size(const Resizable& dest) { return dest.size() * sizeof(T); } - static constexpr bool kIsStable = true; - static bool Resize(Resizable& dest, size_t new_size, size_t used_size) { - RIEGELI_ASSERT_LE(used_size, dest.size() * sizeof(T)) - << "Failed precondition of ResizableTraits::Resize(): " - "used size exceeds old size"; - RIEGELI_ASSERT_LE(used_size, new_size) - << "Failed precondition of ResizableTraits::Resize(): " - "used size exceeds new size"; - const size_t new_num_elements = SizeToNumElements(new_size); - Reserve(dest, new_num_elements, used_size); - dest.resize(new_num_elements); - return true; - } - static void GrowToCapacity(Resizable& dest) { dest.resize(dest.capacity()); } - static bool Grow(Resizable& dest, size_t new_size, size_t used_size) { - RIEGELI_ASSERT_LE(used_size, dest.size() * sizeof(T)) - << "Failed precondition of ResizableTraits::Grow(): " - "used size exceeds old size"; - RIEGELI_ASSERT_LE(used_size, new_size) - << "Failed precondition of ResizableTraits::Grow(): " - "used size exceeds new size"; - Reserve(dest, SizeToNumElements(new_size), used_size); - GrowToCapacity(dest); - return true; - } - - private: - static size_t SizeToNumElements(size_t size) { - return size / sizeof(T) + (size % sizeof(T) == 0 ? 0 : 1); - } - static void Reserve(Resizable& dest, size_t new_num_elements, - size_t used_size) { - if (new_num_elements > dest.capacity()) { - dest.erase(dest.begin() + SizeToNumElements(used_size), dest.end()); - if constexpr (std::is_default_constructible_v<Resizable>) { - dest.reserve( - dest.capacity() <= Resizable().capacity() - ? new_num_elements - : UnsignedMax(new_num_elements, - UnsignedMin(dest.capacity() + dest.capacity() / 2, - dest.max_size()))); - } else { - dest.reserve(UnsignedMax( - new_num_elements, UnsignedMin(dest.capacity() + dest.capacity() / 2, - dest.max_size()))); - } - } - } -}; - // Implementation details follow. inline ResizableWriterBase::ResizableWriterBase(BufferOptions buffer_options)
diff --git a/riegeli/bytes/vector_writer.h b/riegeli/bytes/vector_writer.h index c570acf..974d27c 100644 --- a/riegeli/bytes/vector_writer.h +++ b/riegeli/bytes/vector_writer.h
@@ -19,6 +19,7 @@ #include <type_traits> +#include "riegeli/base/assert.h" #include "riegeli/base/dependency.h" #include "riegeli/base/initializer.h" #include "riegeli/base/object.h" @@ -27,6 +28,100 @@ namespace riegeli { +namespace vector_writer_internal { + +// `ResizableTraits` for `std::vector<T, Alloc>` including +// `UninitializedVector<T>`, `absl::InlinedVector<T, inlined_size, Alloc>` +// including `UninitializedInlinedVector<T, inlined_size>`, or a similar type. +// Its value type must be trivially copyable, usually `char`. +// +// The vector type must support at least the following members: +// +// ``` +// using value_type = ...; +// +// value_type* data(); +// size_t size() const; +// size_t max_size() const; +// size_t capacity() const; +// +// iterator begin(); +// iterator end(); +// +// void resize(size_t new_size); +// void reserve(size_t new_capacity); +// void erase(iterator first, iterator last); +// ``` +// +// Warning: byte contents are reinterpreted as values of type `T`, and the size +// is rounded up to a multiple of the element type. +template <typename VectorType> +struct VectorResizableTraits { + private: + using T = typename VectorType::value_type; + + public: + static_assert(std::is_trivially_copyable_v<T>, + "Value type of the parameter of VectorResizableTraits must be " + "trivially copyable"); + + using Resizable = VectorType; + static char* Data(Resizable& dest) { + return reinterpret_cast<char*>(dest.data()); + } + static size_t Size(const Resizable& dest) { return dest.size() * sizeof(T); } + static constexpr bool kIsStable = true; + static bool Resize(Resizable& dest, size_t new_size, size_t used_size) { + RIEGELI_ASSERT_LE(used_size, dest.size() * sizeof(T)) + << "Failed precondition of ResizableTraits::Resize(): " + "used size exceeds old size"; + RIEGELI_ASSERT_LE(used_size, new_size) + << "Failed precondition of ResizableTraits::Resize(): " + "used size exceeds new size"; + const size_t new_num_elements = SizeToNumElements(new_size); + Reserve(dest, new_num_elements, used_size); + dest.resize(new_num_elements); + return true; + } + static void GrowToCapacity(Resizable& dest) { dest.resize(dest.capacity()); } + static bool Grow(Resizable& dest, size_t new_size, size_t used_size) { + RIEGELI_ASSERT_LE(used_size, dest.size() * sizeof(T)) + << "Failed precondition of ResizableTraits::Grow(): " + "used size exceeds old size"; + RIEGELI_ASSERT_LE(used_size, new_size) + << "Failed precondition of ResizableTraits::Grow(): " + "used size exceeds new size"; + Reserve(dest, SizeToNumElements(new_size), used_size); + GrowToCapacity(dest); + return true; + } + + private: + static size_t SizeToNumElements(size_t size) { + return size / sizeof(T) + (size % sizeof(T) == 0 ? 0 : 1); + } + static void Reserve(Resizable& dest, size_t new_num_elements, + size_t used_size) { + if (new_num_elements > dest.capacity()) { + dest.erase(dest.begin() + SizeToNumElements(used_size), dest.end()); + if constexpr (std::is_default_constructible_v<Resizable>) { + dest.reserve( + dest.capacity() <= Resizable().capacity() + ? new_num_elements + : UnsignedMax(new_num_elements, + UnsignedMin(dest.capacity() + dest.capacity() / 2, + dest.max_size()))); + } else { + dest.reserve(UnsignedMax( + new_num_elements, UnsignedMin(dest.capacity() + dest.capacity() / 2, + dest.max_size()))); + } + } + } +}; + +} // namespace vector_writer_internal + // Template parameter independent part of `VectorWriter`. using VectorWriterBase = ResizableWriterBase; @@ -65,7 +160,7 @@ template <typename Dest = UninitializedVector<char>*> class VectorWriter : public ResizableWriter< - VectorResizableTraits<std::remove_pointer_t< + vector_writer_internal::VectorResizableTraits<std::remove_pointer_t< typename Dependency<void*, TargetT<Dest>>::Subhandle>>, Dest> { public: