26#include "pw_allocator/allocator.h"
27#include "pw_allocator/null_allocator.h"
28#include "pw_bytes/span.h"
29#include "pw_containers/dynamic_deque.h"
30#include "pw_multibuf/chunks.h"
31#include "pw_multibuf/internal/byte_iterator.h"
32#include "pw_multibuf/internal/entry.h"
33#include "pw_multibuf/observer.h"
34#include "pw_multibuf/properties.h"
82namespace multibuf::internal {
206 using size_type =
typename Deque::size_type;
207 using difference_type =
typename Deque::difference_type;
210 using const_iterator =
212 using pointer = iterator::pointer;
213 using const_pointer = const_iterator::pointer;
214 using reference = iterator::reference;
215 using const_reference = const_iterator::reference;
216 using value_type = std::conditional_t<
is_const(),
217 const_iterator::value_type,
218 iterator::value_type>;
247 InvalidCopyOrMove<>();
250 BasicMultiBuf& operator=(
const BasicMultiBuf&) { InvalidCopyOrMove<>(); }
253 BasicMultiBuf& operator=(
const BasicMultiBuf<kOtherProperties...>&) {
254 InvalidCopyOrMove<>();
257 BasicMultiBuf(BasicMultiBuf&&) { InvalidCopyOrMove<>(); }
259 BasicMultiBuf& operator=(BasicMultiBuf&&) { InvalidCopyOrMove<>(); }
263 template <
typename OtherMultiBuf>
264 constexpr OtherMultiBuf& as() & {
265 multibuf::internal::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
266 return generic().
template as<OtherMultiBuf>();
269 template <
typename OtherMultiBuf>
270 constexpr const OtherMultiBuf& as() const& {
271 multibuf::internal::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
272 return generic().
template as<OtherMultiBuf>();
275 template <
typename OtherMultiBuf>
276 constexpr OtherMultiBuf&& as() && {
277 multibuf::internal::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
278 return std::move(generic().
template as<OtherMultiBuf>());
281 template <
typename OtherMultiBuf>
282 constexpr const OtherMultiBuf&& as() const&& {
283 multibuf::internal::AssertIsConvertible<BasicMultiBuf, OtherMultiBuf>();
284 return std::move(generic().
template as<OtherMultiBuf>());
287 template <
typename OtherMultiBuf,
288 typename = multibuf::internal::EnableIfConvertible<BasicMultiBuf,
290 constexpr operator OtherMultiBuf&() & {
291 return as<OtherMultiBuf>();
294 template <
typename OtherMultiBuf,
295 typename = multibuf::internal::EnableIfConvertible<BasicMultiBuf,
297 constexpr operator const OtherMultiBuf&()
const& {
298 return as<OtherMultiBuf>();
301 template <
typename OtherMultiBuf,
302 typename = multibuf::internal::EnableIfConvertible<BasicMultiBuf,
304 constexpr operator OtherMultiBuf&&() && {
305 return std::move(as<OtherMultiBuf>());
308 template <
typename OtherMultiBuf,
309 typename = multibuf::internal::EnableIfConvertible<BasicMultiBuf,
311 constexpr operator const OtherMultiBuf&&()
const&& {
312 return std::move(as<OtherMultiBuf>());
323 constexpr size_t size()
const {
return generic().
size(); }
336 template <
bool kMutable = !is_const()>
337 std::enable_if_t<kMutable, reference> at(
size_t index) {
338 return *(begin() +
static_cast<int>(index));
340 const_reference at(
size_t index)
const {
341 return *(begin() +
static_cast<int>(index));
344 template <
bool kMutable = !is_const()>
345 std::enable_if_t<kMutable, reference> operator[](
size_t index) {
348 const_reference operator[](
size_t index)
const {
return at(index); }
362 template <
bool kMutable = !is_const()>
363 constexpr std::enable_if_t<kMutable, multibuf::Chunks<Deque>> Chunks() {
364 return generic().Chunks();
366 constexpr multibuf::ConstChunks<Deque> Chunks()
const {
367 return generic().ConstChunks();
369 constexpr multibuf::ConstChunks<Deque> ConstChunks()
const {
370 return generic().ConstChunks();
386 template <
bool kMutable = !is_const()>
387 constexpr std::enable_if_t<kMutable, iterator> begin() {
388 return generic().begin();
390 constexpr const_iterator begin()
const {
return cbegin(); }
391 constexpr const_iterator cbegin()
const {
return generic().cbegin(); }
404 template <
bool kMutable = !is_const()>
405 constexpr std::enable_if_t<kMutable, iterator> end() {
406 return generic().end();
408 constexpr const_iterator end()
const {
return cend(); }
409 constexpr const_iterator cend()
const {
return generic().cend(); }
439 bool IsCompatible(
const UniquePtr<
const std::byte[]>& bytes)
const {
452 bool IsCompatible(
const SharedPtr<std::byte[]>& bytes)
const {
455 bool IsCompatible(
const SharedPtr<
const std::byte[]>& bytes)
const {
495 int&... kExplicitGuard,
498 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
559 int&... kExplicitGuard,
562 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
576 Insert(pos, std::move(bytes), 0);
578 void Insert(const_iterator pos,
UniquePtr<
const std::byte[]>&& bytes) {
579 Insert(pos, std::move(bytes), 0);
595 void Insert(const_iterator pos,
596 UniquePtr<std::byte[]>&& bytes,
598 size_t length = dynamic_extent);
599 void Insert(const_iterator pos,
600 UniquePtr<
const std::byte[]>&& bytes,
602 size_t length = dynamic_extent);
615 void Insert(const_iterator pos,
const SharedPtr<std::byte[]>& bytes) {
618 void Insert(const_iterator pos,
const SharedPtr<
const std::byte[]>& bytes) {
635 void Insert(const_iterator pos,
636 const SharedPtr<std::byte[]>& bytes,
638 size_t length = dynamic_extent);
639 void Insert(const_iterator pos,
640 const SharedPtr<
const std::byte[]>& bytes,
642 size_t length = dynamic_extent);
664 int&... kExplicitGuard,
667 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
681 const UniquePtr<
const std::byte[]>& bytes);
695 const SharedPtr<
const std::byte[]>& bytes);
716 int&... kExplicitGuard,
719 std::enable_if_t<std::is_constructible_v<ConstByteSpan, T>,
int>>
750 void PushBack(UniquePtr<std::byte[]>&& bytes,
752 size_t length = dynamic_extent);
754 void PushBack(UniquePtr<
const std::byte[]>&& bytes,
756 size_t length = dynamic_extent);
769 void PushBack(
const SharedPtr<
const std::byte[]>& bytes) {
785 void PushBack(
const SharedPtr<std::byte[]>& bytes,
787 size_t length = dynamic_extent);
788 void PushBack(
const SharedPtr<
const std::byte[]>& bytes,
790 size_t length = dynamic_extent);
921 return generic().
CopyTo(dst, offset);
934 "`CopyFrom` may only be called on mutable MultiBufs");
935 return generic().
CopyFrom(src, offset);
955 return generic().
Get(
copy, offset);
973 template <
int&... kExplicitGuard,
typename Visitor>
975 return visitor(
Get(
copy, offset));
1001 "`observer` may only be called on observable MultiBufs");
1002 return generic().observer_;
1013 "`set_observer` may only be called on observable MultiBufs");
1027 "`NumFragments` may only be called on layerable MultiBufs");
1036 "`NumLayers` may only be called on layerable MultiBufs");
1048 size_t num_chunks = 1) {
1071 [[nodiscard]]
bool AddLayer(
size_t offset,
size_t length = dynamic_extent) {
1073 "`AddLayer` may only be called on layerable MultiBufs");
1074 return generic().
AddLayer(offset, length);
1081 "`SealTopLayer` may only be called on layerable MultiBufs");
1089 "`UnsealTopLayer` may only be called on layerable MultiBufs");
1097 "`IsTopLayerSealed` may only be called on layerable MultiBufs");
1112 "`TruncateTopLayer` may only be called on layerable MultiBufs");
1124 "`SetTopLayer` may only be called on mutable, layerable "
1126 PW_ASSERT(src.size() <=
size());
1141 "`PopLayer` may only be called on layerable MultiBufs");
1146 constexpr BasicMultiBuf() { multibuf::internal::PropertiesAreValid(); }
1149 template <
bool kVal
idCopyOrMove = false>
1150 static constexpr void InvalidCopyOrMove() {
1151 static_assert(kValidCopyOrMove,
1152 "Only copies and moves from `BasicMultiBuf<...>::Instance`"
1153 "to `BasicMultiBuf<...>&` or another "
1154 "`BasicMultiBuf<...>::Instance` are valid.");
1158 friend class BasicMultiBuf;
1160 constexpr GenericMultiBuf&
generic() {
1161 return static_cast<GenericMultiBuf&
>(*this);
1163 constexpr const GenericMultiBuf&
generic()
const {
1164 return static_cast<const GenericMultiBuf&
>(*this);
1172namespace multibuf::internal {
1192 Property::kLayerable,
1193 Property::kObservable> {
1195 using ControlBlock = allocator::internal::ControlBlock;
1217 *
this = std::move(other);
1223 friend class ::pw::BasicMultiBuf;
1230 : deque_(allocator) {}
1232 template <
typename MultiBufType>
1233 constexpr MultiBufType& as() {
1237 template <
typename MultiBufType>
1238 constexpr const MultiBufType& as()
const {
1245 constexpr bool empty()
const {
return deque_.empty(); }
1248 constexpr size_t size()
const {
1249 return static_cast<size_t>(cend() - cbegin());
1253 constexpr bool has_deallocator()
const {
1254 return memory_tag_ == MemoryTag::kDeallocator || has_control_block();
1258 constexpr bool has_control_block()
const {
1259 return memory_tag_ == MemoryTag::kControlBlock;
1285 bool IsCompatible(
const Deallocator* other)
const;
1286 bool IsCompatible(
const ControlBlock* other)
const;
1289 [[nodiscard]]
bool TryReserveChunks(
size_t num_chunks);
1295 [[nodiscard]]
bool TryReserveForInsert(
const_iterator pos,
size_t size);
1301 const ControlBlock* control_block);
1317 ControlBlock* control_block);
1321 [[nodiscard]]
bool IsRemovable(
const_iterator pos,
size_t size)
const;
1345 size_t CopyTo(
ByteSpan dst,
size_t offset)
const;
1362 size_type NumFragments()
const;
1365 constexpr size_type NumLayers()
const {
return depth_ - 1; }
1368 [[nodiscard]]
bool TryReserveLayers(
size_t num_layers,
size_t num_chunks = 1);
1371 [[nodiscard]]
bool AddLayer(
size_t offset,
size_t length = dynamic_extent);
1374 void SealTopLayer();
1377 void UnsealTopLayer();
1380 void TruncateTopLayer(
size_t length);
1394 static size_t CheckRange(
size_t offset,
size_t length,
size_t size);
1397 constexpr std::byte* GetData(size_type index)
const {
1398 return deque_[index].data;
1403 constexpr bool IsOwned(size_type index)
const {
1404 return deque_[index + 1].base_view.owned;
1409 constexpr bool IsShared(size_type index)
const {
1410 return deque_[index + 1].base_view.shared;
1414 constexpr bool IsSealed(size_type index)
const {
1415 return depth_ == 2 ? false : deque_[index + depth_ - 1].view.sealed;
1420 constexpr bool IsBoundary(size_type index)
const {
1421 return depth_ == 2 ? true : deque_[index + depth_ - 1].view.boundary;
1427 constexpr size_type GetOffset(size_type index, uint16_t layer)
const {
1428 return layer == 1 ? deque_[index + 1].base_view.offset
1429 : deque_[index + layer].view.offset;
1433 constexpr size_type GetOffset(size_type index)
const {
1434 return GetOffset(index, NumLayers());
1439 constexpr size_type GetRelativeOffset(size_type index)
const {
1440 uint16_t layer = NumLayers();
1442 return GetOffset(index, layer);
1444 return GetOffset(index, layer) - GetOffset(index, layer - 1);
1448 constexpr size_type GetLength(size_type index)
const {
1449 return depth_ == 2 ? deque_[index + 1].base_view.length
1450 : deque_[index + depth_ - 1].view.length;
1454 constexpr ByteSpan GetView(size_type index)
const {
1455 return ByteSpan(GetData(index) + GetOffset(index), GetLength(index));
1465 ControlBlock* GetControlBlock()
const;
1468 void SetControlBlock(ControlBlock* control_block);
1474 void ClearMemoryContext();
1479 std::pair<size_type, size_type> GetIndexAndOffset(
const_iterator pos)
const;
1486 bool TryReserveEntries(
const_iterator pos, size_type num_entries);
1487 bool TryReserveEntries(size_type num_entries,
bool split =
false);
1492 size_type InsertEntries(
const_iterator pos, size_type num_entries);
1510 void SplitBase(size_type index,
Deque& out_deque, size_type out_index);
1517 void SplitBefore(size_type index,
1520 size_type out_index);
1524 void SplitBefore(size_type index, size_type split);
1531 void SplitAfter(size_type index,
1534 size_type out_index);
1538 void SplitAfter(size_type index, size_type split);
1573 size_type FindShared(size_type index, size_type start);
1577 size_t CopyToImpl(
ByteSpan dst,
size_t offset, size_type start)
const;
1580 [[nodiscard]]
bool IsTopLayerSealed()
const;
1584 void SetLayer(
size_t offset,
size_t length);
1605 size_type depth_ = 2;
1623 enum class MemoryTag : uint8_t {
1627 } memory_tag_ = MemoryTag::kEmpty;
1629 union MemoryContext {
1631 ControlBlock* control_block;
1632 } memory_context_ = {.deallocator =
nullptr};
1658template <
typename MultiBufType>
1681 constexpr Instance(MultiBufType&& mb)
1684 constexpr Instance& operator=(MultiBufType&& mb) {
1692 internal::AssertIsConvertible<
BasicMultiBuf<kProperties...>,
1698 internal::AssertIsConvertible<
BasicMultiBuf<kProperties...>,
1704 constexpr MultiBufType* operator->() {
return &base_.as<MultiBufType>(); }
1705 constexpr const MultiBufType* operator->()
const {
1706 return &base_.as<MultiBufType>();
1709 constexpr MultiBufType& operator*() & {
return base_.as<MultiBufType>(); }
1710 constexpr const MultiBufType& operator*()
const& {
1711 return base_.as<MultiBufType>();
1714 constexpr MultiBufType&& operator*() && {
1715 return std::move(base_.as<MultiBufType>());
1717 constexpr const MultiBufType&& operator*()
const&& {
1718 return std::move(base_.as<MultiBufType>());
1721 constexpr operator MultiBufType&() & {
return base_.as<MultiBufType>(); }
1722 constexpr operator const MultiBufType&()
const& {
1723 return base_.as<MultiBufType>();
1726 constexpr operator MultiBufType&&() && {
1727 return std::move(base_.as<MultiBufType>());
1729 constexpr operator const MultiBufType&&()
const&& {
1730 return std::move(base_.as<MultiBufType>());
1736 template <
bool kMoveOnly = false>
1737 static constexpr void MoveOnly() {
1738 static_assert(kMoveOnly,
1739 "Instances can only be created from existing MultiBufs using "
1740 "move-construction or move-assignment.");
1754 multibuf::internal::AssertIsConvertible<
BasicMultiBuf<kOtherProperties...>,
1756 return generic().TryReserveForInsert(pos,
1761template <
int&... kExplicitGuard,
typename T,
typename>
1764 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1765 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1766 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1767 return generic().TryReserveForInsert(pos, bytes.size());
1772 const_iterator pos,
const UniquePtr<std::byte[]>& bytes) {
1773 return generic().TryReserveForInsert(pos, bytes.size(), bytes.deallocator());
1778 const_iterator pos,
const UniquePtr<
const std::byte[]>& bytes) {
1779 static_assert(is_const(),
1780 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1781 return generic().TryReserveForInsert(pos, bytes.size(), bytes.deallocator());
1786 const_iterator pos,
const SharedPtr<std::byte[]>& bytes) {
1787 return generic().TryReserveForInsert(
1788 pos, bytes.size(), bytes.control_block());
1793 const_iterator pos,
const SharedPtr<
const std::byte[]>& bytes) {
1794 static_assert(is_const(),
1795 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1796 return generic().TryReserveForInsert(
1797 pos, bytes.size(), bytes.control_block());
1804 multibuf::internal::AssertIsConvertible<
BasicMultiBuf<kOtherProperties...>,
1806 generic().Insert(pos, std::move(mb.generic()));
1810template <
int&... kExplicitGuard,
typename T,
typename>
1812 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1813 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1814 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1815 generic().Insert(pos, bytes);
1824 generic().Insert(pos, chunk, offset, length, bytes.deallocator());
1830 UniquePtr<
const std::byte[]>&& bytes,
1833 static_assert(is_const(),
1834 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1835 ConstByteSpan chunk(bytes.get(), bytes.size());
1836 generic().Insert(pos, chunk, offset, length, bytes.deallocator());
1842 const SharedPtr<std::byte[]>& bytes,
1845 ConstByteSpan chunk(bytes.get(), bytes.size());
1846 generic().Insert(pos, chunk, offset, length, bytes.control_block());
1852 const SharedPtr<
const std::byte[]>& bytes,
1855 static_assert(is_const(),
1856 "Cannot `Insert` read-only bytes into mutable MultiBuf");
1857 ConstByteSpan chunk(bytes.get(), bytes.size());
1858 generic().Insert(pos, chunk, offset, length, bytes.control_block());
1865 return TryReserveForInsert(end(), mb);
1869template <
int&... kExplicitGuard,
typename T,
typename>
1871 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1872 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1873 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1874 return TryReserveForInsert(end(), bytes);
1880 return TryReserveForInsert(end(), std::move(bytes));
1885 const UniquePtr<
const std::byte[]>& bytes) {
1886 static_assert(is_const(),
1887 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1888 return TryReserveForInsert(end(), std::move(bytes));
1893 const SharedPtr<std::byte[]>& bytes) {
1894 return TryReserveForInsert(end(), bytes);
1899 const SharedPtr<
const std::byte[]>& bytes) {
1900 static_assert(is_const(),
1901 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1902 return TryReserveForInsert(end(), bytes);
1909 Insert(end(), std::move(mb));
1913template <
int&... kExplicitGuard,
typename T,
typename>
1915 using data_ptr_type =
decltype(std::data(std::declval<T&>()));
1916 static_assert(std::is_same_v<data_ptr_type, std::byte*> || is_const(),
1917 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1918 Insert(end(), bytes);
1925 Insert(end(), std::move(bytes), offset, length);
1930 UniquePtr<
const std::byte[]>&& bytes,
size_t offset,
size_t length) {
1931 static_assert(is_const(),
1932 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1933 Insert(end(), std::move(bytes), offset, length);
1938 const SharedPtr<std::byte[]>& bytes,
size_t offset,
size_t length) {
1939 Insert(end(), bytes, offset, length);
1944 const SharedPtr<
const std::byte[]>& bytes,
size_t offset,
size_t length) {
1945 static_assert(is_const(),
1946 "Cannot `PushBack` read-only bytes into mutable MultiBuf");
1947 Insert(end(), bytes, offset, length);
1951Result<multibuf::internal::Instance<BasicMultiBuf<kProperties...>>>
1953 auto result =
generic().Remove(pos, size);
1955 return result.status();
1957 return Instance(std::move(*result));
1963 auto result =
generic().PopFrontFragment();
1965 return result.status();
1967 return Instance(std::move(*result));
1974 if constexpr (is_const()) {
1988 generic().GetControlBlock());
Definition: allocator.h:43
bool IsTopLayerSealed()
Returns whether the "sealed" flag is set in the top layer.
Definition: multibuf_v2.h:1094
bool AddLayer(size_t offset, size_t length=dynamic_extent)
Definition: multibuf_v2.h:1071
void Insert(const_iterator pos, BasicMultiBuf< kOtherProperties... > &&mb)
Definition: multibuf_v2.h:1802
bool TryReserveForPushBack(const T &bytes)
Definition: multibuf_v2.h:1870
void SealTopLayer()
Definition: multibuf_v2.h:1079
static constexpr bool is_layerable()
Returns whether additional views can be layered on the MultiBuf.
Definition: multibuf_v2.h:197
void UnsealTopLayer()
Definition: multibuf_v2.h:1087
SharedPtr< value_type[]> Share(const_iterator pos)
Definition: multibuf_v2.h:1986
void Insert(const_iterator pos, const T &bytes)
Definition: multibuf_v2.h:1811
void TruncateTopLayer(size_t length)
Definition: multibuf_v2.h:1109
void SetTopLayer(ConstByteSpan src)
Definition: multibuf_v2.h:1122
void PushBack(const T &bytes)
Definition: multibuf_v2.h:1914
static constexpr bool is_const()
Returns whether the MultiBuf data is immutable.
Definition: multibuf_v2.h:192
void PopLayer()
Definition: multibuf_v2.h:1139
void Clear()
Definition: multibuf_v2.h:983
ConstByteSpan Get(ByteSpan copy, size_t offset=0) const
Definition: multibuf_v2.h:954
void set_observer(multibuf::Observer *observer)
Definition: multibuf_v2.h:1011
UniquePtr< value_type[]> Release(const_iterator pos)
Definition: multibuf_v2.h:1972
bool TryReserveChunks(size_t num_chunks)
Definition: multibuf_v2.h:462
size_t CopyTo(ByteSpan dst, size_t offset=0) const
Definition: multibuf_v2.h:920
size_t CopyFrom(ConstByteSpan src, size_t offset=0)
Definition: multibuf_v2.h:932
void ShrinkToFit()
Definition: multibuf_v2.h:991
constexpr multibuf::Observer * observer() const
Definition: multibuf_v2.h:999
bool TryReserveForPushBack(const BasicMultiBuf< kOtherProperties... > &mb)
Definition: multibuf_v2.h:1863
Result< Instance > PopFrontFragment()
Definition: multibuf_v2.h:1962
Result< Instance > Remove(const_iterator pos, size_t size)
Definition: multibuf_v2.h:1952
static constexpr bool is_observable()
Returns whether an observer can be registered on the MultiBuf.
Definition: multibuf_v2.h:202
constexpr size_t size() const
Definition: multibuf_v2.h:323
bool TryReserveLayers(size_t num_layers, size_t num_chunks=1)
Definition: multibuf_v2.h:1047
bool IsShareable(const_iterator pos) const
Definition: multibuf_v2.h:892
constexpr size_type NumLayers() const
Definition: multibuf_v2.h:1034
constexpr bool empty() const
Definition: multibuf_v2.h:319
Result< const_iterator > Discard(const_iterator pos, size_t size)
Definition: multibuf_v2.h:862
bool IsReleasable(const_iterator pos) const
Definition: multibuf_v2.h:870
bool IsRemovable(const_iterator pos, size_t size) const
Definition: multibuf_v2.h:802
bool TryReserveForInsert(const_iterator pos, const BasicMultiBuf< kOtherProperties... > &mb)
Definition: multibuf_v2.h:1752
size_type NumFragments() const
Definition: multibuf_v2.h:1025
void PushBack(BasicMultiBuf< kOtherProperties... > &&mb)
Definition: multibuf_v2.h:1907
auto Visit(Visitor visitor, ByteSpan copy, size_t offset)
Definition: multibuf_v2.h:974
bool TryReserveForInsert(const_iterator pos, const T &bytes)
Definition: multibuf_v2.h:1762
bool IsCompatible(const BasicMultiBuf &mb) const
Definition: multibuf_v2.h:423
Abstract interface for releasing memory.
Definition: deallocator.h:29
Definition: dynamic_deque.h:60
Definition: shared_ptr.h:63
Definition: unique_ptr.h:43
element_type * Release() noexcept
Definition: unique_ptr.h:252
Deallocator * deallocator() const
Returns a pointer to the object that can destroy the value.
Definition: unique_ptr.h:183
size_t size() const
Definition: unique_ptr.h:176
Definition: observer.h:29
Definition: byte_iterator.h:44
Definition: multibuf_v2.h:1193
Definition: multibuf_v2.h:1659
NullAllocator & GetNullAllocator()
Returns a reference to the NullAllocator singleton.
constexpr OutputIt copy(InputIt first, InputIt last, OutputIt d_first)
constexpr backport of <algorithm>'s std::copy for C++17.
Definition: algorithm.h:355
Property
Basic properties of a MultiBuf.
Definition: properties.h:25
Result(T value) -> Result< T >
Deduction guide to allow Result(v) rather than Result<T>(v).
The Pigweed namespace.
Definition: alignment.h:27