diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-08 23:58:43 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-20 15:35:58 +0100 |
commit | af164f9af26d0c64d2e8210039b99e4f191acdaa (patch) | |
tree | 85bf7c0703bd03f88ec99d4f5a9f9931471da2b0 /asl | |
parent | 72fe8dd2d6d6a3a5592646950a4e43b9a79ed9b4 (diff) |
Some careful work on buffer
Diffstat (limited to 'asl')
-rw-r--r-- | asl/buffer.hpp | 87 | ||||
-rw-r--r-- | asl/tests/buffer_tests.cpp | 18 |
2 files changed, 101 insertions, 4 deletions
diff --git a/asl/buffer.hpp b/asl/buffer.hpp index abf29fe..b45d5d8 100644 --- a/asl/buffer.hpp +++ b/asl/buffer.hpp @@ -3,6 +3,7 @@ #include "asl/meta.hpp"
#include "asl/allocator.hpp"
#include "asl/annotations.hpp"
+#include "asl/memory.hpp"
namespace asl
{
@@ -14,17 +15,47 @@ class buffer T* m_data{};
isize_t m_capacity{};
- // bit 63 : 0 = on heap, 1 = inline
+ static constexpr size_t kOnHeapMask = 0x8000'0000'0000'0000ULL;
+
+ // bit 63 : 1 = on heap, 0 = inline
// bits [62:56] : size when inline
- // bits [52:0] : size when on heap
- size_t m_size_encoded{};
+ // bits [62:0] : size when on heap
+ size_t m_size_encoded_{};
ASL_NO_UNIQUE_ADDRESS Allocator m_allocator;
static_assert(align_of<T> <= align_of<T*>);
static_assert(align_of<T*> == align_of<isize_t>);
static_assert(align_of<T*> == align_of<size_t>);
-
+
+ constexpr size_t load_size_encoded() const
+ {
+ size_t s{};
+ asl::memcpy(&s, &m_size_encoded_, sizeof(size_t));
+ return s;
+ }
+
+ static constexpr bool is_on_heap(size_t size_encoded)
+ {
+ return (size_encoded & kOnHeapMask) != 0;
+ }
+
+ static constexpr isize_t decode_size(size_t size_encoded)
+ {
+ if constexpr (kInlineCapacity == 0)
+ {
+ return is_on_heap(size_encoded)
+ ? static_cast<isize_t>(size_encoded & (~kOnHeapMask))
+ : 0;
+ }
+ else
+ {
+ return is_on_heap(size_encoded)
+ ? static_cast<isize_t>(size_encoded & (~kOnHeapMask))
+ : static_cast<isize_t>(size_encoded >> 56);
+ }
+ }
+
public:
static constexpr isize_t kInlineCapacity = []() {
@@ -40,6 +71,54 @@ public: explicit constexpr buffer(Allocator allocator)
: m_allocator{ASL_MOVE(allocator)}
{}
+
+ constexpr isize_t size() const
+ {
+ return decode_size(load_size_encoded());
+ }
+
+ constexpr isize_t capacity() const
+ {
+ if constexpr (kInlineCapacity == 0)
+ {
+ return m_capacity;
+ }
+ else
+ {
+ return is_on_heap(load_size_encoded())
+ ? m_capacity
+ : kInlineCapacity;
+ }
+ }
+
+ // @Todo(C++23) Use deducing this
+ const T* data() const
+ {
+ if constexpr (kInlineCapacity == 0)
+ {
+ return m_data;
+ }
+ else
+ {
+ return is_on_heap(load_size_encoded())
+ ? m_data
+ : reinterpret_cast<const T*>(this);
+ }
+ }
+
+ T* data()
+ {
+ if constexpr (kInlineCapacity == 0)
+ {
+ return m_data;
+ }
+ else
+ {
+ return is_on_heap(load_size_encoded())
+ ? m_data
+ : reinterpret_cast<const T*>(this);
+ }
+ }
};
} // namespace asl
diff --git a/asl/tests/buffer_tests.cpp b/asl/tests/buffer_tests.cpp index 133a549..2d23b2f 100644 --- a/asl/tests/buffer_tests.cpp +++ b/asl/tests/buffer_tests.cpp @@ -2,7 +2,25 @@ #include <asl/testing/testing.hpp>
+struct Big
+{
+ uint64_t data[8];
+};
+
static_assert(asl::buffer<int32_t>::kInlineCapacity == 5);
static_assert(asl::buffer<int64_t>::kInlineCapacity == 2);
static_assert(asl::buffer<char>::kInlineCapacity == 23);
+static_assert(asl::buffer<Big>::kInlineCapacity == 0);
+
+ASL_TEST(default_size)
+{
+ asl::buffer<int32_t> b1;
+ ASL_TEST_EXPECT(b1.size() == 0);
+ ASL_TEST_EXPECT(b1.capacity() == 5);
+ ASL_TEST_EXPECT(static_cast<const void*>(b1.data()) == &b1);
+ asl::buffer<Big> b2;
+ ASL_TEST_EXPECT(b2.size() == 0);
+ ASL_TEST_EXPECT(b2.capacity() == 0);
+ ASL_TEST_EXPECT(b2.data() == nullptr);
+}
|