20#include "pw_assert/assert.h"
21#include "pw_bytes/span.h"
22#include "pw_containers/dynamic_deque.h"
23#include "pw_multibuf/internal/entry.h"
24#include "pw_preprocessor/compiler.h"
26namespace pw::multibuf_impl {
29template <
typename,
typename>
40template <
typename SizeType,
bool kIsConst>
43 using SpanType = std::conditional_t<kIsConst, ConstByteSpan, ByteSpan>;
44 using ByteType =
typename SpanType::element_type;
45 using Deque = std::conditional_t<kIsConst,
50 using size_type = SizeType;
51 using difference_type = std::ptrdiff_t;
52 using value_type = SpanType;
53 using pointer = value_type*;
54 using const_pointer =
const value_type*;
55 using reference = value_type&;
56 using const_reference =
const value_type&;
57 using iterator_category = std::bidirectional_iterator_tag;
65 return {deque_, depth_, index_};
68 constexpr reference operator*() {
69 PW_ASSERT(is_valid());
73 constexpr const_reference operator*()
const {
74 PW_ASSERT(is_valid());
78 constexpr pointer operator->() {
79 PW_ASSERT(is_valid());
83 constexpr const_pointer operator->()
const {
84 PW_ASSERT(is_valid());
106 return lhs.deque_ == rhs.deque_ && lhs.depth_ == rhs.depth_ &&
107 lhs.index_ == rhs.index_;
112 return !(lhs == rhs);
117 template <
typename,
typename>
121 template <
typename,
bool>
125 template <
typename,
bool>
128 constexpr ChunkIterator(Deque* deque, size_type depth, size_type index)
129 : deque_(deque), depth_(depth), index_(index) {
133 constexpr bool is_valid()
const {
134 return deque_ !=
nullptr && index_ < deque_->size();
137 constexpr ByteType* data(size_type index)
const {
138 return (*deque_)[index].data + (*deque_)[index + depth_ - 1].view.offset;
141 constexpr size_t size(size_type index)
const {
142 return (*deque_)[index + depth_ - 1].view.length;
145 constexpr void ResetCurrent();
147 Deque* deque_ =
nullptr;
148 size_type depth_ = 0;
149 size_type index_ = 0;
154template <
typename Derived,
typename Deque>
157 using size_type =
typename Deque::size_type;
158 using value_type =
typename Deque::value_type;
159 using difference_type =
typename Deque::difference_type;
165 constexpr size_type size()
const {
return deque().size() / depth(); }
166 constexpr size_type capacity()
const {
return deque().capacity() / depth(); }
168 constexpr const_iterator cbegin()
const {
return derived().begin(); }
172 constexpr void Init(Deque& deque, size_type depth) {
173 derived().begin_.deque_ = &deque;
174 derived().begin_.depth_ = depth;
175 derived().end_.deque_ = &deque;
176 derived().end_.depth_ = depth;
177 derived().end_.index_ = deque.size();
180 constexpr Derived& derived() {
return static_cast<Derived&
>(*this); }
181 constexpr const Derived& derived()
const {
182 return static_cast<const Derived&
>(*this);
185 constexpr const Deque& deque()
const {
return *(derived().begin_.deque_); }
186 constexpr size_type depth()
const {
return derived().begin_.depth_; }
201template <
typename SizeType = u
int16_t>
203 :
public ChunksImpl<Chunks<SizeType>, DynamicDeque<Entry, SizeType>> {
210 using typename Base::difference_type;
212 using typename Base::size_type;
213 using typename Base::value_type;
215 constexpr Chunks() =
default;
217 constexpr iterator begin()
const {
return begin_; }
218 constexpr iterator end()
const {
return end_; }
221 template <
typename,
typename>
226 friend class IteratorTest;
228 constexpr Chunks(
Deque& deque, size_type depth) { Base::Init(deque, depth); }
246template <
typename SizeType = u
int16_t>
248 const DynamicDeque<Entry, SizeType>> {
255 using typename Base::difference_type;
256 using typename Base::size_type;
257 using typename Base::value_type;
265 template <
typename,
typename>
270 Base::Init(deque, depth);
279template <
typename SizeType,
bool kIsConst>
282 deque_ = other.deque_;
283 depth_ = other.depth_;
284 index_ = other.index_;
289template <
typename SizeType,
bool kIsConst>
290constexpr ChunkIterator<SizeType, kIsConst>&
291ChunkIterator<SizeType, kIsConst>::operator++() {
292 PW_ASSERT(is_valid());
293 size_t left = current_.size();
295 left -= size(index_);
298 while (index_ < deque_->size() && size(index_) == 0) {
305template <
typename SizeType,
bool kIsConst>
306constexpr ChunkIterator<SizeType, kIsConst>&
307ChunkIterator<SizeType, kIsConst>::operator--() {
308 PW_ASSERT(deque_ !=
nullptr);
309 PW_ASSERT(index_ != 0);
310 current_ = SpanType();
311 while (index_ != 0) {
312 SpanType prev(data(index_ - depth_), size(index_ - depth_));
313 if (!current_.empty() && prev.data() + prev.size() != current_.data()) {
316 current_ = SpanType(prev.data(), prev.size() + current_.size());
322template <
typename SizeType,
bool kIsConst>
323constexpr void ChunkIterator<SizeType, kIsConst>::ResetCurrent() {
325 current_ = SpanType();
328 current_ = SpanType(data(index_), size(index_));
329 for (size_type i = index_; i < deque_->size() - depth_; i += depth_) {
330 SpanType next(data(i + depth_), size(i + depth_));
331 if (current_.empty()) {
336 if (current_.data() + current_.size() != next.data()) {
339 current_ = SpanType(current_.data(), current_.size() + next.size());
Definition: dynamic_deque.h:60
Definition: byte_iterator.h:38
Definition: chunk_iterator.h:41
Definition: chunk_iterator.h:203
Base class for ranges of chunks.
Definition: chunk_iterator.h:155
Definition: chunk_iterator.h:248
Definition: multibuf_v2.h:1172