From 19c358c32fe91685e7fc001a866b3208444068da Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Tue, 17 Dec 2024 23:56:03 +0100 Subject: Add buffer::push --- asl/buffer.hpp | 53 +++++++++++++++++++++++++++++++++++++++------- asl/tests/buffer_tests.cpp | 34 +++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 8 deletions(-) (limited to 'asl') diff --git a/asl/buffer.hpp b/asl/buffer.hpp index 8ee2869..e001ee0 100644 --- a/asl/buffer.hpp +++ b/asl/buffer.hpp @@ -16,6 +16,16 @@ class buffer T* m_data{}; isize_t m_capacity{}; +public: + static constexpr isize_t kInlineCapacity = []() { + // 1 byte is used for size inline in m_size_encoded. + // This is enough because we have at most 24 bytes available, + // so 23 chars of capacity. + const isize_t available_size = size_of + size_of + size_of - 1; + return available_size / size_of; + }(); + +private: static constexpr size_t kOnHeapMask = 0x8000'0000'0000'0000ULL; // bit 63 : 1 = on heap, 0 = inline @@ -72,15 +82,32 @@ class buffer return is_on_heap(load_size_encoded()); } -public: + constexpr T* push_uninit() + { + isize_t sz = size(); + reserve_capacity(sz + 1); + set_size(sz + 1); + return data() + sz; + } - static constexpr isize_t kInlineCapacity = []() { - // 1 byte is used for size inline in m_size_encoded. - // This is enough because we have at most 24 bytes available, - // so 23 chars of capacity. - const isize_t available_size = size_of + size_of + size_of - 1; - return available_size / size_of; - }(); + constexpr void set_size(isize_t new_size) + { + ASL_ASSERT(new_size >= 0); + ASL_ASSERT_RELEASE(new_size <= capacity()); + size_t size_encoded = load_size_encoded(); + if (kInlineCapacity == 0 || is_on_heap(size_encoded)) + { + store_size_encoded(encode_size_heap(new_size)); + } + else + { + ASL_ASSERT(new_size <= kInlineCapacity); + size_encoded = (size_encoded & size_t{0x00ff'ffff'ffff'ffff}) | (bit_cast(new_size) << 56); + store_size_encoded(size_encoded); + } + } + +public: constexpr buffer() requires default_constructible = default; @@ -144,6 +171,14 @@ public: store_size_encoded(encode_size_heap(current_size)); } + constexpr T& push(auto&&... args) + requires constructible_from + { + T* uninit = push_uninit(); + T* init = construct_at(uninit, ASL_FWD(args)...); + return *init; + } + // @Todo(C++23) Use deducing this const T* data() const { @@ -168,6 +203,8 @@ public: return is_on_heap() ? m_data : reinterpret_cast(this); } } + + // @Todo operator[] }; } // namespace asl diff --git a/asl/tests/buffer_tests.cpp b/asl/tests/buffer_tests.cpp index 32f6682..3dc8ffb 100644 --- a/asl/tests/buffer_tests.cpp +++ b/asl/tests/buffer_tests.cpp @@ -49,3 +49,37 @@ ASL_TEST(reserve_capacity) ASL_TEST_EXPECT(b.size() == 0); ASL_TEST_EXPECT(b.capacity() >= 130); } + +// NOLINTBEGIN(*-pointer-arithmetic) +ASL_TEST(push) +{ + asl::buffer b; + ASL_TEST_EXPECT(b.size() == 0); + + b.push(1); + ASL_TEST_EXPECT(b.size() == 1); + ASL_TEST_EXPECT(b.data()[0] == 1); + + b.push(2); + b.push(3); + ASL_TEST_EXPECT(b.size() == 3); + ASL_TEST_EXPECT(b.data()[0] == 1); + ASL_TEST_EXPECT(b.data()[1] == 2); + ASL_TEST_EXPECT(b.data()[2] == 3); + + b.push(4); + b.push(5); + b.push(6); + b.push(7); + ASL_TEST_EXPECT(b.size() == 7); + ASL_TEST_EXPECT(b.data()[0] == 1); + ASL_TEST_EXPECT(b.data()[1] == 2); + ASL_TEST_EXPECT(b.data()[2] == 3); + ASL_TEST_EXPECT(b.data()[3] == 4); + ASL_TEST_EXPECT(b.data()[4] == 5); + ASL_TEST_EXPECT(b.data()[5] == 6); + ASL_TEST_EXPECT(b.data()[6] == 7); +} +// NOLINTEND(*-pointer-arithmetic) + +// @Todo Test push with non trivial move (non copy) types -- cgit