C/C++ API Reference
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
27
28class MultiBuf;
29
31class PW_MULTIBUF_DEPRECATED MultiBufChunks {
32 public:
33 using element_type = Chunk;
34 using value_type = Chunk;
35 using pointer = Chunk*;
36 using reference = Chunk&;
37 using const_pointer = const Chunk*;
38 using difference_type = std::ptrdiff_t;
39 using const_reference = const Chunk&;
40 using size_type = std::size_t;
41
43 class iterator {
44 public:
45 using value_type = Chunk;
46 using difference_type = std::ptrdiff_t;
47 using reference = Chunk&;
48 using pointer = Chunk*;
49 using iterator_category = std::forward_iterator_tag;
50
51 constexpr iterator() = default;
52
53 constexpr reference operator*() const { return *chunk_; }
54 constexpr pointer operator->() const { return chunk_; }
55
56 constexpr iterator& operator++() {
57 chunk_ = chunk_->next_in_buf_;
58 return *this;
59 }
60
61 constexpr iterator operator++(int) {
62 iterator tmp = *this;
63 ++(*this);
64 return tmp;
65 }
66
67 constexpr bool operator==(const iterator& other) const {
68 return chunk_ == other.chunk_;
69 }
70
71 constexpr bool operator!=(const iterator& other) const {
72 return chunk_ != other.chunk_;
73 }
74
75 private:
76 friend class MultiBufChunks;
77 friend class MultiBuf;
78
79 constexpr iterator(Chunk* chunk) : chunk_(chunk) {}
80 static constexpr iterator end() { return iterator(nullptr); }
81 Chunk* chunk_ = nullptr;
82 };
83
86 public:
87 using value_type = const Chunk;
88 using difference_type = std::ptrdiff_t;
89 using reference = const Chunk&;
90 using pointer = const Chunk*;
91 using iterator_category = std::forward_iterator_tag;
92
93 constexpr const_iterator() = default;
94
95 constexpr reference operator*() const { return *chunk_; }
96 constexpr pointer operator->() const { return chunk_; }
97
98 constexpr const_iterator& operator++() {
99 chunk_ = chunk_->next_in_buf_;
100 return *this;
101 }
102
103 constexpr const_iterator operator++(int) {
104 const_iterator tmp = *this;
105 ++(*this);
106 return tmp;
107 }
108
109 constexpr bool operator==(const const_iterator& other) const {
110 return chunk_ == other.chunk_;
111 }
112
113 constexpr bool operator!=(const const_iterator& other) const {
114 return chunk_ != other.chunk_;
115 }
116
117 private:
118 friend class MultiBufChunks;
119 friend class MultiBuf;
120
121 constexpr const_iterator(const Chunk* chunk) : chunk_(chunk) {}
122 static constexpr const_iterator end() { return const_iterator(nullptr); }
123 const Chunk* chunk_ = nullptr;
124 };
125
126 MultiBufChunks(const MultiBufChunks&) = delete;
127 MultiBufChunks& operator=(const MultiBufChunks&) = delete;
128
132 constexpr Chunk& front() { return *first_; }
133 constexpr const Chunk& front() const { return *first_; }
134
140 Chunk& back() { return const_cast<Chunk&>(std::as_const(*this).back()); }
141 const Chunk& back() const;
142
143 constexpr iterator begin() { return iterator(first_); }
144 constexpr const_iterator begin() const { return cbegin(); }
145 constexpr const_iterator cbegin() const { return const_iterator(first_); }
146
147 constexpr iterator end() { return iterator::end(); }
148 constexpr const_iterator end() const { return cend(); }
149 constexpr const_iterator cend() const { return const_iterator::end(); }
150
152 size_t size() const {
153 return static_cast<size_t>(std::distance(begin(), end()));
154 }
155
157 size_t size_bytes() const;
158
160 [[nodiscard]] bool empty() const { return first_ == nullptr; }
161
165 void push_front(OwnedChunk&& chunk);
166
170 void push_back(OwnedChunk&& chunk);
171
176
183 //
184 // Implementation note: `Chunks().size()` should be remain relatively small,
185 // but this could be made `O(1)` in the future by adding a `prev` pointer to
186 // the `iterator`.
187 iterator insert(iterator position, OwnedChunk&& chunk);
188
195 //
196 // Implementation note: `Chunks().size()` should be remain relatively small,
197 // but this could be made `O(1)` in the future by adding a `prev` pointer to
198 // the `iterator`.
199 std::tuple<iterator, OwnedChunk> take(iterator position);
200
201 protected:
202 explicit constexpr MultiBufChunks(Chunk* first_chunk) : first_(first_chunk) {}
203
205 ~MultiBufChunks() { Release(); }
206
207 // Disable maybe-uninitialized: this check fails erroneously on Windows GCC.
209 PW_MODIFY_DIAGNOSTIC_GCC(ignored, "-Wmaybe-uninitialized");
210 constexpr MultiBufChunks(MultiBufChunks&& other) noexcept
211 : first_(other.first_) {
212 other.first_ = nullptr;
213 }
215
216 MultiBufChunks& operator=(MultiBufChunks&& other) noexcept {
217 Release();
218 first_ = other.first_;
219 other.first_ = nullptr;
220 return *this;
221 }
222
223 // Releases all chunks in the `MultiBuf`.
224 void Release() noexcept;
225
226 void PushSuffix(MultiBufChunks&& tail);
227
235 Chunk* Previous(Chunk* chunk) const;
236
237 private:
238 Chunk* first_;
239};
240
248class PW_MULTIBUF_DEPRECATED MultiBuf : private MultiBufChunks {
249 public:
250 class iterator;
251 class const_iterator;
252
253 constexpr MultiBuf() : MultiBufChunks(nullptr) {}
254
255 static MultiBuf FromChunk(OwnedChunk&& chunk) {
256 return MultiBuf(std::move(chunk).Take());
257 }
258
259 MultiBuf(const MultiBuf&) = delete;
260 MultiBuf& operator=(const MultiBuf&) = delete;
261
262 constexpr MultiBuf(MultiBuf&& other) noexcept = default;
263
264 MultiBuf& operator=(MultiBuf&& other) noexcept = default;
265
274 void Release() noexcept { MultiBufChunks::Release(); }
275
277 ~MultiBuf() = default;
278
282 [[nodiscard]] size_t size() const { return MultiBufChunks::size_bytes(); }
283
288 [[nodiscard]] bool empty() const;
289
296 [[nodiscard]] bool IsContiguous() const {
297 return ContiguousSpan().has_value();
298 }
299
308 std::optional<ByteSpan> ContiguousSpan() {
309 auto result = std::as_const(*this).ContiguousSpan();
310 if (result.has_value()) {
311 return span(const_cast<std::byte*>(result->data()), result->size());
312 }
313 return std::nullopt;
314 }
315 std::optional<ConstByteSpan> ContiguousSpan() const;
316
318 iterator begin() { return iterator(Chunks().begin().chunk_); }
321 return const_iterator(Chunks().begin().chunk_);
322 }
325 return const_iterator(Chunks().begin().chunk_);
326 }
327
329 iterator end() { return iterator::end(); }
331 const_iterator end() const { return const_iterator::end(); }
333 const_iterator cend() const { return const_iterator::end(); }
334
343 [[nodiscard]] bool ClaimPrefix(size_t bytes_to_claim);
344
353 [[nodiscard]] bool ClaimSuffix(size_t bytes_to_claim);
354
363 void DiscardPrefix(size_t bytes_to_discard);
364
373 void Slice(size_t begin, size_t end);
374
382 void Truncate(size_t len);
383
391
400 std::optional<MultiBuf> TakePrefix(size_t bytes_to_take);
401
410 std::optional<MultiBuf> TakeSuffix(size_t bytes_to_take);
411
415 void PushPrefix(MultiBuf&& front);
416
420 void PushSuffix(MultiBuf&& tail) {
421 return MultiBufChunks::PushSuffix(std::move(tail.Chunks()));
422 }
423
436 StatusWithSize CopyTo(ByteSpan dest, size_t position = 0) const;
437
449 StatusWithSize CopyFrom(ConstByteSpan source, size_t position = 0) {
450 return CopyFromAndOptionallyTruncate(source, position, /*truncate=*/false);
451 }
452
473 size_t position = 0) {
474 return CopyFromAndOptionallyTruncate(source, position, /*truncate=*/true);
475 }
476
478 //--------------------- Chunk manipulation ----------------------//
480
483 MultiBufChunks::push_front(std::move(chunk));
484 }
485
487 void PushBackChunk(OwnedChunk&& chunk) {
488 MultiBufChunks::push_back(std::move(chunk));
489 }
490
492 OwnedChunk TakeFrontChunk() { return MultiBufChunks::take_front(); }
493
496 OwnedChunk&& chunk) {
497 return MultiBufChunks::insert(position, std::move(chunk));
498 }
499
501 std::tuple<MultiBufChunks::iterator, OwnedChunk> TakeChunk(
502 MultiBufChunks::iterator position) {
503 return MultiBufChunks::take(position);
504 }
505
507 constexpr MultiBufChunks& Chunks() { return *this; }
508
510 constexpr const MultiBufChunks& Chunks() const { return *this; }
511
513 constexpr const MultiBufChunks& ConstChunks() const { return *this; }
514
516 //--------------------- Iterator details ------------------------//
518
519 using element_type = std::byte;
520 using value_type = std::byte;
521 using pointer = std::byte*;
522 using const_pointer = const std::byte*;
523 using reference = std::byte&;
524 using const_reference = const std::byte&;
525 using difference_type = std::ptrdiff_t;
526 using size_type = std::size_t;
527
530 public:
531 using value_type = std::byte;
532 using difference_type = std::ptrdiff_t;
533 using reference = const std::byte&;
534 using pointer = const std::byte*;
535 using iterator_category = std::forward_iterator_tag;
536
537 constexpr const_iterator() : chunk_(nullptr), byte_index_(0) {}
538
539 reference operator*() const { return (*chunk_)[byte_index_]; }
540 pointer operator->() const { return &(*chunk_)[byte_index_]; }
541
542 const_iterator& operator++();
543 const_iterator operator++(int) {
544 const_iterator tmp = *this;
545 ++(*this);
546 return tmp;
547 }
548 const_iterator operator+(size_t rhs) const {
549 const_iterator tmp = *this;
550 tmp += rhs;
551 return tmp;
552 }
553 const_iterator& operator+=(size_t advance);
554
555 constexpr bool operator==(const const_iterator& other) const {
556 return chunk_ == other.chunk_ && byte_index_ == other.byte_index_;
557 }
558
559 constexpr bool operator!=(const const_iterator& other) const {
560 return !(*this == other);
561 }
562
564 constexpr const Chunk* chunk() const { return chunk_; }
565
568 constexpr size_t byte_index() const { return byte_index_; }
569
570 private:
571 friend class MultiBuf;
572
573 explicit constexpr const_iterator(const Chunk* chunk, size_t byte_index = 0)
574 : chunk_(chunk), byte_index_(byte_index) {
575 AdvanceToData();
576 }
577
578 static const_iterator end() { return const_iterator(nullptr); }
579
580 constexpr void AdvanceToData() {
581 while (chunk_ != nullptr && chunk_->empty()) {
582 chunk_ = chunk_->next_in_buf_;
583 }
584 }
585
586 const Chunk* chunk_;
587 size_t byte_index_;
588 };
589
591 class iterator {
592 public:
593 using value_type = std::byte;
594 using difference_type = std::ptrdiff_t;
595 using reference = std::byte&;
596 using pointer = std::byte*;
597 using iterator_category = std::forward_iterator_tag;
598
599 constexpr iterator() = default;
600
601 reference operator*() const { return const_cast<std::byte&>(*const_iter_); }
602 pointer operator->() const { return const_cast<std::byte*>(&*const_iter_); }
603
604 iterator& operator++() {
605 const_iter_++;
606 return *this;
607 }
608 iterator operator++(int) {
609 iterator tmp = *this;
610 ++(*this);
611 return tmp;
612 }
613 iterator operator+(size_t rhs) const {
614 iterator tmp = *this;
615 tmp += rhs;
616 return tmp;
617 }
618 iterator& operator+=(size_t rhs) {
619 const_iter_ += rhs;
620 return *this;
621 }
622 constexpr bool operator==(const iterator& other) const {
623 return const_iter_ == other.const_iter_;
624 }
625 constexpr bool operator!=(const iterator& other) const {
626 return const_iter_ != other.const_iter_;
627 }
628
630 constexpr Chunk* chunk() const {
631 return const_cast<Chunk*>(const_iter_.chunk());
632 }
633
636 constexpr size_t byte_index() const { return const_iter_.byte_index(); }
637
638 private:
639 friend class MultiBuf;
640
641 explicit constexpr iterator(Chunk* chunk, size_t byte_index = 0)
642 : const_iter_(chunk, byte_index) {}
643
644 static iterator end() { return iterator(nullptr); }
645
646 const_iterator const_iter_;
647 };
648
649 private:
650 explicit constexpr MultiBuf(Chunk* first_chunk)
651 : MultiBufChunks(first_chunk) {}
652
653 StatusWithSize CopyFromAndOptionallyTruncate(ConstByteSpan source,
654 size_t position,
655 bool truncate);
656};
657
659
660} // namespace pw::multibuf
Definition: status_with_size.h:51
Definition: chunk.h:50
A const std::forward_iterator over the bytes of a MultiBuf.
Definition: multibuf_v1.h:529
constexpr size_t byte_index() const
Definition: multibuf_v1.h:568
constexpr const Chunk * chunk() const
Returns the current Chunk pointed to by this iterator.
Definition: multibuf_v1.h:564
An std::forward_iterator over the bytes of a MultiBuf.
Definition: multibuf_v1.h:591
constexpr size_t byte_index() const
Definition: multibuf_v1.h:636
constexpr Chunk * chunk() const
Returns the current Chunk pointed to by this iterator.
Definition: multibuf_v1.h:630
A const std::forward_iterator over the Chunks of a MultiBuf.
Definition: multibuf_v1.h:85
A std::forward_iterator over the Chunks of a MultiBuf.
Definition: multibuf_v1.h:43
A Chunk-oriented view of a MultiBuf.
Definition: multibuf_v1.h:31
bool empty() const
Returns whether the MultiBuf contains any chunks (size() == 0).
Definition: multibuf_v1.h:160
constexpr Chunk & front()
Definition: multibuf_v1.h:132
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:140
~MultiBufChunks()
This destructor will acquire a mutex and is not IRQ safe.
Definition: multibuf_v1.h:205
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:152
Definition: multibuf_v1.h:248
~MultiBuf()=default
This destructor will acquire a mutex and is not IRQ safe.
void PushBackChunk(OwnedChunk &&chunk)
Definition: multibuf_v1.h:487
constexpr MultiBufChunks & Chunks()
Returns a Chunk-oriented view of this MultiBuf.
Definition: multibuf_v1.h:507
void Release() noexcept
Definition: multibuf_v1.h:274
MultiBufChunks::iterator InsertChunk(MultiBufChunks::iterator position, OwnedChunk &&chunk)
Definition: multibuf_v1.h:495
const_iterator cbegin() const
Returns a const iterator pointing to the first byte of this MultiBuf.
Definition: multibuf_v1.h:324
void PushSuffix(MultiBuf &&tail)
Definition: multibuf_v1.h:420
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:482
const_iterator begin() const
Returns a const iterator pointing to the first byte of this MultiBuf.
Definition: multibuf_v1.h:320
const_iterator end() const
Returns a const iterator pointing to the end of this MultiBuf.
Definition: multibuf_v1.h:331
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:318
StatusWithSize CopyFromAndTruncate(ConstByteSpan source, size_t position=0)
Definition: multibuf_v1.h:472
bool IsContiguous() const
Definition: multibuf_v1.h:296
constexpr const MultiBufChunks & ConstChunks() const
Returns a const Chunk-oriented view of this MultiBuf.
Definition: multibuf_v1.h:513
void Truncate(size_t len)
iterator end()
Returns an iterator pointing to the end of this MultiBuf.
Definition: multibuf_v1.h:329
StatusWithSize CopyFrom(ConstByteSpan source, size_t position=0)
Definition: multibuf_v1.h:449
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:501
OwnedChunk TakeFrontChunk()
Definition: multibuf_v1.h:492
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:510
std::optional< ByteSpan > ContiguousSpan()
Definition: multibuf_v1.h:308
void PushPrefix(MultiBuf &&front)
const_iterator cend() const
Returns a const iterator pointing to the end of this MultiBuf.
Definition: multibuf_v1.h:333
size_t size() const
Definition: multibuf_v1.h:282
void Slice(size_t begin, size_t end)
Definition: chunk.h:326
Definition: span_impl.h:235
BasicMultiBuf< MultiBufProperty::kLayerable > MultiBuf
Definition: multibuf_v2.h:63
#define PW_MODIFY_DIAGNOSTICS_POP()
Definition: compiler.h:194
#define PW_MODIFY_DIAGNOSTIC_GCC(kind, option)
Definition: compiler.h:211
#define PW_MODIFY_DIAGNOSTICS_PUSH()
Definition: compiler.h:189