summaryrefslogtreecommitdiff
path: root/asl/buffer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'asl/buffer.hpp')
-rw-r--r--asl/buffer.hpp87
1 files changed, 83 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