34#include "pw_allocator/allocator.h"
35#include "pw_bytes/span.h"
36#include "pw_containers/dynamic_deque.h"
37#include "pw_multibuf/internal/byte_iterator.h"
38#include "pw_multibuf/internal/chunk_iterator.h"
39#include "pw_multibuf/internal/entry.h"
40#include "pw_multibuf/observer.h"
41#include "pw_multibuf/properties.h"
42#include "pw_span/span.h"
50namespace multibuf_impl {
196 using ChunksType = multibuf_impl::Chunks<typename Deque::size_type>;
197 using ConstChunksType = multibuf_impl::ConstChunks<typename Deque::size_type>;
205 return ((kProperties == Property::kConst) || ...);
210 return ((kProperties == Property::kLayerable) || ...);
215 return ((kProperties == Property::kObservable) || ...);
218 using size_type =
typename Deque::size_type;
219 using difference_type =
typename Deque::difference_type;
220 using iterator = multibuf_impl::ByteIterator<size_type,
false>;
221 using const_iterator =
222 multibuf_impl::ByteIterator<size_type,
true>;
223 using pointer = iterator::pointer;
224 using const_pointer = const_iterator::pointer;
225 using reference = iterator::reference;
226 using const_reference = const_iterator::reference;
227 using value_type = std::conditional_t<
is_const(),
228 const_iterator::value_type,
229 iterator::value_type>;
256 template <
Property... kOtherProperties>
261 template <
Property... kOtherProperties>
266 template <
Property... kOtherProperties>
271 template <
Property... kOtherProperties>
276 template <
typename OtherMultiBuf>
277 OtherMultiBuf& as() {
278 multibuf_impl::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
279 return generic().
template as<OtherMultiBuf>();
282 template <
typename OtherMultiBuf>
283 const OtherMultiBuf& as()
const {
284 multibuf_impl::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
285 return generic().
template as<OtherMultiBuf>();
288 template <
typename OtherMultiBuf,
289 typename = multibuf_impl::EnableIfConvertible<BasicMultiBuf,
291 operator OtherMultiBuf&() {
292 return as<OtherMultiBuf>();
295 template <
typename OtherMultiBuf,
296 typename = multibuf_impl::EnableIfConvertible<BasicMultiBuf,
298 operator const OtherMultiBuf&()
const {
299 return as<OtherMultiBuf>();
310 constexpr size_t size()
const {
return generic().
size(); }
323 template <
bool kMutable = !is_const()>
324 std::enable_if_t<kMutable, reference> at(
size_t index) {
325 return *(begin() +
static_cast<int>(index));
327 const_reference at(
size_t index)
const {
328 return *(begin() +
static_cast<int>(index));
331 template <
bool kMutable = !is_const()>
332 std::enable_if_t<kMutable, reference> operator[](
size_t index) {
335 const_reference operator[](
size_t index)
const {
return at(index); }
349 template <
bool kMutable = !is_const()>
350 constexpr std::enable_if_t<kMutable, ChunksType> Chunks() {
351 return generic().Chunks();
353 ConstChunksType Chunks()
const {
return generic().ConstChunks(); }
354 ConstChunksType ConstChunks()
const {
return generic().ConstChunks(); }
369 template <
bool kMutable = !is_const()>
370 constexpr std::enable_if_t<kMutable, iterator> begin() {
371 return generic().begin();
373 constexpr const_iterator begin()
const {
return cbegin(); }
374 constexpr const_iterator cbegin()
const {
return generic().cbegin(); }
387 template <
bool kMutable = !is_const()>
388 constexpr std::enable_if_t<kMutable, iterator> end() {
389 return generic().end();
391 constexpr const_iterator end()
const {
return cend(); }
392 constexpr const_iterator cend()
const {
return generic().cend(); }
422 bool IsCompatible(
const UniquePtr<
const std::byte[]>& bytes)
const {
435 bool IsCompatible(
const SharedPtr<std::byte[]>& bytes)
const {
438 bool IsCompatible(
const SharedPtr<
const std::byte[]>& bytes)
const {
472 template <Property... kOtherProperties>
488 int&... kExplicitGuard,
491 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
510 const_iterator pos,
const UniquePtr<
const std::byte[]>& bytes);
529 const_iterator pos,
const SharedPtr<
const std::byte[]>& bytes);
540 template <
Property... kOtherProperties>
552 int&... kExplicitGuard,
555 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
556 void Insert(const_iterator pos,
const T& bytes);
569 Insert(pos, std::move(bytes), 0);
571 void Insert(const_iterator pos,
UniquePtr<
const std::byte[]>&& bytes) {
572 Insert(pos, std::move(bytes), 0);
588 void Insert(const_iterator pos,
589 UniquePtr<std::byte[]>&& bytes,
591 size_t length = dynamic_extent);
592 void Insert(const_iterator pos,
593 UniquePtr<
const std::byte[]>&& bytes,
595 size_t length = dynamic_extent);
608 void Insert(const_iterator pos,
const SharedPtr<std::byte[]>& bytes) {
611 void Insert(const_iterator pos,
const SharedPtr<
const std::byte[]>& bytes) {
628 void Insert(const_iterator pos,
629 const SharedPtr<std::byte[]>& bytes,
631 size_t length = dynamic_extent);
632 void Insert(const_iterator pos,
633 const SharedPtr<
const std::byte[]>& bytes,
635 size_t length = dynamic_extent);
645 template <Property... kOtherProperties>
657 int&... kExplicitGuard,
660 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
674 const UniquePtr<
const std::byte[]>& bytes);
688 const SharedPtr<
const std::byte[]>& bytes);
698 template <
Property... kOtherProperties>
709 int&... kExplicitGuard,
712 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
743 void PushBack(UniquePtr<std::byte[]>&& bytes,
745 size_t length = dynamic_extent);
747 void PushBack(UniquePtr<
const std::byte[]>&& bytes,
749 size_t length = dynamic_extent);
762 void PushBack(
const SharedPtr<
const std::byte[]>& bytes) {
778 void PushBack(
const SharedPtr<std::byte[]>& bytes,
780 size_t length = dynamic_extent);
781 void PushBack(
const SharedPtr<
const std::byte[]>& bytes,
783 size_t length = dynamic_extent);
930 size_t CopyTo(ByteSpan dst,
size_t offset = 0)
const {
931 return generic().
CopyTo(dst, offset);
942 size_t CopyFrom(ConstByteSpan src,
size_t offset = 0) {
944 "`CopyFrom` may only be called on mutable MultiBufs");
945 return generic().
CopyFrom(src, offset);
964 ConstByteSpan
Get(ByteSpan copy,
size_t offset = 0)
const {
965 return generic().
Get(copy, offset);
983 template <
int&... kExplicitGuard,
typename Visitor>
984 auto Visit(Visitor visitor, ByteSpan copy,
size_t offset) {
985 return visitor(
Get(copy, offset));
1003 "`observer` may only be called on observable MultiBufs");
1004 return generic().observer_;
1015 "`set_observer` may only be called on observable MultiBufs");
1029 "`NumFragments` may only be called on layerable MultiBufs");
1038 "`NumLayers` may only be called on layerable MultiBufs");
1061 [[nodiscard]]
bool AddLayer(
size_t offset,
size_t length = dynamic_extent) {
1063 "`AddLayer` may only be called on layerable MultiBufs");
1064 return generic().
AddLayer(offset, length);
1071 "`SealTopLayer` may only be called on layerable MultiBufs");
1079 "`UnsealTopLayer` may only be called on layerable MultiBufs");
1095 size_t length = dynamic_extent) {
1097 "`ResizeTopLayer` may only be called on layerable MultiBufs");
1112 "`PopLayer` may only be called on layerable MultiBufs");
1117 constexpr BasicMultiBuf() { multibuf_impl::PropertiesAreValid(); }
1120 template <Property...>
1121 friend class BasicMultiBuf;
1123 constexpr GenericMultiBuf&
generic() {
1124 return static_cast<GenericMultiBuf&
>(*this);
1126 constexpr const GenericMultiBuf&
generic()
const {
1127 return static_cast<const GenericMultiBuf&
>(*this);
1131namespace multibuf_impl {
1159 using ControlBlock = allocator::internal::ControlBlock;
1181 *
this = std::move(other);
1187 friend class ::pw::BasicMultiBuf;
1190 friend class ::pw::multibuf_impl::Instance;
1194 : deque_(allocator) {}
1196 template <
typename MultiBufType>
1197 MultiBufType& as() {
1201 template <
typename MultiBufType>
1202 const MultiBufType& as()
const {
1209 constexpr bool empty()
const {
return deque_.empty(); }
1212 constexpr size_t size()
const {
1213 return static_cast<size_t>(cend() - cbegin());
1217 constexpr bool has_deallocator()
const {
1218 return memory_tag_ == MemoryTag::kDeallocator || has_control_block();
1222 constexpr bool has_control_block()
const {
1223 return memory_tag_ == MemoryTag::kControlBlock;
1228 constexpr ChunksType Chunks() {
return ChunksType(deque_, depth_); }
1229 constexpr ConstChunksType ConstChunks()
const {
1230 return ConstChunksType(deque_, depth_);
1233 constexpr iterator begin() {
return iterator(Chunks().begin(), 0); }
1234 constexpr const_iterator cbegin()
const {
1235 return const_iterator(ConstChunks().cbegin(), 0);
1238 constexpr iterator end() {
return iterator(Chunks().end(), 0); }
1239 constexpr const_iterator cend()
const {
1240 return const_iterator(ConstChunks().cend(), 0);
1247 bool IsCompatible(
const Deallocator* other)
const;
1248 bool IsCompatible(
const ControlBlock* other)
const;
1251 [[nodiscard]]
bool TryReserveChunks(size_type num_chunks);
1255 [[nodiscard]]
bool TryReserveForInsert(const_iterator pos,
1257 [[nodiscard]]
bool TryReserveForInsert(const_iterator pos,
size_t size);
1258 [[nodiscard]]
bool TryReserveForInsert(const_iterator pos,
1261 [[nodiscard]]
bool TryReserveForInsert(const_iterator pos,
1263 const ControlBlock* control_block);
1269 void Insert(const_iterator pos, ConstByteSpan bytes);
1270 void Insert(const_iterator pos,
1271 ConstByteSpan bytes,
1275 void Insert(const_iterator pos,
1276 ConstByteSpan bytes,
1279 ControlBlock* control_block);
1283 [[nodiscard]]
bool IsRemovable(const_iterator pos,
size_t size)
const;
1286 Result<GenericMultiBuf> Remove(const_iterator pos,
size_t size);
1289 Result<GenericMultiBuf> PopFrontFragment();
1292 Result<const_iterator> Discard(const_iterator pos,
size_t size);
1295 [[nodiscard]]
bool IsReleasable(const_iterator pos)
const;
1301 [[nodiscard]]
bool IsShareable(const_iterator pos)
const;
1304 std::byte* Share(const_iterator pos);
1307 size_t CopyTo(ByteSpan dst,
size_t offset)
const;
1310 size_t CopyFrom(ConstByteSpan src,
size_t offset);
1313 ConstByteSpan Get(ByteSpan copy,
size_t offset)
const;
1321 size_type NumFragments()
const;
1324 constexpr size_type NumLayers()
const {
return depth_ - 1; }
1327 [[nodiscard]]
bool AddLayer(
size_t offset,
size_t length = dynamic_extent);
1330 void SealTopLayer();
1333 void UnsealTopLayer();
1336 [[nodiscard]]
bool ResizeTopLayer(
size_t offset,
1337 size_t length = dynamic_extent);
1340 [[nodiscard]]
bool PopLayer();
1351 static size_t CheckRange(
size_t offset,
size_t length,
size_t size);
1354 constexpr std::byte* GetData(size_type index)
const {
1355 return deque_[index].data;
1360 constexpr bool IsOwned(size_type index)
const {
1361 return deque_[index + 1].base_view.owned;
1366 constexpr bool IsShared(size_type index)
const {
1367 return deque_[index + 1].base_view.shared;
1371 constexpr bool IsSealed(size_type index)
const {
1372 return depth_ == 2 ? false : deque_[index + depth_ - 1].view.sealed;
1377 constexpr bool IsBoundary(size_type index)
const {
1378 return depth_ == 2 ? true : deque_[index + depth_ - 1].view.boundary;
1382 constexpr size_type GetOffset(size_type index)
const {
1383 return depth_ == 2 ? deque_[index + 1].base_view.offset
1384 : deque_[index + depth_ - 1].view.offset;
1388 constexpr size_type GetLength(size_type index)
const {
1389 return depth_ == 2 ? deque_[index + 1].base_view.length
1390 : deque_[index + depth_ - 1].view.length;
1394 constexpr ByteSpan GetView(size_type index)
const {
1395 return ByteSpan(GetData(index) + GetOffset(index), GetLength(index));
1405 ControlBlock* GetControlBlock()
const;
1408 void SetControlBlock(ControlBlock* control_block);
1414 void ClearMemoryContext();
1419 std::pair<size_type, size_type> GetIndexAndOffset(const_iterator pos)
const;
1426 bool TryReserveEntries(const_iterator pos, size_type num_entries);
1427 bool TryReserveEntries(size_type num_entries,
bool split =
false);
1432 size_type InsertEntries(const_iterator pos, size_type num_entries);
1436 size_type Insert(const_iterator pos,
1437 ConstByteSpan bytes,
1450 void SplitBase(size_type index,
Deque& out_deque, size_type out_index);
1457 void SplitBefore(size_type index,
1460 size_type out_index);
1464 void SplitBefore(size_type index, size_type split);
1471 void SplitAfter(size_type index,
1474 size_type out_index);
1478 void SplitAfter(size_type index, size_type split);
1490 [[nodiscard]]
bool TryReserveForRemove(const_iterator pos,
1498 void CopyRange(const_iterator pos,
size_t size,
GenericMultiBuf& out);
1503 void ClearRange(const_iterator pos,
size_t size);
1509 void EraseRange(const_iterator pos,
size_t size);
1513 size_type FindShared(size_type index, size_type start);
1517 size_t CopyToImpl(ByteSpan dst,
size_t offset, size_type start)
const;
1520 [[nodiscard]]
bool IsTopLayerSealed()
const;
1524 void SetLayer(
size_t offset,
size_t length);
1545 size_type depth_ = 2;
1563 enum class MemoryTag : uint8_t {
1567 } memory_tag_ = MemoryTag::kEmpty;
1569 union MemoryContext {
1571 ControlBlock* control_block;
1572 } memory_context_ = {.deallocator =
nullptr};
1598template <
typename MultiBufType>
1606 constexpr Instance(MultiBufType&& mb)
1609 constexpr Instance& operator=(MultiBufType&& mb) { base_ = std::move(mb); }
1611 MultiBufType& operator*() {
return base_.as<MultiBufType>(); }
1612 const MultiBufType& operator*()
const {
return base_.as<MultiBufType>(); }
1614 MultiBufType* operator->() {
return &base_.as<MultiBufType>(); }
1615 const MultiBufType* operator->()
const {
return &base_.as<MultiBufType>(); }
1617 operator MultiBufType&() {
return base_.as<MultiBufType>(); }
1618 operator const MultiBufType&()
const {
return base_.as<MultiBufType>(); }
1634 multibuf_impl::AssertIsConvertible<
BasicMultiBuf<kOtherProperties...>,
1636 return generic().TryReserveForInsert(pos,
1641template <
int&... kExplicitGuard,
typename T,
typename>
1644 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1645 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1646 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1647 return generic().TryReserveForInsert(pos, bytes.size());
1652 const_iterator pos,
const UniquePtr<std::byte[]>& bytes) {
1653 return generic().TryReserveForInsert(pos, bytes.size(), bytes.deallocator());
1658 const_iterator pos,
const UniquePtr<
const std::byte[]>& bytes) {
1659 static_assert(is_const(),
1660 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1661 return generic().TryReserveForInsert(pos, bytes.size(), bytes.deallocator());
1666 const_iterator pos,
const SharedPtr<std::byte[]>& bytes) {
1667 return generic().TryReserveForInsert(
1668 pos, bytes.size(), bytes.control_block());
1673 const_iterator pos,
const SharedPtr<
const std::byte[]>& bytes) {
1674 static_assert(is_const(),
1675 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1676 return generic().TryReserveForInsert(
1677 pos, bytes.size(), bytes.control_block());
1684 multibuf_impl::AssertIsConvertible<
BasicMultiBuf<kOtherProperties...>,
1686 generic().Insert(pos, std::move(mb.generic()));
1690template <
int&... kExplicitGuard,
typename T,
typename>
1692 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1693 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1694 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1695 generic().Insert(pos, bytes);
1703 ConstByteSpan chunk(bytes.get(), bytes.size());
1704 generic().Insert(pos, chunk, offset, length, bytes.deallocator());
1710 UniquePtr<
const std::byte[]>&& bytes,
1713 static_assert(is_const(),
1714 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1715 ConstByteSpan chunk(bytes.get(), bytes.size());
1716 generic().Insert(pos, chunk, offset, length, bytes.deallocator());
1722 const SharedPtr<std::byte[]>& bytes,
1725 ConstByteSpan chunk(bytes.get(), bytes.size());
1726 generic().Insert(pos, chunk, offset, length, bytes.control_block());
1732 const SharedPtr<
const std::byte[]>& bytes,
1735 static_assert(is_const(),
1736 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1737 ConstByteSpan chunk(bytes.get(), bytes.size());
1738 generic().Insert(pos, chunk, offset, length, bytes.control_block());
1745 return TryReserveForInsert(end(), mb);
1749template <
int&... kExplicitGuard,
typename T,
typename>
1751 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1752 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1753 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1754 return TryReserveForInsert(end(), bytes);
1760 return TryReserveForInsert(end(), std::move(bytes));
1765 const UniquePtr<
const std::byte[]>& bytes) {
1766 static_assert(is_const(),
1767 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1768 return TryReserveForInsert(end(), std::move(bytes));
1773 const SharedPtr<std::byte[]>& bytes) {
1774 return TryReserveForInsert(end(), bytes);
1779 const SharedPtr<
const std::byte[]>& bytes) {
1780 static_assert(is_const(),
1781 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1782 return TryReserveForInsert(end(), bytes);
1789 Insert(end(), std::move(mb));
1793template <
int&... kExplicitGuard,
typename T,
typename>
1795 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1796 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1797 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1798 Insert(end(), bytes);
1805 Insert(end(), std::move(bytes), offset, length);
1810 UniquePtr<
const std::byte[]>&& bytes,
size_t offset,
size_t length) {
1811 static_assert(is_const(),
1812 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1813 Insert(end(), std::move(bytes), offset, length);
1818 const SharedPtr<std::byte[]>& bytes,
size_t offset,
size_t length) {
1819 Insert(end(), bytes, offset, length);
1824 const SharedPtr<
const std::byte[]>& bytes,
size_t offset,
size_t length) {
1825 static_assert(is_const(),
1826 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1827 Insert(end(), bytes, offset, length);
1831Result<multibuf_impl::Instance<BasicMultiBuf<kProperties...>>>
1833 auto result =
generic().Remove(pos, size);
1835 return result.status();
1837 return Instance(std::move(*result));
1843 Result<GenericMultiBuf> result =
generic().PopFrontFragment();
1845 return result.status();
1847 return Instance(std::move(*result));
1854 if constexpr (is_const()) {
1868 generic().GetControlBlock());
Definition: allocator.h:34
bool AddLayer(size_t offset, size_t length=dynamic_extent)
Definition: multibuf_v2.h:1061
Result< Instance > Remove(const_iterator pos, size_t size)
Definition: multibuf_v2.h:1832
void Insert(const_iterator pos, BasicMultiBuf< kOtherProperties... > &&mb)
Definition: multibuf_v2.h:1682
bool TryReserveForPushBack(const T &bytes)
Definition: multibuf_v2.h:1750
void SealTopLayer()
Definition: multibuf_v2.h:1069
static constexpr bool is_layerable()
Returns whether additional views can be layered on the MultiBuf.
Definition: multibuf_v2.h:209
void UnsealTopLayer()
Definition: multibuf_v2.h:1077
SharedPtr< value_type[]> Share(const_iterator pos)
Definition: multibuf_v2.h:1866
void Insert(const_iterator pos, const T &bytes)
Definition: multibuf_v2.h:1691
bool TryReserveChunks(size_type num_chunks)
Definition: multibuf_v2.h:455
void set_observer(MultiBufObserver *observer)
Definition: multibuf_v2.h:1013
void PushBack(const T &bytes)
Definition: multibuf_v2.h:1794
static constexpr bool is_const()
Returns whether the MultiBuf data is immutable.
Definition: multibuf_v2.h:204
void Clear()
Definition: multibuf_v2.h:993
ConstByteSpan Get(ByteSpan copy, size_t offset=0) const
Definition: multibuf_v2.h:964
Result< Instance > PopFrontFragment()
Definition: multibuf_v2.h:1842
UniquePtr< value_type[]> Release(const_iterator pos)
Definition: multibuf_v2.h:1852
size_t CopyTo(ByteSpan dst, size_t offset=0) const
Definition: multibuf_v2.h:930
size_t CopyFrom(ConstByteSpan src, size_t offset=0)
Definition: multibuf_v2.h:942
bool TryReserveForPushBack(const BasicMultiBuf< kOtherProperties... > &mb)
Definition: multibuf_v2.h:1743
static constexpr bool is_observable()
Returns whether an observer can be registered on the MultiBuf.
Definition: multibuf_v2.h:214
constexpr size_t size() const
Definition: multibuf_v2.h:310
bool PopLayer()
Definition: multibuf_v2.h:1110
bool IsShareable(const_iterator pos) const
Definition: multibuf_v2.h:902
constexpr size_type NumLayers() const
Definition: multibuf_v2.h:1036
constexpr bool empty() const
Definition: multibuf_v2.h:306
Result< const_iterator > Discard(const_iterator pos, size_t size)
Definition: multibuf_v2.h:872
bool IsReleasable(const_iterator pos) const
Definition: multibuf_v2.h:880
bool IsRemovable(const_iterator pos, size_t size) const
Definition: multibuf_v2.h:795
bool TryReserveForInsert(const_iterator pos, const BasicMultiBuf< kOtherProperties... > &mb)
Definition: multibuf_v2.h:1632
size_type NumFragments() const
Definition: multibuf_v2.h:1027
void PushBack(BasicMultiBuf< kOtherProperties... > &&mb)
Definition: multibuf_v2.h:1787
bool ResizeTopLayer(size_t offset, size_t length=dynamic_extent)
Definition: multibuf_v2.h:1094
constexpr MultiBufObserver * observer() const
Definition: multibuf_v2.h:1001
auto Visit(Visitor visitor, ByteSpan copy, size_t offset)
Definition: multibuf_v2.h:984
bool TryReserveForInsert(const_iterator pos, const T &bytes)
Definition: multibuf_v2.h:1642
bool IsCompatible(const BasicMultiBuf &mb) const
Definition: multibuf_v2.h:406
Abstract interface for releasing memory.
Definition: deallocator.h:27
Definition: dynamic_deque.h:55
Definition: observer.h:27
Definition: shared_ptr.h:57
Definition: unique_ptr.h:41
element_type * Release() noexcept
Definition: unique_ptr.h:201
Deallocator * deallocator() const
Returns a pointer to the object that can destroy the value.
Definition: unique_ptr.h:135
size_t size() const
Definition: unique_ptr.h:128
Definition: multibuf_v2.h:1155
Definition: multibuf_v2.h:1599
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
MultiBufProperty
Basic properties of a MultiBuf.
Definition: properties.h:22