Iros
 
Loading...
Searching...
No Matches
chunk_view.h
Go to the documentation of this file.
1#pragma once
2
12#include "di/math/to_unsigned.h"
14#include "di/util/store_if.h"
15
16namespace di::container {
17template<concepts::View View>
19
20template<concepts::View View>
23private:
26 using SSizeType = meta::ContainerSSizeType<View>;
27
28 class InnerIterator : public IteratorBase<InnerIterator, InputIteratorTag, meta::ContainerValue<View>, SSizeType> {
29 private:
30 friend class ChunkView;
31
32 constexpr explicit InnerIterator(ChunkView& parent) : m_parent(util::addressof(parent)) {}
33
34 public:
35 InnerIterator(InnerIterator&&) = default;
36 auto operator=(InnerIterator&&) -> InnerIterator& = default;
37
38 constexpr auto base() const& -> Iter const& { return *m_parent->m_current; }
39
40 constexpr auto operator*() const -> decltype(auto) { return **m_parent->m_current; }
41
42 constexpr void advance_one() {
43 ++*m_parent->m_current;
44 if (*m_parent->m_current == container::end(m_parent->m_base)) {
45 m_parent->m_remainder = 0;
46 } else {
47 --m_parent->m_remainder;
48 }
49 }
50
51 private:
52 constexpr auto at_end() const -> bool { return m_parent->m_remainder == 0; }
53
54 constexpr auto distance() const -> SSizeType {
55 return container::min(m_parent->m_remainder, container::end(m_parent->m_base) - *m_parent->m_current);
56 }
57
58 constexpr friend auto operator==(InnerIterator const& a, DefaultSentinel) -> bool { return a.at_end(); }
59
60 constexpr friend auto operator-(DefaultSentinel, InnerIterator const& a) -> SSizeType
62 {
63 return a.distance();
64 }
65
66 constexpr friend auto operator-(InnerIterator const& a, DefaultSentinel) -> SSizeType
68 {
69 return -(default_sentinel - a);
70 }
71
72 ChunkView* m_parent { nullptr };
73 };
74
75 class ValueType : public ViewInterface<ValueType> {
76 friend class ChunkView;
77
78 constexpr explicit ValueType(ChunkView& parent) : m_parent(util::addressof(parent)) {}
79
80 public:
81 constexpr auto begin() const { return InnerIterator(*m_parent); }
82
83 constexpr auto end() const { return default_sentinel; }
84
85 constexpr auto size() const
86 requires(concepts::SizedSentinelFor<Sent, Iter>)
87 {
88 return container::min(m_parent->m_remainder, container::end(m_parent->m_base) - *m_parent->m_current);
89 }
90
91 private:
92 ChunkView* m_parent { nullptr };
93 };
94
95 class OuterIterator : public IteratorBase<OuterIterator, InputIteratorTag, ValueType, SSizeType> {
96 private:
97 friend class ChunkView;
98
99 constexpr explicit OuterIterator(ChunkView& parent) : m_parent(util::addressof(parent)) {}
100
101 public:
102 OuterIterator(OuterIterator&&) = default;
103 auto operator=(OuterIterator&&) -> OuterIterator& = default;
104
105 constexpr auto operator*() const -> ValueType { return ValueType(*m_parent); }
106
107 constexpr void advance_one() {
108 container::advance(*m_parent->m_current, m_parent->m_remainder, container::end(m_parent->m_base));
109 m_parent->m_remainder = m_parent->m_chunk_size;
110 }
111
112 private:
113 constexpr auto at_end() const -> bool {
114 return *m_parent->m_current == container::end(m_parent->m_base) && m_parent->m_remainder != 0;
115 }
116
117 constexpr auto distance() const -> SSizeType {
118 auto const distance = container::end(m_parent->m_base) - *m_parent->m_current;
119
120 if (distance < m_parent->m_remainder) {
121 return distance == 0 ? 0 : 1;
122 }
123 return math::divide_round_up(distance - m_parent->m_remainder, m_parent->m_chunk_size) + 1;
124 }
125
126 constexpr friend auto operator==(OuterIterator const& a, DefaultSentinel) -> bool { return a.at_end(); }
127
128 constexpr friend auto operator-(DefaultSentinel, OuterIterator const& a) -> SSizeType
130 {
131 return a.distance();
132 }
133
134 constexpr friend auto operator-(OuterIterator const& a, DefaultSentinel) -> SSizeType
136 {
137 return -(default_sentinel - a);
138 }
139
140 ChunkView* m_parent { nullptr };
141 };
142
143public:
146 = default;
147
148 constexpr explicit ChunkView(View base, SSizeType chunk_size) : m_base(util::move(base)), m_chunk_size(chunk_size) {
150 }
151
152 constexpr auto base() const& -> View
153 requires(concepts::CopyConstructible<View>)
154 {
155 return m_base;
156 }
157 constexpr auto base() && -> View { return util::move(m_base); }
158
159 constexpr auto chunk_size() const { return m_chunk_size; }
160
161 constexpr auto begin() {
162 m_current = container::begin(m_base);
163 m_remainder = m_chunk_size;
164 return OuterIterator(*this);
165 }
166
167 constexpr auto end() const { return default_sentinel; }
168
169 constexpr auto size()
171 {
172 return math::to_unsigned(math::divide_round_up(container::distance(m_base), m_chunk_size));
173 }
174
175 constexpr auto size() const
176 requires(concepts::SizedContainer<View const>)
177 {
178 return math::to_unsigned(math::divide_round_up(container::distance(m_base), m_chunk_size));
179 }
180
181private:
182 View m_base {};
183 SSizeType m_chunk_size { 0 };
184 SSizeType m_remainder { 0 };
185 util::NonPropagatingCache<Iter> m_current;
186};
187
188template<concepts::View View>
189requires(concepts::ForwardContainer<View>)
191 : public ViewInterface<ChunkView<View>>
192 , public meta::EnableBorrowedContainer<ChunkView<View>, concepts::BorrowedContainer<View>> {
193private:
194 template<bool is_const>
196
197 template<bool is_const>
199
200 template<bool is_const>
202
203 template<bool is_const>
205
206 template<bool is_const>
207 using ValueType =
208 decltype(view::take(reconstruct(in_place_type<Base<is_const>>, util::declval<Iter<is_const> const&>(),
209 util::declval<Sent<is_const> const&>()),
210 util::declval<SSizeType<is_const> const&>()));
211
212 template<bool is_const>
214 : public IteratorBase<Iterator<is_const>,
215 meta::Conditional<concepts::RandomAccessIterator<Iter<is_const>>, RandomAccessIteratorTag,
216 meta::Conditional<concepts::BidirectionalIterator<Iter<is_const>>,
217 BidirectionalIteratorTag, ForwardIteratorTag>>,
218 ValueType<is_const>, SSizeType<is_const>> {
219 private:
220 friend class ChunkView;
221
222 constexpr Iterator(meta::MaybeConst<is_const, ChunkView>* parent, Iter<is_const> base,
223 SSizeType<is_const> missing = 0)
224 : m_base(util::move(base))
225 , m_end(container::end(parent->m_base))
226 , m_chunk_size(parent->chunk_size())
227 , m_missing(missing) {}
228
229 public:
230 Iterator() = default;
231
233 requires(is_const && concepts::ConvertibleTo<Iter<false>, Iter<true>> &&
235 : m_base(util::move(other.m_base))
236 , m_end(util::move(other.m_end))
237 , m_chunk_size(other.m_chunk_size)
238 , m_missing(other.m_missing) {}
239
240 constexpr auto base() -> Iter<is_const> { return m_base; }
241
242 constexpr auto operator*() const -> decltype(auto) {
243 return view::take(reconstruct(in_place_type<Base<is_const>>, m_base, m_end), m_chunk_size);
244 }
245
246 constexpr void advance_one() { m_missing = container::advance(m_base, m_chunk_size, m_end); }
247
248 constexpr void back_one()
250 {
251 container::advance(m_base, m_missing - m_chunk_size);
252 m_missing = 0;
253 }
254
255 constexpr void advance_n(SSizeType<is_const> n)
257 {
258 if (n > 0) {
259 m_missing = container::advance(m_base, m_chunk_size * n, m_end);
260 } else if (n < 0) {
261 container::advance(m_base, m_chunk_size * n + m_missing);
262 m_missing = 0;
263 }
264 }
265
266 private:
267 template<bool>
268 friend class Iterator;
269
270 constexpr friend auto operator==(Iterator const& self, DefaultSentinel) -> bool {
271 return self.m_base == self.m_end;
272 }
273 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool { return a.m_base == b.m_base; }
274
275 constexpr friend auto operator<=>(Iterator const& a, Iterator const& b)
277 {
278 return a.m_base <=> b.m_base;
279 }
280
281 constexpr friend auto operator-(Iterator const& a, Iterator const& b) -> SSizeType<is_const>
282 requires(concepts::SizedSentinelFor<Iter<is_const>, Iter<is_const>>)
283 {
284 auto n = a.m_base - b.m_base;
285 return (n + a.m_missing - b.m_missing) / a.m_chunk_size;
286 }
287
288 constexpr friend auto operator-(DefaultSentinel, Iterator const& b) -> SSizeType<is_const> {
289 return math::divide_round_up(b.m_base - b.m_current, b.m_chunk_size);
290 }
291 constexpr friend auto operator-(Iterator const& a, DefaultSentinel) -> SSizeType<is_const> {
292 return -(default_sentinel - a);
293 }
294
295 Iter<is_const> m_base {};
296 Sent<is_const> m_end {};
297 SSizeType<is_const> m_chunk_size { 0 };
298 SSizeType<is_const> m_missing { 0 };
299 };
300
301public:
304 = default;
305
306 constexpr explicit ChunkView(View base, SSizeType<false> chunk_size)
307 : m_base(util::move(base)), m_chunk_size(chunk_size) {
309 }
310
311 constexpr auto base() const& -> View
312 requires(concepts::CopyConstructible<View>)
313 {
314 return m_base;
315 }
316 constexpr auto base() && -> View { return util::move(m_base); }
317
318 constexpr auto chunk_size() const { return m_chunk_size; }
319
320 constexpr auto begin()
322 {
323 return Iterator<false>(this, container::begin(m_base));
324 }
325
326 constexpr auto begin() const
327 requires(concepts::Container<View const>)
328 {
329 return Iterator<true>(this, container::begin(m_base));
330 }
331
332 constexpr auto end()
334 {
336 auto missing = (m_chunk_size - container::distance(m_base) % m_chunk_size) % m_chunk_size;
337 return Iterator<false>(this, container::end(m_base), missing);
339 return Iterator<false>(this, container::end(m_base));
340 } else {
341 return default_sentinel;
342 }
343 }
344
345 constexpr auto end() const
346 requires(concepts::Container<View const>)
347 {
349 auto missing = (m_chunk_size - container::distance(m_base) % m_chunk_size) % m_chunk_size;
350 return Iterator<true>(this, container::end(m_base), missing);
352 return Iterator<true>(this, container::end(m_base));
353 } else {
354 return default_sentinel;
355 }
356 }
357
358 constexpr auto size()
360 {
361 return math::to_unsigned(math::divide_round_up(container::distance(m_base), m_chunk_size));
362 }
363
364 constexpr auto size() const
365 requires(concepts::SizedContainer<View const>)
366 {
367 return math::to_unsigned(math::divide_round_up(container::distance(m_base), m_chunk_size));
368 }
369
370private:
371 View m_base;
372 SSizeType<false> m_chunk_size;
373};
374
375template<typename Con>
377}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition chunk_view.h:18
constexpr auto base() const &-> Iter const &
Definition chunk_view.h:38
constexpr auto begin()
Definition chunk_view.h:161
constexpr auto base() const &-> View requires(concepts::CopyConstructible< View >)
Definition chunk_view.h:152
constexpr friend auto operator<=>(Iterator const &a, Iterator const &b)
Definition chunk_view.h:275
constexpr ChunkView(View base, SSizeType< false > chunk_size)
Definition chunk_view.h:306
constexpr friend auto operator-(DefaultSentinel, OuterIterator const &a) -> SSizeType requires(concepts::SizedSentinelFor< Sent, Iter >)
Definition chunk_view.h:128
constexpr auto base() -> Iter< is_const >
Definition chunk_view.h:240
constexpr friend auto operator==(InnerIterator const &a, DefaultSentinel) -> bool
Definition chunk_view.h:58
constexpr auto begin() const
Definition chunk_view.h:326
constexpr friend auto operator-(DefaultSentinel, Iterator const &b) -> SSizeType< is_const >
Definition chunk_view.h:288
constexpr auto size()
Definition chunk_view.h:169
constexpr auto begin()
Definition chunk_view.h:320
auto operator=(OuterIterator &&) -> OuterIterator &=default
constexpr void back_one()
Definition chunk_view.h:248
constexpr friend auto operator==(Iterator const &a, Iterator const &b) -> bool
Definition chunk_view.h:273
constexpr friend auto operator-(DefaultSentinel, InnerIterator const &a) -> SSizeType requires(concepts::SizedSentinelFor< Sent, Iter >)
Definition chunk_view.h:60
constexpr ChunkView(View base, SSizeType chunk_size)
Definition chunk_view.h:148
constexpr void advance_one()
Definition chunk_view.h:246
constexpr auto begin() const
Definition chunk_view.h:81
constexpr auto size() const
Definition chunk_view.h:85
constexpr auto end() const
Definition chunk_view.h:83
constexpr void advance_one()
Definition chunk_view.h:42
constexpr auto end() const
Definition chunk_view.h:345
constexpr auto size() const
Definition chunk_view.h:175
auto operator=(InnerIterator &&) -> InnerIterator &=default
constexpr auto operator*() const -> decltype(auto)
Definition chunk_view.h:40
constexpr auto operator*() const -> ValueType
Definition chunk_view.h:105
constexpr auto base() &&-> View
Definition chunk_view.h:157
constexpr void advance_one()
Definition chunk_view.h:107
constexpr Iterator(Iterator<!is_const > other)
Definition chunk_view.h:232
constexpr friend auto operator==(OuterIterator const &a, DefaultSentinel) -> bool
Definition chunk_view.h:126
constexpr void advance_n(SSizeType< is_const > n)
Definition chunk_view.h:255
constexpr friend auto operator-(InnerIterator const &a, DefaultSentinel) -> SSizeType requires(concepts::SizedSentinelFor< Sent, Iter >)
Definition chunk_view.h:66
constexpr auto operator*() const -> decltype(auto)
Definition chunk_view.h:242
constexpr friend auto operator-(OuterIterator const &a, DefaultSentinel) -> SSizeType requires(concepts::SizedSentinelFor< Sent, Iter >)
Definition chunk_view.h:134
constexpr auto chunk_size() const
Definition chunk_view.h:159
constexpr auto end()
Definition chunk_view.h:332
constexpr friend auto operator-(Iterator const &a, DefaultSentinel) -> SSizeType< is_const >
Definition chunk_view.h:291
constexpr friend auto operator-(Iterator const &a, Iterator const &b) -> SSizeType< is_const > requires(concepts::SizedSentinelFor< Iter< is_const >, Iter< is_const > >)
Definition chunk_view.h:281
friend class ChunkView
Definition chunk_view.h:30
friend class Iterator
Definition chunk_view.h:268
constexpr friend auto operator==(Iterator const &self, DefaultSentinel) -> bool
Definition chunk_view.h:270
constexpr auto end() const
Definition chunk_view.h:167
Definition view_interface.h:26
Definition view.h:35
Definition bidirectional_container.h:8
Definition bidirectional_iterator.h:8
Definition common_container.h:10
Definition operations.h:99
Definition operations.h:27
Definition forward_container.h:8
Definition input_container.h:8
Definition random_access_iterator.h:12
Definition simple_view.h:11
Definition sized_container.h:8
Definition sized_sentinel_for.h:9
Definition any_storable.h:9
constexpr auto take
Definition take.h:35
Definition sequence.h:12
constexpr auto min
Definition min.h:47
constexpr auto reconstruct
Definition reconstruct.h:75
ChunkView(Con &&, meta::ContainerSSizeType< Con >) -> ChunkView< meta::AsView< Con > >
constexpr auto move
Definition move.h:38
constexpr auto distance
Definition distance.h:44
constexpr auto default_sentinel
Definition default_sentinel.h:6
constexpr auto end
Definition end.h:47
constexpr auto advance
Definition advance.h:62
constexpr auto begin
Definition begin.h:44
constexpr auto to_unsigned
Definition to_unsigned.h:16
constexpr auto divide_round_up
Definition divide_round_up.h:17
Definition merge_interfaces.h:6
IteratorSSizeType< ContainerIterator< T > > ContainerSSizeType
Definition container_ssize_type.h:8
decltype(container::end(util::declval< T & >())) ContainerSentinel
Definition container_sentinel.h:8
Conditional< is_const, T const, T > MaybeConst
Definition util.h:9
decltype(container::begin(util::declval< T & >())) ContainerIterator
Definition container_iterator.h:8
Definition vocab.h:96
auto declval() -> meta::AddRValueReference< T >
Definition declval.h:8
constexpr auto distance
Definition distance.h:44
constexpr auto in_place_type
Definition in_place_type.h:12
Definition default_sentinel.h:4
Definition enable_borrowed_container.h:9