13 template<
class traits_t>
14 sbo_bytes<traits_t>::sbo_bytes(sbo_bytes&& other) noexcept
16 std::swap(m_Data, other.m_Data);
17 std::swap(m_nSize, other.m_nSize);
18 std::swap(m_nAllocatedSize, other.m_nAllocatedSize);
21 template<
class traits_t>
22 sbo_bytes<traits_t>::~sbo_bytes() noexcept
24 QX_STATIC_ASSERT_EQ(
sizeof(sbo_bytes), nSBOSize);
29 template<
class traits_t>
30 sbo_bytes<traits_t>& sbo_bytes<traits_t>::operator=(sbo_bytes&& other) noexcept
32 std::swap(m_Data, other.m_Data);
33 std::swap(m_nSize, other.m_nSize);
34 std::swap(m_nAllocatedSize, other.m_nAllocatedSize);
38 template<
class traits_t>
42 if (nRequestedSize > capacity())
44 bRet = reallocate_to_big(get_new_size(nRequestedSize));
48 if constexpr (bShrinkToFitWhenSmall)
49 if (!is_small() && nRequestedSize <= nBufferSize)
50 reallocate_to_small(nRequestedSize);
54 m_nSize = nRequestedSize;
59 template<
class traits_t>
62 if (nRequestedSize <= capacity())
65 return reallocate_to_big(get_new_size(nRequestedSize));
68 template<
class traits_t>
71 if (m_nSize <= nBufferSize)
74 reallocate_to_small(m_nSize);
80 return reallocate_to_big(m_nSize);
84 template<
class traits_t>
89 std::free(m_Data.pData);
90 m_Data.buffer = buffer_type();
96 template<
class traits_t>
100 return m_Data.buffer.data();
105 template<
class traits_t>
111 template<
class traits_t>
117 template<
class traits_t>
120 return is_small() ? nBufferSize : m_nAllocatedSize;
123 template<
class traits_t>
126 return m_nAllocatedSize == 0;
129 template<
class traits_t>
132 const bool bSmallAtStart = is_small();
134 if (
void* pNewBlock = std::realloc(bSmallAtStart ?
nullptr : m_Data.pData, nNewSize)) [[likely]]
136 if constexpr (bPreserveContents)
138 std::memcpy(pNewBlock, m_Data.buffer.data(), std::min(nNewSize, capacity()));
140 m_Data.pData =
static_cast<std::byte*
>(pNewBlock);
141 m_nAllocatedSize = nNewSize;
150 template<
class traits_t>
151 void sbo_bytes<traits_t>::reallocate_to_small(size_type nNewSize) noexcept
153 if constexpr (bPreserveContents)
156 std::memcpy(buff.data(), m_Data.pData, std::min(nNewSize, capacity()));
158 m_Data.buffer = buff;
166 template<
class traits_t>
167 QX_FORCE_INLINE sbo_bytes<traits_t>::size_type sbo_bytes<traits_t>::get_new_size(
168 size_type nRequestedSize)
const noexcept
170 const size_t nCapacity = capacity();
171 const size_t nAdvancedGrowth = traits_type::growth_strategy(nCapacity);
172 size_t nNewSize = nRequestedSize;
173 if (nCapacity < nRequestedSize && nRequestedSize < nAdvancedGrowth)
174 nNewSize = nAdvancedGrowth;
A type erased small buffer object that works with raw data.
QX_FORCE_INLINE size_type capacity() const noexcept
Get SBO capacity (bytes)
QX_FORCE_INLINE bool is_small() const noexcept
Is the SBO small and fits into the local buffer.
bool reserve(size_type nRequestedSize) noexcept
Make sure the capacity is at least nRequestedSize and allocate memory if needed, but do not change th...
bool shrink_to_fit() noexcept
Reduce capacity to fit the size, possibly moving data to the internal buffer if the size becomes smal...
void free() noexcept
Free allocated memory.
QX_FORCE_INLINE std::byte * data() noexcept
Get SBO data: from a buffer or from a heap.
QX_FORCE_INLINE size_type size() const noexcept
Get SBO size (bytes)
bool resize(size_type nRequestedSize) noexcept
Make sure the capacity is at least nRequestedSize and allocate memory if needed, and change the size ...
#define QX_FORCE_INLINE
Make this function forcefully inlined (except for QX_DEBUG build)
#define QX_CONST_CAST_THIS()
This macro is made for situations where you have a const method, and you need exactly the same method...