20#include "pw_assert/assert.h"
21#include "pw_bytes/span.h"
22#include "pw_containers/dynamic_deque.h"
23#include "pw_multibuf/v2/internal/entry.h"
25namespace pw::multibuf::v2 {
44 using size_type = Entry::size_type;
45 using difference_type = Entry::difference_type;
46 using iterator_category = std::random_access_iterator_tag;
57 size_type entries_per_chunk,
61 entries_per_chunk_(entries_per_chunk),
64 [[nodiscard]]
constexpr bool has_deque()
const {
return deque_ !=
nullptr; }
66 [[nodiscard]]
constexpr const Deque& deque()
const {
67 PW_ASSERT(deque_ !=
nullptr);
71 constexpr void Increment(difference_type n);
73 constexpr void Decrement(difference_type n);
77 const Deque* deque_ =
nullptr;
79 size_type entries_per_chunk_ = 0;
80 size_type offset_ = 0;
84template <Mutability kMutability>
88 using BasicByteIterator::difference_type;
89 using BasicByteIterator::iterator_category;
90 using BasicByteIterator::size_type;
92 using value_type = std::conditional_t<kMutability == Mutability::kConst,
95 using pointer = value_type*;
96 using reference = value_type&;
105 deque(), chunk_, entries_per_chunk_, offset_)
109 constexpr reference operator*()
const {
110 return Entry::GetView(deque(), chunk_, entries_per_chunk_)[offset_];
113 constexpr reference operator[](difference_type n)
const {
117 constexpr ByteIterator& operator++() {
return operator+=(1); }
125 template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>,
int>>
127 if constexpr (std::is_unsigned_v<T>) {
128 PW_ASSERT(
size_t(n) < std::numeric_limits<difference_type>::max());
130 Increment(
static_cast<difference_type
>(n));
134 template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>,
int>>
139 template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>,
int>>
144 constexpr ByteIterator& operator--() {
return operator-=(1); }
152 template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>,
int>>
154 if constexpr (std::is_unsigned_v<T>) {
155 PW_ASSERT(
size_t(n) < std::numeric_limits<difference_type>::max());
157 Decrement(
static_cast<difference_type
>(n));
161 template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>,
int>>
166 constexpr friend bool operator==(
const ByteIterator& lhs,
168 return lhs.Compare(rhs) == 0;
171 constexpr friend bool operator!=(
const ByteIterator& lhs,
173 return lhs.Compare(rhs) != 0;
176 constexpr friend bool operator<(
const ByteIterator& lhs,
178 return lhs.Compare(rhs) < 0;
181 constexpr friend bool operator>(
const ByteIterator& lhs,
183 return lhs.Compare(rhs) > 0;
186 constexpr friend bool operator<=(
const ByteIterator& lhs,
188 return lhs.Compare(rhs) <= 0;
191 constexpr friend bool operator>=(
const ByteIterator& lhs,
193 return lhs.Compare(rhs) >= 0;
198 template <Mutability>
205 friend class ::pw::multibuf::v2::test::IteratorTest;
209 size_type entries_per_chunk,
216constexpr void BasicByteIterator::Increment(difference_type n) {
221 PW_ASSERT(deque_ !=
nullptr);
222 PW_ASSERT(n < std::numeric_limits<size_type>::max());
223 size_type delta =
static_cast<size_type
>(n) + offset_;
224 size_type length = 0;
226 while (chunk_ < num_chunks) {
228 if (delta < length) {
234 PW_ASSERT(delta < length || delta == 0);
238constexpr void BasicByteIterator::Decrement(difference_type n) {
240 return Increment(-n);
242 PW_ASSERT(deque_ !=
nullptr);
243 PW_ASSERT(n < std::numeric_limits<size_type>::max());
244 size_type delta =
static_cast<size_type
>(n);
245 while (delta > offset_) {
246 PW_ASSERT(chunk_ != 0);
254constexpr int BasicByteIterator::Compare(
const BasicByteIterator& other)
const {
255 if (deque_ ==
nullptr && other.deque_ ==
nullptr) {
258 if (deque_ ==
nullptr && other.deque_ !=
nullptr) {
261 if (deque_ !=
nullptr && other.deque_ ==
nullptr) {
264 if (deque_ != other.deque_) {
265 return std::less<>()(deque_, other.deque_) ? -1 : 1;
267 if (chunk_ != other.chunk_) {
268 return chunk_ < other.chunk_ ? -1 : 1;
270 if (offset_ != other.offset_) {
271 return offset_ < other.offset_ ? -1 : 1;
276constexpr BasicByteIterator::difference_type operator-(
277 const BasicByteIterator& lhs,
const BasicByteIterator& rhs) {
278 using size_type = BasicByteIterator::size_type;
279 PW_ASSERT(lhs.deque_ !=
nullptr);
280 PW_ASSERT(lhs.deque_ == rhs.deque_);
281 PW_ASSERT(lhs.entries_per_chunk_ == rhs.entries_per_chunk_);
282 int cmp = lhs.Compare(rhs);
290 size_type chunk = rhs.chunk_;
291 while (chunk < lhs.chunk_) {
295 delta -= rhs.offset_;
296 delta += lhs.offset_;
297 return static_cast<BasicByteIterator::difference_type
>(delta);
Definition: dynamic_deque.h:60
Definition: byte_iterator.h:41
Byte iterator templated on the const-ness of the bytes it references.
Definition: byte_iterator.h:85
Definition: multibuf.h:1057
static constexpr size_type num_chunks(const Deque &deque, size_type entries_per_chunk)
Returns the number of chunks in a deque.
Definition: entry.h:68
static constexpr ByteSpan GetView(const Deque &deque, size_type chunk, size_type entries_per_chunk, size_type layer)
Returns a view of the visible data length of the chunk at the given layer.
Definition: entry.h:235
static constexpr size_type GetLength(const Deque &deque, size_type chunk, size_type entries_per_chunk, size_type layer)
Returns the length of the given layer of the chunk.
Definition: entry.h:216