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