C/C++ API Reference
Loading...
Searching...
No Matches
byte_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 <iterator>
18
19#include "pw_bytes/span.h"
20#include "pw_multibuf/internal/chunk_iterator.h"
21
22namespace pw::multibuf {
23
24// Forward declarations for friending.
25class MultiBufV1Adapter;
26
27namespace test {
28class IteratorTest;
29} // namespace test
30
31namespace internal {
32class GenericMultiBuf;
33
42template <typename SizeType, ChunkMutability kMutability>
44 private:
45 using ChunkIteratorType =
47 using Deque = typename ChunkIteratorType::Deque;
48
49 public:
50 using size_type = SizeType;
51 using difference_type = ptrdiff_t;
52 using value_type = typename ChunkIteratorType::ByteType;
53 using pointer = value_type*;
54 using reference = value_type&;
55 using iterator_category = std::random_access_iterator_tag;
56
57 constexpr ByteIterator() = default;
58
59 // Support converting non-const iterators to const_iterators.
60 constexpr operator ByteIterator<SizeType, ChunkMutability::kConst>() const {
61 return {chunk_iterator_, offset_};
62 }
63
64 constexpr reference operator*() const {
65 return chunk_iterator_->data()[offset_];
66 }
67
68 constexpr reference operator[](difference_type n) const {
69 return *(*this + n);
70 }
71
72 constexpr ByteIterator& operator++() { return operator+=(1); }
73
74 constexpr ByteIterator operator++(int) {
75 ByteIterator previous(*this);
76 operator++();
77 return previous;
78 }
79
80 constexpr ByteIterator& operator+=(difference_type n) {
81 if (n < 0) {
82 return operator-=(-n);
83 }
84 size_t delta = static_cast<size_t>(n);
85 delta += offset_;
86 while (delta != 0 && chunk_iterator_->size() <= delta) {
87 delta -= chunk_iterator_->size();
88 ++chunk_iterator_;
89 }
90 offset_ = delta;
91 return *this;
92 }
93
94 constexpr friend ByteIterator operator+(ByteIterator it, difference_type n) {
95 return it += n;
96 }
97
98 constexpr friend ByteIterator operator+(difference_type n, ByteIterator it) {
99 return it += n;
100 }
101
102 constexpr ByteIterator& operator--() { return operator-=(1); }
103
104 constexpr ByteIterator operator--(int) {
105 ByteIterator previous(*this);
106 operator--();
107 return previous;
108 }
109
110 constexpr ByteIterator& operator-=(difference_type n) {
111 if (n < 0) {
112 return operator+=(-n);
113 }
114 size_t delta = static_cast<size_t>(n);
115 while (delta > offset_) {
116 --chunk_iterator_;
117 delta -= offset_;
118 offset_ = chunk_iterator_->size();
119 }
120 offset_ -= delta;
121 return *this;
122 }
123
124 constexpr friend ByteIterator operator-(ByteIterator it, difference_type n) {
125 return it -= n;
126 }
127
128 constexpr friend difference_type operator-(const ByteIterator& lhs,
129 const ByteIterator& rhs) {
130 if (lhs < rhs) {
131 return -(rhs - lhs);
132 }
133 difference_type delta = 0;
134 auto chunk_iterator = rhs.chunk_iterator_;
135 size_t offset = rhs.offset_;
136 while (chunk_iterator != lhs.chunk_iterator_) {
137 ConstByteSpan bytes = *chunk_iterator;
138 delta += static_cast<difference_type>(bytes.size() - offset);
139 offset = 0;
140 ++chunk_iterator;
141 }
142 return delta + static_cast<difference_type>(lhs.offset_);
143 }
144
145 constexpr friend bool operator==(const ByteIterator& lhs,
146 const ByteIterator& rhs) {
147 return lhs.Compare(rhs) == 0;
148 }
149
150 constexpr friend bool operator!=(const ByteIterator& lhs,
151 const ByteIterator& rhs) {
152 return lhs.Compare(rhs) != 0;
153 }
154
155 constexpr friend bool operator<(const ByteIterator& lhs,
156 const ByteIterator& rhs) {
157 return lhs.Compare(rhs) < 0;
158 }
159
160 constexpr friend bool operator>(const ByteIterator& lhs,
161 const ByteIterator& rhs) {
162 return lhs.Compare(rhs) > 0;
163 }
164
165 constexpr friend bool operator<=(const ByteIterator& lhs,
166 const ByteIterator& rhs) {
167 return lhs.Compare(rhs) <= 0;
168 }
169
170 constexpr friend bool operator>=(const ByteIterator& lhs,
171 const ByteIterator& rhs) {
172 return lhs.Compare(rhs) >= 0;
173 }
174
175 private:
176 // Allow non-const iterators to construct const_iterators in conversions.
177 template <typename, ChunkMutability>
178 friend class ByteIterator;
179
180 // Allow MultiBufs to create iterators.
181 friend class ::pw::multibuf::internal::GenericMultiBuf;
182
183 // Allow MultiBufV1Adapters to create iterators.
184 friend class ::pw::multibuf::MultiBufV1Adapter;
185
186 // For unit testing.
187 friend class ::pw::multibuf::test::IteratorTest;
188
189 constexpr ByteIterator(ChunkIteratorType&& chunk_iterator, size_t offset)
190 : chunk_iterator_(std::move(chunk_iterator)), offset_(offset) {}
191
192 constexpr size_type chunk() const { return chunk_iterator_.chunk_; }
193
194 // Compare using a method to allow access to the befriended ChunkIterator.
195 constexpr int Compare(const ByteIterator& other) const {
196 if (chunk_iterator_ != other.chunk_iterator_) {
197 return chunk_iterator_.chunk_ < other.chunk_iterator_.chunk_ ? -1 : 1;
198 }
199 if (offset_ != other.offset_) {
200 return offset_ < other.offset_ ? -1 : 1;
201 }
202 return 0;
203 }
204
205 ChunkIteratorType chunk_iterator_;
206 size_t offset_ = 0;
207};
208
209} // namespace internal
210} // namespace pw::multibuf
Definition: byte_iterator.h:43