Some careful work on buffer
This commit is contained in:
@ -3,6 +3,7 @@
|
||||
#include "asl/meta.hpp"
|
||||
#include "asl/allocator.hpp"
|
||||
#include "asl/annotations.hpp"
|
||||
#include "asl/memory.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
@ -14,10 +15,12 @@ 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;
|
||||
|
||||
@ -25,6 +28,34 @@ class buffer
|
||||
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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user