C/C++ API Reference
Loading...
Searching...
No Matches
chunk_iterator.h
1// Copyright 2025 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 <cstddef>
17#include <cstdint>
18#include <iterator>
19
20#include "pw_assert/assert.h"
21#include "pw_bytes/span.h"
22#include "pw_containers/dynamic_deque.h"
23#include "pw_multibuf/internal/entry.h"
24#include "pw_preprocessor/compiler.h"
25
26namespace pw::multibuf {
27
28// Forward declarations.
29template <typename, typename>
31
32namespace internal {
33
42template <typename SizeType, bool kIsConst>
44 private:
45 using SpanType = std::conditional_t<kIsConst, ConstByteSpan, ByteSpan>;
46 using ByteType = typename SpanType::element_type;
47 using Deque = std::conditional_t<kIsConst,
50
51 public:
52 using size_type = SizeType;
53 using difference_type = std::ptrdiff_t;
54 using value_type = SpanType;
55 using pointer = value_type*;
56 using const_pointer = const value_type*;
57 using reference = value_type&;
58 using const_reference = const value_type&;
59 using iterator_category = std::bidirectional_iterator_tag;
60
61 constexpr ChunkIterator() = default;
62 constexpr ChunkIterator(const ChunkIterator& other) { *this = other; }
63 constexpr ChunkIterator& operator=(const ChunkIterator& other);
64
65 // Support converting non-const iterators to const_iterators.
66 constexpr operator ChunkIterator<SizeType, /*kIsConst=*/true>() const {
67 return {deque_, depth_, index_};
68 }
69
70 constexpr reference operator*() {
71 PW_ASSERT(is_valid());
72 return current_;
73 }
74
75 constexpr const_reference operator*() const {
76 PW_ASSERT(is_valid());
77 return current_;
78 }
79
80 constexpr pointer operator->() {
81 PW_ASSERT(is_valid());
82 return &current_;
83 }
84
85 constexpr const_pointer operator->() const {
86 PW_ASSERT(is_valid());
87 return &current_;
88 }
89
90 constexpr ChunkIterator& operator++();
91
92 constexpr ChunkIterator operator++(int) {
93 ChunkIterator previous(*this);
94 operator++();
95 return previous;
96 }
97
98 constexpr ChunkIterator& operator--();
99
100 constexpr ChunkIterator operator--(int) {
101 ChunkIterator previous(*this);
102 operator--();
103 return previous;
104 }
105
106 constexpr friend bool operator==(const ChunkIterator& lhs,
107 const ChunkIterator& rhs) {
108 return lhs.deque_ == rhs.deque_ && lhs.depth_ == rhs.depth_ &&
109 lhs.index_ == rhs.index_;
110 }
111
112 constexpr friend bool operator!=(const ChunkIterator& lhs,
113 const ChunkIterator& rhs) {
114 return !(lhs == rhs);
115 }
116
117 private:
118 // Iterators that point to something are created `Chunks` or `ConstChunks`.
119 template <typename, typename>
120 friend class ChunksImpl;
121
122 // Allow non-const iterators to construct const_iterators in conversions.
123 template <typename, bool>
124 friend class ChunkIterator;
125
126 // Byte iterators use chunk iterators to get contiguous spans.
127 template <typename, bool>
128 friend class ByteIterator;
129
130 constexpr ChunkIterator(Deque* deque, size_type depth, size_type index)
131 : deque_(deque), depth_(depth), index_(index) {
132 ResetCurrent();
133 }
134
135 constexpr bool is_valid() const {
136 return deque_ != nullptr && index_ < deque_->size();
137 }
138
139 constexpr ByteType* data(size_type index) const {
140 return (*deque_)[index].data + (*deque_)[index + depth_ - 1].view.offset;
141 }
142
143 constexpr size_t size(size_type index) const {
144 return (*deque_)[index + depth_ - 1].view.length;
145 }
146
147 constexpr void ResetCurrent();
148
149 Deque* deque_ = nullptr;
150 size_type depth_ = 0;
151 size_type index_ = 0;
152 SpanType current_;
153};
154
155// Template method implementations.
156
157template <typename SizeType, bool kIsConst>
160 deque_ = other.deque_;
161 depth_ = other.depth_;
162 index_ = other.index_;
163 ResetCurrent();
164 return *this;
165}
166
167template <typename SizeType, bool kIsConst>
168constexpr ChunkIterator<SizeType, kIsConst>&
169ChunkIterator<SizeType, kIsConst>::operator++() {
170 PW_ASSERT(is_valid());
171 size_t left = current_.size();
172 while (left != 0) {
173 left -= size(index_);
174 index_ += depth_;
175 }
176 while (index_ < deque_->size() && size(index_) == 0) {
177 index_ += depth_;
178 }
179 ResetCurrent();
180 return *this;
181}
182
183template <typename SizeType, bool kIsConst>
184constexpr ChunkIterator<SizeType, kIsConst>&
185ChunkIterator<SizeType, kIsConst>::operator--() {
186 PW_ASSERT(deque_ != nullptr);
187 PW_ASSERT(index_ != 0);
188 current_ = SpanType();
189 while (index_ != 0) {
190 SpanType prev(data(index_ - depth_), size(index_ - depth_));
191 if (!current_.empty() && prev.data() + prev.size() != current_.data()) {
192 break;
193 }
194 current_ = SpanType(prev.data(), prev.size() + current_.size());
195 index_ -= depth_;
196 }
197 return *this;
198}
199
200template <typename SizeType, bool kIsConst>
201constexpr void ChunkIterator<SizeType, kIsConst>::ResetCurrent() {
202 if (!is_valid()) {
203 current_ = SpanType();
204 return;
205 }
206 current_ = SpanType(data(index_), size(index_));
207 for (size_type i = index_; i < deque_->size() - depth_; i += depth_) {
208 SpanType next(data(i + depth_), size(i + depth_));
209 if (current_.empty()) {
210 current_ = next;
211 index_ += depth_;
212 continue;
213 }
214 if (current_.data() + current_.size() != next.data()) {
215 break;
216 }
217 current_ = SpanType(current_.data(), current_.size() + next.size());
218 }
219}
220
221} // namespace internal
222} // namespace pw::multibuf
Definition: dynamic_deque.h:60
Definition: chunk_iterator.h:30
Definition: byte_iterator.h:44
Definition: chunk_iterator.h:43
Base class for ranges of chunks.
Definition: chunks.h:30