Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
multibuf_v1.h
1// Copyright 2023 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <iterator>
17#include <tuple>
18
19#include "pw_multibuf/chunk.h"
20#include "pw_multibuf/config.h"
21#include "pw_preprocessor/compiler.h"
22#include "pw_status/status_with_size.h"
23
24namespace pw::multibuf {
25
26class MultiBuf;
27
29class PW_MULTIBUF_DEPRECATED MultiBufChunks {
30 public:
31 using element_type = Chunk;
32 using value_type = Chunk;
33 using pointer = Chunk*;
34 using reference = Chunk&;
35 using const_pointer = const Chunk*;
36 using difference_type = std::ptrdiff_t;
37 using const_reference = const Chunk&;
38 using size_type = std::size_t;
39
41 class iterator {
42 public:
43 using value_type = Chunk;
44 using difference_type = std::ptrdiff_t;
45 using reference = Chunk&;
46 using pointer = Chunk*;
47 using iterator_category = std::forward_iterator_tag;
48
49 constexpr iterator() = default;
50
51 constexpr reference operator*() const { return *chunk_; }
52 constexpr pointer operator->() const { return chunk_; }
53
54 constexpr iterator& operator++() {
55 chunk_ = chunk_->next_in_buf_;
56 return *this;
57 }
58
59 constexpr iterator operator++(int) {
60 iterator tmp = *this;
61 ++(*this);
62 return tmp;
63 }
64
65 constexpr bool operator==(const iterator& other) const {
66 return chunk_ == other.chunk_;
67 }
68
69 constexpr bool operator!=(const iterator& other) const {
70 return chunk_ != other.chunk_;
71 }
72
73 private:
74 friend class MultiBufChunks;
75 friend class MultiBuf;
76
77 constexpr iterator(Chunk* chunk) : chunk_(chunk) {}
78 static constexpr iterator end() { return iterator(nullptr); }
79 Chunk* chunk_ = nullptr;
80 };
81
84 public:
85 using value_type = const Chunk;
86 using difference_type = std::ptrdiff_t;
87 using reference = const Chunk&;
88 using pointer = const Chunk*;
89 using iterator_category = std::forward_iterator_tag;
90
91 constexpr const_iterator() = default;
92
93 constexpr reference operator*() const { return *chunk_; }
94 constexpr pointer operator->() const { return chunk_; }
95
96 constexpr const_iterator& operator++() {
97 chunk_ = chunk_->next_in_buf_;
98 return *this;
99 }
100
101 constexpr const_iterator operator++(int) {
102 const_iterator tmp = *this;
103 ++(*this);
104 return tmp;
105 }
106
107 constexpr bool operator==(const const_iterator& other) const {
108 return chunk_ == other.chunk_;
109 }
110
111 constexpr bool operator!=(const const_iterator& other) const {
112 return chunk_ != other.chunk_;
113 }
114
115 private:
116 friend class MultiBufChunks;
117 friend class MultiBuf;
118
119 constexpr const_iterator(const Chunk* chunk) : chunk_(chunk) {}
120 static constexpr const_iterator end() { return const_iterator(nullptr); }
121 const Chunk* chunk_ = nullptr;
122 };
123
124 MultiBufChunks(const MultiBufChunks&) = delete;
125 MultiBufChunks& operator=(const MultiBufChunks&) = delete;
126
130 constexpr Chunk& front() { return *first_; }
131 constexpr const Chunk& front() const { return *first_; }
132
138 Chunk& back() { return const_cast<Chunk&>(std::as_const(*this).back()); }
139 const Chunk& back() const;
140
141 constexpr iterator begin() { return iterator(first_); }
142 constexpr const_iterator begin() const { return cbegin(); }
143 constexpr const_iterator cbegin() const { return const_iterator(first_); }
144
145 constexpr iterator end() { return iterator::end(); }
146 constexpr const_iterator end() const { return cend(); }
147 constexpr const_iterator cend() const { return const_iterator::end(); }
148
150 size_t size() const {
151 return static_cast<size_t>(std::distance(begin(), end()));
152 }
153
155 size_t size_bytes() const;
156
158 [[nodiscard]] bool empty() const { return first_ == nullptr; }
159
163 void push_front(OwnedChunk&& chunk);
164
168 void push_back(OwnedChunk&& chunk);
169
174
181 //
182 // Implementation note: `Chunks().size()` should be remain relatively small,
183 // but this could be made `O(1)` in the future by adding a `prev` pointer to
184 // the `iterator`.
185 iterator insert(iterator position, OwnedChunk&& chunk);
186
193 //
194 // Implementation note: `Chunks().size()` should be remain relatively small,
195 // but this could be made `O(1)` in the future by adding a `prev` pointer to
196 // the `iterator`.
197 std::tuple<iterator, OwnedChunk> take(iterator position);
198
199 protected:
200 explicit constexpr MultiBufChunks(Chunk* first_chunk) : first_(first_chunk) {}
201
203 ~MultiBufChunks() { Release(); }
204
205 // Disable maybe-uninitialized: this check fails erroneously on Windows GCC.
207 PW_MODIFY_DIAGNOSTIC_GCC(ignored, "-Wmaybe-uninitialized");
208 constexpr MultiBufChunks(MultiBufChunks&& other) noexcept
209 : first_(other.first_) {
210 other.first_ = nullptr;
211 }
213
214 MultiBufChunks& operator=(MultiBufChunks&& other) noexcept {
215 Release();
216 first_ = other.first_;
217 other.first_ = nullptr;
218 return *this;
219 }
220
221 // Releases all chunks in the `MultiBuf`.
222 void Release() noexcept;
223
224 void PushSuffix(MultiBufChunks&& tail);
225
233 Chunk* Previous(Chunk* chunk) const;
234
235 private:
236 Chunk* first_;
237};
238
246class PW_MULTIBUF_DEPRECATED MultiBuf : private MultiBufChunks {
247 public:
248 class iterator;
249 class const_iterator;
250
251 constexpr MultiBuf() : MultiBufChunks(nullptr) {}
252
253 static MultiBuf FromChunk(OwnedChunk&& chunk) {
254 return MultiBuf(std::move(chunk).Take());
255 }
256
257 MultiBuf(const MultiBuf&) = delete;
258 MultiBuf& operator=(const MultiBuf&) = delete;
259
260 constexpr MultiBuf(MultiBuf&& other) noexcept = default;
261
262 MultiBuf& operator=(MultiBuf&& other) noexcept = default;
263
272 void Release() noexcept { MultiBufChunks::Release(); }
273
275 ~MultiBuf() = default;
276
280 [[nodiscard]] size_t size() const { return MultiBufChunks::size_bytes(); }
281
286 [[nodiscard]] bool empty() const;
287
294 [[nodiscard]] bool IsContiguous() const {
295 return ContiguousSpan().has_value();
296 }
297
306 std::optional<ByteSpan> ContiguousSpan() {
307 auto result = std::as_const(*this).ContiguousSpan();
308 if (result.has_value()) {
309 return span(const_cast<std::byte*>(result->data()), result->size());
310 }
311 return std::nullopt;
312 }
313 std::optional<ConstByteSpan> ContiguousSpan() const;
314
316 iterator begin() { return iterator(Chunks().begin().chunk_); }
319 return const_iterator(Chunks().begin().chunk_);
320 }
323 return const_iterator(Chunks().begin().chunk_);
324 }
325
327 iterator end() { return iterator::end(); }
329 const_iterator end() const { return const_iterator::end(); }
331 const_iterator cend() const { return const_iterator::end(); }
332
341 [[nodiscard]] bool ClaimPrefix(size_t bytes_to_claim);
342
351 [[nodiscard]] bool ClaimSuffix(size_t bytes_to_claim);
352
361 void DiscardPrefix(size_t bytes_to_discard);
362
371 void Slice(size_t begin, size_t end);
372
380 void Truncate(size_t len);
381
389
398 std::optional<MultiBuf> TakePrefix(size_t bytes_to_take);
399
408 std::optional<MultiBuf> TakeSuffix(size_t bytes_to_take);
409
413 void PushPrefix(MultiBuf&& front);
414
418 void PushSuffix(MultiBuf&& tail) {
419 return MultiBufChunks::PushSuffix(std::move(tail.Chunks()));
420 }
421
440 StatusWithSize CopyTo(ByteSpan dest, size_t position = 0) const;
441
459 StatusWithSize CopyFrom(ConstByteSpan source, size_t position = 0) {
460 return CopyFromAndOptionallyTruncate(source, position, /*truncate=*/false);
461 }
462
491 size_t position = 0) {
492 return CopyFromAndOptionallyTruncate(source, position, /*truncate=*/true);
493 }
494
496 //--------------------- Chunk manipulation ----------------------//
498
501 MultiBufChunks::push_front(std::move(chunk));
502 }
503
505 void PushBackChunk(OwnedChunk&& chunk) {
506 MultiBufChunks::push_back(std::move(chunk));
507 }
508
510 OwnedChunk TakeFrontChunk() { return MultiBufChunks::take_front(); }
511
514 OwnedChunk&& chunk) {
515 return MultiBufChunks::insert(position, std::move(chunk));
516 }
517
519 std::tuple<MultiBufChunks::iterator, OwnedChunk> TakeChunk(
520 MultiBufChunks::iterator position) {
521 return MultiBufChunks::take(position);
522 }
523
525 constexpr MultiBufChunks& Chunks() { return *this; }
526
528 constexpr const MultiBufChunks& Chunks() const { return *this; }
529
531 constexpr const MultiBufChunks& ConstChunks() const { return *this; }
532
534 //--------------------- Iterator details ------------------------//
536
537 using element_type = std::byte;
538 using value_type = std::byte;
539 using pointer = std::byte*;
540 using const_pointer = const std::byte*;
541 using reference = std::byte&;
542 using const_reference = const std::byte&;
543 using difference_type = std::ptrdiff_t;
544 using size_type = std::size_t;
545
548 public:
549 using value_type = std::byte;
550 using difference_type = std::ptrdiff_t;
551 using reference = const std::byte&;
552 using pointer = const std::byte*;
553 using iterator_category = std::forward_iterator_tag;
554
555 constexpr const_iterator() : chunk_(nullptr), byte_index_(0) {}
556
557 reference operator*() const { return (*chunk_)[byte_index_]; }
558 pointer operator->() const { return &(*chunk_)[byte_index_]; }
559
560 const_iterator& operator++();
561 const_iterator operator++(int) {
562 const_iterator tmp = *this;
563 ++(*this);
564 return tmp;
565 }
566 const_iterator operator+(size_t rhs) const {
567 const_iterator tmp = *this;
568 tmp += rhs;
569 return tmp;
570 }
571 const_iterator& operator+=(size_t advance);
572
573 constexpr bool operator==(const const_iterator& other) const {
574 return chunk_ == other.chunk_ && byte_index_ == other.byte_index_;
575 }
576
577 constexpr bool operator!=(const const_iterator& other) const {
578 return !(*this == other);
579 }
580
582 constexpr const Chunk* chunk() const { return chunk_; }
583
586 constexpr size_t byte_index() const { return byte_index_; }
587
588 private:
589 friend class MultiBuf;
590
591 explicit constexpr const_iterator(const Chunk* chunk, size_t byte_index = 0)
592 : chunk_(chunk), byte_index_(byte_index) {
593 AdvanceToData();
594 }
595
596 static const_iterator end() { return const_iterator(nullptr); }
597
598 constexpr void AdvanceToData() {
599 while (chunk_ != nullptr && chunk_->empty()) {
600 chunk_ = chunk_->next_in_buf_;
601 }
602 }
603
604 const Chunk* chunk_;
605 size_t byte_index_;
606 };
607
609 class iterator {
610 public:
611 using value_type = std::byte;
612 using difference_type = std::ptrdiff_t;
613 using reference = std::byte&;
614 using pointer = std::byte*;
615 using iterator_category = std::forward_iterator_tag;
616
617 constexpr iterator() = default;
618
619 reference operator*() const { return const_cast<std::byte&>(*const_iter_); }
620 pointer operator->() const { return const_cast<std::byte*>(&*const_iter_); }
621
622 iterator& operator++() {
623 const_iter_++;
624 return *this;
625 }
626 iterator operator++(int) {
627 iterator tmp = *this;
628 ++(*this);
629 return tmp;
630 }
631 iterator operator+(size_t rhs) const {
632 iterator tmp = *this;
633 tmp += rhs;
634 return tmp;
635 }
636 iterator& operator+=(size_t rhs) {
637 const_iter_ += rhs;
638 return *this;
639 }
640 constexpr bool operator==(const iterator& other) const {
641 return const_iter_ == other.const_iter_;
642 }
643 constexpr bool operator!=(const iterator& other) const {
644 return const_iter_ != other.const_iter_;
645 }
646
648 constexpr Chunk* chunk() const {
649 return const_cast<Chunk*>(const_iter_.chunk());
650 }
651
654 constexpr size_t byte_index() const { return const_iter_.byte_index(); }
655
656 private:
657 friend class MultiBuf;
658
659 explicit constexpr iterator(Chunk* chunk, size_t byte_index = 0)
660 : const_iter_(chunk, byte_index) {}
661
662 static iterator end() { return iterator(nullptr); }
663
664 const_iterator const_iter_;
665 };
666
667 private:
668 explicit constexpr MultiBuf(Chunk* first_chunk)
669 : MultiBufChunks(first_chunk) {}
670
671 StatusWithSize CopyFromAndOptionallyTruncate(ConstByteSpan source,
672 size_t position,
673 bool truncate);
674};
675
676} // namespace pw::multibuf
Definition: status_with_size.h:49
Definition: chunk.h:48
A const std::forward_iterator over the bytes of a MultiBuf.
Definition: multibuf_v1.h:547
constexpr size_t byte_index() const
Definition: multibuf_v1.h:586
constexpr const Chunk * chunk() const
Returns the current Chunk pointed to by this iterator.
Definition: multibuf_v1.h:582
An std::forward_iterator over the bytes of a MultiBuf.
Definition: multibuf_v1.h:609
constexpr size_t byte_index() const
Definition: multibuf_v1.h:654
constexpr Chunk * chunk() const
Returns the current Chunk pointed to by this iterator.
Definition: multibuf_v1.h:648
A const std::forward_iterator over the Chunks of a MultiBuf.
Definition: multibuf_v1.h:83
A std::forward_iterator over the Chunks of a MultiBuf.
Definition: multibuf_v1.h:41
A Chunk-oriented view of a MultiBuf.
Definition: multibuf_v1.h:29
bool empty() const
Returns whether the MultiBuf contains any chunks (size() == 0).
Definition: multibuf_v1.h:158
constexpr Chunk & front()
Definition: multibuf_v1.h:130
std::tuple< iterator, OwnedChunk > take(iterator position)
void push_back(OwnedChunk &&chunk)
void push_front(OwnedChunk &&chunk)
iterator insert(iterator position, OwnedChunk &&chunk)
Chunk & back()
Definition: multibuf_v1.h:138
~MultiBufChunks()
This destructor will acquire a mutex and is not IRQ safe.
Definition: multibuf_v1.h:203
size_t size_bytes() const
Returns the total number of bytes in all Chunks.
size_t size() const
Returns the number of Chunks in this MultiBuf, including empty chunks.
Definition: multibuf_v1.h:150
Definition: multibuf_v1.h:246
~MultiBuf()=default
This destructor will acquire a mutex and is not IRQ safe.
void PushBackChunk(OwnedChunk &&chunk)
Definition: multibuf_v1.h:505
constexpr MultiBufChunks & Chunks()
Returns a Chunk-oriented view of this MultiBuf.
Definition: multibuf_v1.h:525
void Release() noexcept
Definition: multibuf_v1.h:272
MultiBufChunks::iterator InsertChunk(MultiBufChunks::iterator position, OwnedChunk &&chunk)
Definition: multibuf_v1.h:513
const_iterator cbegin() const
Returns a const iterator pointing to the first byte of this MultiBuf.
Definition: multibuf_v1.h:322
void PushSuffix(MultiBuf &&tail)
Definition: multibuf_v1.h:418
std::optional< MultiBuf > TakeSuffix(size_t bytes_to_take)
void TruncateAfter(iterator pos)
void DiscardPrefix(size_t bytes_to_discard)
void PushFrontChunk(OwnedChunk &&chunk)
Definition: multibuf_v1.h:500
const_iterator begin() const
Returns a const iterator pointing to the first byte of this MultiBuf.
Definition: multibuf_v1.h:318
const_iterator end() const
Returns a const iterator pointing to the end of this MultiBuf.
Definition: multibuf_v1.h:329
StatusWithSize CopyTo(ByteSpan dest, size_t position=0) const
iterator begin()
Returns an iterator pointing to the first byte of this MultiBuf.
Definition: multibuf_v1.h:316
StatusWithSize CopyFromAndTruncate(ConstByteSpan source, size_t position=0)
Definition: multibuf_v1.h:490
bool IsContiguous() const
Definition: multibuf_v1.h:294
constexpr const MultiBufChunks & ConstChunks() const
Returns a const Chunk-oriented view of this MultiBuf.
Definition: multibuf_v1.h:531
void Truncate(size_t len)
iterator end()
Returns an iterator pointing to the end of this MultiBuf.
Definition: multibuf_v1.h:327
StatusWithSize CopyFrom(ConstByteSpan source, size_t position=0)
Definition: multibuf_v1.h:459
bool ClaimSuffix(size_t bytes_to_claim)
std::optional< MultiBuf > TakePrefix(size_t bytes_to_take)
std::tuple< MultiBufChunks::iterator, OwnedChunk > TakeChunk(MultiBufChunks::iterator position)
Definition: multibuf_v1.h:519
OwnedChunk TakeFrontChunk()
Definition: multibuf_v1.h:510
bool ClaimPrefix(size_t bytes_to_claim)
constexpr const MultiBufChunks & Chunks() const
Returns a const Chunk-oriented view of this MultiBuf.
Definition: multibuf_v1.h:528
std::optional< ByteSpan > ContiguousSpan()
Definition: multibuf_v1.h:306
void PushPrefix(MultiBuf &&front)
const_iterator cend() const
Returns a const iterator pointing to the end of this MultiBuf.
Definition: multibuf_v1.h:331
size_t size() const
Definition: multibuf_v1.h:280
void Slice(size_t begin, size_t end)
Definition: chunk.h:324
BasicMultiBuf< MultiBufProperty::kLayerable > MultiBuf
Definition: multibuf_v2.h:72
#define PW_MODIFY_DIAGNOSTICS_POP()
Definition: compiler.h:191
#define PW_MODIFY_DIAGNOSTIC_GCC(kind, option)
Definition: compiler.h:208
#define PW_MODIFY_DIAGNOSTICS_PUSH()
Definition: compiler.h:186