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