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