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 {
195 using ChunksType = multibuf_impl::Chunks<typename Deque::size_type>;
196 using ConstChunksType = multibuf_impl::ConstChunks<typename Deque::size_type>;
204 return ((kProperties == Property::kConst) || ...);
209 return ((kProperties == Property::kLayerable) || ...);
214 return ((kProperties == Property::kObservable) || ...);
217 using size_type =
typename Deque::size_type;
218 using difference_type =
typename Deque::difference_type;
219 using iterator = multibuf_impl::ByteIterator<size_type,
false>;
220 using const_iterator =
221 multibuf_impl::ByteIterator<size_type,
true>;
222 using pointer = iterator::pointer;
223 using const_pointer = const_iterator::pointer;
224 using reference = iterator::reference;
225 using const_reference = const_iterator::reference;
226 using value_type = std::conditional_t<
is_const(),
227 const_iterator::value_type,
228 iterator::value_type>;
255 template <
Property... kOtherProperties>
260 template <
Property... kOtherProperties>
269 template <
typename OtherMultiBuf>
270 OtherMultiBuf& as() & {
271 multibuf_impl::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
272 return generic().
template as<OtherMultiBuf>();
275 template <
typename OtherMultiBuf>
276 const OtherMultiBuf& as() const& {
277 multibuf_impl::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
278 return generic().
template as<OtherMultiBuf>();
281 template <
typename OtherMultiBuf>
282 OtherMultiBuf&& as() && {
283 multibuf_impl::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
284 return std::move(generic().
template as<OtherMultiBuf>());
287 template <
typename OtherMultiBuf>
288 const OtherMultiBuf&& as() const&& {
289 multibuf_impl::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
290 return std::move(generic().
template as<OtherMultiBuf>());
293 template <
typename OtherMultiBuf,
294 typename = multibuf_impl::EnableIfConvertible<BasicMultiBuf,
296 operator OtherMultiBuf&() & {
297 return as<OtherMultiBuf>();
300 template <
typename OtherMultiBuf,
301 typename = multibuf_impl::EnableIfConvertible<BasicMultiBuf,
303 operator const OtherMultiBuf&()
const& {
304 return as<OtherMultiBuf>();
307 template <
typename OtherMultiBuf,
308 typename = multibuf_impl::EnableIfConvertible<BasicMultiBuf,
310 operator OtherMultiBuf&&() && {
311 return std::move(as<OtherMultiBuf>());
314 template <
typename OtherMultiBuf,
315 typename = multibuf_impl::EnableIfConvertible<BasicMultiBuf,
317 operator const OtherMultiBuf&&()
const&& {
318 return std::move(as<OtherMultiBuf>());
329 constexpr size_t size()
const {
return generic().
size(); }
342 template <
bool kMutable = !is_const()>
343 std::enable_if_t<kMutable, reference> at(
size_t index) {
344 return *(begin() +
static_cast<int>(index));
346 const_reference at(
size_t index)
const {
347 return *(begin() +
static_cast<int>(index));
350 template <
bool kMutable = !is_const()>
351 std::enable_if_t<kMutable, reference> operator[](
size_t index) {
354 const_reference operator[](
size_t index)
const {
return at(index); }
368 template <
bool kMutable = !is_const()>
369 constexpr std::enable_if_t<kMutable, ChunksType> Chunks() {
370 return generic().Chunks();
372 ConstChunksType Chunks()
const {
return generic().ConstChunks(); }
373 ConstChunksType ConstChunks()
const {
return generic().ConstChunks(); }
388 template <
bool kMutable = !is_const()>
389 constexpr std::enable_if_t<kMutable, iterator> begin() {
390 return generic().begin();
392 constexpr const_iterator begin()
const {
return cbegin(); }
393 constexpr const_iterator cbegin()
const {
return generic().cbegin(); }
406 template <
bool kMutable = !is_const()>
407 constexpr std::enable_if_t<kMutable, iterator> end() {
408 return generic().end();
410 constexpr const_iterator end()
const {
return cend(); }
411 constexpr const_iterator cend()
const {
return generic().cend(); }
441 bool IsCompatible(
const UniquePtr<
const std::byte[]>& bytes)
const {
454 bool IsCompatible(
const SharedPtr<std::byte[]>& bytes)
const {
457 bool IsCompatible(
const SharedPtr<
const std::byte[]>& bytes)
const {
481 template <Property... kOtherProperties>
497 int&... kExplicitGuard,
500 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
519 const_iterator pos,
const UniquePtr<
const std::byte[]>& bytes);
538 const_iterator pos,
const SharedPtr<
const std::byte[]>& bytes);
549 template <
Property... kOtherProperties>
561 int&... kExplicitGuard,
564 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
565 void Insert(const_iterator pos,
const T& bytes);
578 Insert(pos, std::move(bytes), 0);
580 void Insert(const_iterator pos,
UniquePtr<
const std::byte[]>&& bytes) {
581 Insert(pos, std::move(bytes), 0);
597 void Insert(const_iterator pos,
598 UniquePtr<std::byte[]>&& bytes,
600 size_t length = dynamic_extent);
601 void Insert(const_iterator pos,
602 UniquePtr<
const std::byte[]>&& bytes,
604 size_t length = dynamic_extent);
617 void Insert(const_iterator pos,
const SharedPtr<std::byte[]>& bytes) {
620 void Insert(const_iterator pos,
const SharedPtr<
const std::byte[]>& bytes) {
637 void Insert(const_iterator pos,
638 const SharedPtr<std::byte[]>& bytes,
640 size_t length = dynamic_extent);
641 void Insert(const_iterator pos,
642 const SharedPtr<
const std::byte[]>& bytes,
644 size_t length = dynamic_extent);
654 template <Property... kOtherProperties>
666 int&... kExplicitGuard,
669 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
683 const UniquePtr<
const std::byte[]>& bytes);
697 const SharedPtr<
const std::byte[]>& bytes);
707 template <
Property... kOtherProperties>
718 int&... kExplicitGuard,
721 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
752 void PushBack(UniquePtr<std::byte[]>&& bytes,
754 size_t length = dynamic_extent);
756 void PushBack(UniquePtr<
const std::byte[]>&& bytes,
758 size_t length = dynamic_extent);
771 void PushBack(
const SharedPtr<
const std::byte[]>& bytes) {
787 void PushBack(
const SharedPtr<std::byte[]>& bytes,
789 size_t length = dynamic_extent);
790 void PushBack(
const SharedPtr<
const std::byte[]>& bytes,
792 size_t length = dynamic_extent);
940 return generic().
CopyTo(dst, offset);
953 "`CopyFrom` may only be called on mutable MultiBufs");
954 return generic().
CopyFrom(src, offset);
974 return generic().
Get(copy, offset);
992 template <
int&... kExplicitGuard,
typename Visitor>
994 return visitor(
Get(copy, offset));
1012 "`observer` may only be called on observable MultiBufs");
1013 return generic().observer_;
1024 "`set_observer` may only be called on observable MultiBufs");
1038 "`NumFragments` may only be called on layerable MultiBufs");
1047 "`NumLayers` may only be called on layerable MultiBufs");
1059 size_t num_chunks = 1) {
1082 [[nodiscard]]
bool AddLayer(
size_t offset,
size_t length = dynamic_extent) {
1084 "`AddLayer` may only be called on layerable MultiBufs");
1085 return generic().
AddLayer(offset, length);
1092 "`SealTopLayer` may only be called on layerable MultiBufs");
1100 "`UnsealTopLayer` may only be called on layerable MultiBufs");
1108 "`IsTopLayerSealed` may only be called on layerable MultiBufs");
1123 "`TruncateTopLayer` may only be called on layerable MultiBufs");
1135 "`SetTopLayer` may only be called on mutable, layerable "
1137 PW_ASSERT(src.size() <=
size());
1152 "`PopLayer` may only be called on layerable MultiBufs");
1157 constexpr BasicMultiBuf() { multibuf_impl::PropertiesAreValid(); }
1160 template <Property...>
1161 friend class BasicMultiBuf;
1163 constexpr GenericMultiBuf&
generic() {
1164 return static_cast<GenericMultiBuf&
>(*this);
1166 constexpr const GenericMultiBuf&
generic()
const {
1167 return static_cast<const GenericMultiBuf&
>(*this);
1171namespace multibuf_impl {
1199 using ControlBlock = allocator::internal::ControlBlock;
1221 *
this = std::move(other);
1227 friend class ::pw::BasicMultiBuf;
1230 friend class ::pw::multibuf_impl::Instance;
1234 : deque_(allocator) {}
1236 template <
typename MultiBufType>
1237 MultiBufType& as() {
1241 template <
typename MultiBufType>
1242 const MultiBufType& as()
const {
1249 constexpr bool empty()
const {
return deque_.empty(); }
1252 constexpr size_t size()
const {
1253 return static_cast<size_t>(cend() - cbegin());
1257 constexpr bool has_deallocator()
const {
1258 return memory_tag_ == MemoryTag::kDeallocator || has_control_block();
1262 constexpr bool has_control_block()
const {
1263 return memory_tag_ == MemoryTag::kControlBlock;
1268 constexpr ChunksType Chunks() {
return ChunksType(deque_, depth_); }
1269 constexpr ConstChunksType ConstChunks()
const {
1270 return ConstChunksType(deque_, depth_);
1273 constexpr iterator begin() {
return iterator(Chunks().begin(), 0); }
1274 constexpr const_iterator cbegin()
const {
1275 return const_iterator(ConstChunks().cbegin(), 0);
1278 constexpr iterator end() {
return iterator(Chunks().end(), 0); }
1279 constexpr const_iterator cend()
const {
1280 return const_iterator(ConstChunks().cend(), 0);
1287 bool IsCompatible(
const Deallocator* other)
const;
1288 bool IsCompatible(
const ControlBlock* other)
const;
1291 [[nodiscard]]
bool TryReserveChunks(
size_t num_chunks);
1295 [[nodiscard]]
bool TryReserveForInsert(const_iterator pos,
1297 [[nodiscard]]
bool TryReserveForInsert(const_iterator pos,
size_t size);
1298 [[nodiscard]]
bool TryReserveForInsert(const_iterator pos,
1301 [[nodiscard]]
bool TryReserveForInsert(const_iterator pos,
1303 const ControlBlock* control_block);
1310 void Insert(const_iterator pos,
1315 void Insert(const_iterator pos,
1319 ControlBlock* control_block);
1323 [[nodiscard]]
bool IsRemovable(const_iterator pos,
size_t size)
const;
1335 [[nodiscard]]
bool IsReleasable(const_iterator pos)
const;
1341 [[nodiscard]]
bool IsShareable(const_iterator pos)
const;
1344 std::byte* Share(const_iterator pos);
1347 size_t CopyTo(
ByteSpan dst,
size_t offset)
const;
1361 size_type NumFragments()
const;
1364 constexpr size_type NumLayers()
const {
return depth_ - 1; }
1367 [[nodiscard]]
bool TryReserveLayers(
size_t num_layers,
size_t num_chunks = 1);
1370 [[nodiscard]]
bool AddLayer(
size_t offset,
size_t length = dynamic_extent);
1373 void SealTopLayer();
1376 void UnsealTopLayer();
1379 void TruncateTopLayer(
size_t length);
1393 static size_t CheckRange(
size_t offset,
size_t length,
size_t size);
1396 constexpr std::byte* GetData(size_type index)
const {
1397 return deque_[index].data;
1402 constexpr bool IsOwned(size_type index)
const {
1403 return deque_[index + 1].base_view.owned;
1408 constexpr bool IsShared(size_type index)
const {
1409 return deque_[index + 1].base_view.shared;
1413 constexpr bool IsSealed(size_type index)
const {
1414 return depth_ == 2 ? false : deque_[index + depth_ - 1].view.sealed;
1419 constexpr bool IsBoundary(size_type index)
const {
1420 return depth_ == 2 ? true : deque_[index + depth_ - 1].view.boundary;
1426 constexpr size_type GetOffset(size_type index, uint16_t layer)
const {
1427 return layer == 1 ? deque_[index + 1].base_view.offset
1428 : deque_[index + layer].view.offset;
1432 constexpr size_type GetOffset(size_type index)
const {
1433 return GetOffset(index, NumLayers());
1438 constexpr size_type GetRelativeOffset(size_type index)
const {
1439 uint16_t layer = NumLayers();
1441 return GetOffset(index, layer);
1443 return GetOffset(index, layer) - GetOffset(index, layer - 1);
1447 constexpr size_type GetLength(size_type index)
const {
1448 return depth_ == 2 ? deque_[index + 1].base_view.length
1449 : deque_[index + depth_ - 1].view.length;
1453 constexpr ByteSpan GetView(size_type index)
const {
1454 return ByteSpan(GetData(index) + GetOffset(index), GetLength(index));
1464 ControlBlock* GetControlBlock()
const;
1467 void SetControlBlock(ControlBlock* control_block);
1473 void ClearMemoryContext();
1478 std::pair<size_type, size_type> GetIndexAndOffset(const_iterator pos)
const;
1485 bool TryReserveEntries(const_iterator pos, size_type num_entries);
1486 bool TryReserveEntries(size_type num_entries,
bool split =
false);
1491 size_type InsertEntries(const_iterator pos, size_type num_entries);
1495 size_type Insert(const_iterator pos,
1509 void SplitBase(size_type index,
Deque& out_deque, size_type out_index);
1516 void SplitBefore(size_type index,
1519 size_type out_index);
1523 void SplitBefore(size_type index, size_type split);
1530 void SplitAfter(size_type index,
1533 size_type out_index);
1537 void SplitAfter(size_type index, size_type split);
1549 [[nodiscard]]
bool TryReserveForRemove(const_iterator pos,
1557 void CopyRange(const_iterator pos,
size_t size,
GenericMultiBuf& out);
1562 void ClearRange(const_iterator pos,
size_t size);
1568 void EraseRange(const_iterator pos,
size_t size);
1572 size_type FindShared(size_type index, size_type start);
1576 size_t CopyToImpl(
ByteSpan dst,
size_t offset, size_type start)
const;
1579 [[nodiscard]]
bool IsTopLayerSealed()
const;
1583 void SetLayer(
size_t offset,
size_t length);
1604 size_type depth_ = 2;
1622 enum class MemoryTag : uint8_t {
1626 } memory_tag_ = MemoryTag::kEmpty;
1628 union MemoryContext {
1630 ControlBlock* control_block;
1631 } memory_context_ = {.deallocator =
nullptr};
1657template <
typename MultiBufType>
1665 constexpr Instance(MultiBufType&& mb)
1668 constexpr Instance& operator=(MultiBufType&& mb) {
1673 MultiBufType* operator->() {
return &base_.as<MultiBufType>(); }
1674 const MultiBufType* operator->()
const {
return &base_.as<MultiBufType>(); }
1676 MultiBufType& operator*() & {
return base_.as<MultiBufType>(); }
1677 const MultiBufType& operator*()
const& {
return base_.as<MultiBufType>(); }
1679 MultiBufType&& operator*() && {
return std::move(base_.as<MultiBufType>()); }
1680 const MultiBufType&& operator*()
const&& {
1681 return std::move(base_.as<MultiBufType>());
1684 operator MultiBufType&() & {
return base_.as<MultiBufType>(); }
1685 operator const MultiBufType&()
const& {
return base_.as<MultiBufType>(); }
1687 operator MultiBufType&&() && {
return std::move(base_.as<MultiBufType>()); }
1688 operator const MultiBufType&&()
const&& {
1689 return std::move(base_.as<MultiBufType>());
1708 multibuf_impl::AssertIsConvertible<
BasicMultiBuf<kOtherProperties...>,
1710 return generic().TryReserveForInsert(pos,
1715template <
int&... kExplicitGuard,
typename T,
typename>
1718 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1719 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1720 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1721 return generic().TryReserveForInsert(pos, bytes.size());
1726 const_iterator pos,
const UniquePtr<std::byte[]>& bytes) {
1727 return generic().TryReserveForInsert(pos, bytes.size(), bytes.deallocator());
1732 const_iterator pos,
const UniquePtr<
const std::byte[]>& bytes) {
1733 static_assert(is_const(),
1734 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1735 return generic().TryReserveForInsert(pos, bytes.size(), bytes.deallocator());
1740 const_iterator pos,
const SharedPtr<std::byte[]>& bytes) {
1741 return generic().TryReserveForInsert(
1742 pos, bytes.size(), bytes.control_block());
1747 const_iterator pos,
const SharedPtr<
const std::byte[]>& bytes) {
1748 static_assert(is_const(),
1749 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1750 return generic().TryReserveForInsert(
1751 pos, bytes.size(), bytes.control_block());
1758 multibuf_impl::AssertIsConvertible<
BasicMultiBuf<kOtherProperties...>,
1760 generic().Insert(pos, std::move(mb.generic()));
1764template <
int&... kExplicitGuard,
typename T,
typename>
1766 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1767 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1768 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1769 generic().Insert(pos, bytes);
1778 generic().Insert(pos, chunk, offset, length, bytes.deallocator());
1784 UniquePtr<
const std::byte[]>&& bytes,
1787 static_assert(is_const(),
1788 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1789 ConstByteSpan chunk(bytes.get(), bytes.size());
1790 generic().Insert(pos, chunk, offset, length, bytes.deallocator());
1796 const SharedPtr<std::byte[]>& bytes,
1799 ConstByteSpan chunk(bytes.get(), bytes.size());
1800 generic().Insert(pos, chunk, offset, length, bytes.control_block());
1806 const SharedPtr<
const std::byte[]>& bytes,
1809 static_assert(is_const(),
1810 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1811 ConstByteSpan chunk(bytes.get(), bytes.size());
1812 generic().Insert(pos, chunk, offset, length, bytes.control_block());
1819 return TryReserveForInsert(end(), mb);
1823template <
int&... kExplicitGuard,
typename T,
typename>
1825 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1826 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1827 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1828 return TryReserveForInsert(end(), bytes);
1834 return TryReserveForInsert(end(), std::move(bytes));
1839 const UniquePtr<
const std::byte[]>& bytes) {
1840 static_assert(is_const(),
1841 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1842 return TryReserveForInsert(end(), std::move(bytes));
1847 const SharedPtr<std::byte[]>& bytes) {
1848 return TryReserveForInsert(end(), bytes);
1853 const SharedPtr<
const std::byte[]>& bytes) {
1854 static_assert(is_const(),
1855 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1856 return TryReserveForInsert(end(), bytes);
1863 Insert(end(), std::move(mb));
1867template <
int&... kExplicitGuard,
typename T,
typename>
1869 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1870 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1871 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1872 Insert(end(), bytes);
1879 Insert(end(), std::move(bytes), offset, length);
1884 UniquePtr<
const std::byte[]>&& bytes,
size_t offset,
size_t length) {
1885 static_assert(is_const(),
1886 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1887 Insert(end(), std::move(bytes), offset, length);
1892 const SharedPtr<std::byte[]>& bytes,
size_t offset,
size_t length) {
1893 Insert(end(), bytes, offset, length);
1898 const SharedPtr<
const std::byte[]>& bytes,
size_t offset,
size_t length) {
1899 static_assert(is_const(),
1900 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1901 Insert(end(), bytes, offset, length);
1905Result<multibuf_impl::Instance<BasicMultiBuf<kProperties...>>>
1907 auto result =
generic().Remove(pos, size);
1909 return result.status();
1911 return Instance(std::move(*result));
1919 return result.status();
1921 return Instance(std::move(*result));
1928 if constexpr (is_const()) {
1942 generic().GetControlBlock());
Definition: allocator.h:36
bool IsTopLayerSealed()
Returns whether the "sealed" flag is set in the top layer.
Definition: multibuf_v2.h:1105
bool AddLayer(size_t offset, size_t length=dynamic_extent)
Definition: multibuf_v2.h:1082
Result< Instance > Remove(const_iterator pos, size_t size)
Definition: multibuf_v2.h:1906
void Insert(const_iterator pos, BasicMultiBuf< kOtherProperties... > &&mb)
Definition: multibuf_v2.h:1756
bool TryReserveForPushBack(const T &bytes)
Definition: multibuf_v2.h:1824
void SealTopLayer()
Definition: multibuf_v2.h:1090
static constexpr bool is_layerable()
Returns whether additional views can be layered on the MultiBuf.
Definition: multibuf_v2.h:208
void UnsealTopLayer()
Definition: multibuf_v2.h:1098
SharedPtr< value_type[]> Share(const_iterator pos)
Definition: multibuf_v2.h:1940
void Insert(const_iterator pos, const T &bytes)
Definition: multibuf_v2.h:1765
void TruncateTopLayer(size_t length)
Definition: multibuf_v2.h:1120
void set_observer(MultiBufObserver *observer)
Definition: multibuf_v2.h:1022
void SetTopLayer(ConstByteSpan src)
Definition: multibuf_v2.h:1133
void PushBack(const T &bytes)
Definition: multibuf_v2.h:1868
static constexpr bool is_const()
Returns whether the MultiBuf data is immutable.
Definition: multibuf_v2.h:203
void PopLayer()
Definition: multibuf_v2.h:1150
void Clear()
Definition: multibuf_v2.h:1002
ConstByteSpan Get(ByteSpan copy, size_t offset=0) const
Definition: multibuf_v2.h:973
Result< Instance > PopFrontFragment()
Definition: multibuf_v2.h:1916
UniquePtr< value_type[]> Release(const_iterator pos)
Definition: multibuf_v2.h:1926
bool TryReserveChunks(size_t num_chunks)
Definition: multibuf_v2.h:464
size_t CopyTo(ByteSpan dst, size_t offset=0) const
Definition: multibuf_v2.h:939
size_t CopyFrom(ConstByteSpan src, size_t offset=0)
Definition: multibuf_v2.h:951
bool TryReserveForPushBack(const BasicMultiBuf< kOtherProperties... > &mb)
Definition: multibuf_v2.h:1817
static constexpr bool is_observable()
Returns whether an observer can be registered on the MultiBuf.
Definition: multibuf_v2.h:213
constexpr size_t size() const
Definition: multibuf_v2.h:329
bool TryReserveLayers(size_t num_layers, size_t num_chunks=1)
Definition: multibuf_v2.h:1058
bool IsShareable(const_iterator pos) const
Definition: multibuf_v2.h:911
constexpr size_type NumLayers() const
Definition: multibuf_v2.h:1045
constexpr bool empty() const
Definition: multibuf_v2.h:325
Result< const_iterator > Discard(const_iterator pos, size_t size)
Definition: multibuf_v2.h:881
bool IsReleasable(const_iterator pos) const
Definition: multibuf_v2.h:889
bool IsRemovable(const_iterator pos, size_t size) const
Definition: multibuf_v2.h:804
bool TryReserveForInsert(const_iterator pos, const BasicMultiBuf< kOtherProperties... > &mb)
Definition: multibuf_v2.h:1706
size_type NumFragments() const
Definition: multibuf_v2.h:1036
void PushBack(BasicMultiBuf< kOtherProperties... > &&mb)
Definition: multibuf_v2.h:1861
constexpr MultiBufObserver * observer() const
Definition: multibuf_v2.h:1010
auto Visit(Visitor visitor, ByteSpan copy, size_t offset)
Definition: multibuf_v2.h:993
bool TryReserveForInsert(const_iterator pos, const T &bytes)
Definition: multibuf_v2.h:1716
bool IsCompatible(const BasicMultiBuf &mb) const
Definition: multibuf_v2.h:425
Abstract interface for releasing memory.
Definition: deallocator.h:29
Definition: dynamic_deque.h:60
Definition: observer.h:29
Definition: shared_ptr.h:59
Definition: unique_ptr.h:43
element_type * Release() noexcept
Definition: unique_ptr.h:205
Deallocator * deallocator() const
Returns a pointer to the object that can destroy the value.
Definition: unique_ptr.h:137
size_t size() const
Definition: unique_ptr.h:130
Definition: multibuf_v2.h:1195
Definition: multibuf_v2.h:1658
MultiBufProperty
Basic properties of a MultiBuf.
Definition: properties.h:24
The Pigweed namespace.
Definition: alignment.h:27