Line | Branch | Exec | Source |
---|---|---|---|
1 | #pragma once | ||
2 | |||
3 | #include "IterValue.h" | ||
4 | #include "SizeHint.h" | ||
5 | |||
6 | /** | ||
7 | * @brief Trait namespace. This namespaces contains all public traits that cover all of the iterator's inner workings. | ||
8 | */ | ||
9 | namespace CXXIter::trait { | ||
10 | |||
11 | // ################################################################################################ | ||
12 | // ITERATOR TRAITS | ||
13 | // ################################################################################################ | ||
14 | |||
15 | /** | ||
16 | * @brief Trait, that is used for the chaining and the operation of iterator pipelines. | ||
17 | * @details This allows making any class or struct iterable, to be able to interact with CXXIter's | ||
18 | * iterator pipelines. It essentially provides two functions: | ||
19 | * - One that delivers a hint about the iterator's size after the current element implementing | ||
20 | * the trait @c CXXIter::trait::Iterator | ||
21 | * - Method that allows pulling one element from the iterator pipeline. | ||
22 | */ | ||
23 | template<typename T> | ||
24 | struct Iterator { | ||
25 | /** | ||
26 | * @brief Self-Type. This is the type of the struct for which the trait::Iterator is being specialized. | ||
27 | */ | ||
28 | using Self = trait::Iterator<T>; | ||
29 | /** | ||
30 | * @brief Item-Type. This is the type of elements that can be pulled from this pipeline-element. | ||
31 | */ | ||
32 | using Item = void; | ||
33 | |||
34 | /** | ||
35 | * @brief Pull one element from the iterator pipeline previous to this pipeline-element. | ||
36 | * @param self Reference to the instance of the class for which trait::Iterator is being specialized. | ||
37 | * @return An element (if any) wrapped in the CXXIter::IterValue. | ||
38 | */ | ||
39 | static constexpr inline IterValue<Item> next(Self& self) = delete; | ||
40 | |||
41 | /** | ||
42 | * @brief Get the bounds on the remaining length of the iterator pipeline until this pipeline-element, | ||
43 | * estimated from the source and all of the chained iterations until after this pipeline-element. | ||
44 | * @return The estimated bounds on the remaining length of the iterator pipeline until after this pipeline-element. | ||
45 | */ | ||
46 | static constexpr inline SizeHint sizeHint(const Self& self) = delete; | ||
47 | |||
48 | /** | ||
49 | * @brief Advance the iterator by n elements. | ||
50 | * @details If possible, this should be forwarded to the previous pipeline element, because then the | ||
51 | * pipeline source has the possibility to implement this as a O(1) operation, if supported. | ||
52 | * @param n The amount of elements to advance the iterator by. | ||
53 | * @return The amount of elements by which the iterator was actually advanced (e.g. if the iterator | ||
54 | * did have less than @p n elements remaining) | ||
55 | */ | ||
56 | static constexpr inline size_t advanceBy(Self& self, size_t n) = delete; | ||
57 | }; | ||
58 | |||
59 | /** | ||
60 | * @brief Trait, that extends iterators for which an exact length is known. | ||
61 | */ | ||
62 | template<typename T> | ||
63 | struct ExactSizeIterator { | ||
64 | /** | ||
65 | * @brief Get the iterator's exact number of elements. | ||
66 | * @param self Reference to the instance of the class for which trait::ExactSizeIterator is being specialized. | ||
67 | * @return This iterator's exact number of elements. | ||
68 | */ | ||
69 | static constexpr inline size_t size(const typename trait::Iterator<T>::Self& self) = delete; | ||
70 | }; | ||
71 | |||
72 | /** | ||
73 | * @brief Trait, that iterators implement whose elements are stored in a contiguous block of memory. | ||
74 | * @details This trait allows downstream elements to assume that it is valid to access following | ||
75 | * elements by reading from the current element onward. | ||
76 | */ | ||
77 | template<typename T> | ||
78 | struct ContiguousMemoryIterator { | ||
79 | /** | ||
80 | * @brief Pointer type to an item of this iterator. | ||
81 | * @details This keeps the const specifier. | ||
82 | */ | ||
83 | using ItemPtr = std::add_pointer_t<std::remove_reference_t<typename Iterator<T>::Item>>; | ||
84 | /** | ||
85 | * @brief Get the pointer of the current element. | ||
86 | * @param self Reference to the instance of the class for which trait::ExactSizeIterator is being specialized. | ||
87 | * @return Pointer of the element that would be returned by the next call to next(). | ||
88 | */ | ||
89 | static constexpr inline ItemPtr currentPtr(typename trait::Iterator<T>::Self& self) = delete; | ||
90 | }; | ||
91 | |||
92 | /** | ||
93 | * @brief Trait that extends the Iterator trait with double-ended functionality. | ||
94 | * @details Implementing this trait extends the iterator with the functionality to pull elements from the back. | ||
95 | * This can be arbitrarily mixed. Elements can e.g. be retrieved from front and back alternatingly. | ||
96 | */ | ||
97 | template<typename T> | ||
98 | struct DoubleEndedIterator { | ||
99 | using Self = typename trait::Iterator<T>::Self; | ||
100 | |||
101 | /** | ||
102 | * @brief Pull the next last element from the iterator pipeline previous to this pipeline-element. | ||
103 | * @param self Reference to the instance of the class for which trait::DoubleEndedIterator is being specialized. | ||
104 | * @return An element (if any) wrapped in the CXXIter::IterValue. | ||
105 | */ | ||
106 | static constexpr inline IterValue<typename Iterator<T>::Item> nextBack(Self& self) = delete; | ||
107 | }; | ||
108 | |||
109 | |||
110 | // ################################################################################################ | ||
111 | // SOURCE TRAITS | ||
112 | // ################################################################################################ | ||
113 | |||
114 | /** | ||
115 | * @brief SourceTrait, that is used by CXXIter's standard source classes @c CXXIter::SrcMov, @c CXXIter::SrcRef and @c CXXIter::SrcCRef. | ||
116 | * @details If you want to add support for your own containers to these sources, and thus to @c CXXIter::from() calls, | ||
117 | * create a template specialization of @c CXXIter::SourceTrait, for your container class. | ||
118 | * | ||
119 | * This is the default implementation supporting all STL containers. | ||
120 | */ | ||
121 | template<typename TContainer> struct Source { | ||
122 | /** | ||
123 | * @brief Type of the item @p TContainer holds and provides for the iterator. | ||
124 | */ | ||
125 | using Item = typename TContainer::value_type; | ||
126 | /** | ||
127 | * @brief Type of the item @p TContainer holds and provides for the iterator, in referenced form. | ||
128 | */ | ||
129 | using ItemRef = typename TContainer::reference; | ||
130 | /** | ||
131 | * @brief Type of the item @p TContainer holds and provides for the iterator, in const referenced form. | ||
132 | */ | ||
133 | using ItemConstRef = typename TContainer::const_reference; | ||
134 | |||
135 | /** | ||
136 | * @brief Type of the state structure stored in CXXIter's source classes, used to keep track of the iteration progress. | ||
137 | * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef | ||
138 | */ | ||
139 | struct IteratorState { | ||
140 | /** Iteration range left (start) */ | ||
141 | typename TContainer::iterator left; | ||
142 | /** Iteration range right (end) */ | ||
143 | typename TContainer::iterator right; | ||
144 | }; | ||
145 | |||
146 | /** | ||
147 | * @brief Type of the state structure stored in CXXIter's source classes, used to keep track of the iteration progress. | ||
148 | * @details This is used for @c CXXIter::SrcCRef | ||
149 | */ | ||
150 | struct ConstIteratorState { | ||
151 | /** Iteration range left (start) */ | ||
152 | typename TContainer::const_iterator left; | ||
153 | /** Iteration range right (end) */ | ||
154 | typename TContainer::const_iterator right; | ||
155 | }; | ||
156 | |||
157 | /** | ||
158 | * @brief Report a size hint for a source on the given @p container. | ||
159 | * @details This injects information about the source's size (element count) into the iterator API. | ||
160 | * @param container Container for which to generate a size hint. | ||
161 | * @return A size hint for the given @p container. | ||
162 | */ | ||
163 | 532 | static constexpr inline SizeHint sizeHint(const TContainer& container) { return SizeHint(container.size(), container.size()); } | |
164 | |||
165 | /** | ||
166 | * @brief Return an initial @c IteratorState instance for iteration on the given @p container. | ||
167 | * @details This is stored within CXXIter's source classes, to hold the iteration's state. | ||
168 | * This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef | ||
169 | * @param container Container on which the source runs. | ||
170 | * @return Instance of @c IteratorState | ||
171 | */ | ||
172 | 872 | static constexpr inline IteratorState initIterator(TContainer& container) { return {container.begin(), container.end()}; } | |
173 | /** | ||
174 | * @brief Return an initial @c IteratorState instance for iteration on the given @p container. | ||
175 | * @details This is stored within CXXIter's source classes, to hold the iteration's state. | ||
176 | * This is used for @c CXXIter::SrcCRef | ||
177 | * @param container Container on which the source runs. | ||
178 | * @return Instance of @c ConstIteratorState | ||
179 | */ | ||
180 | 76 | static constexpr inline ConstIteratorState initIterator(const TContainer& container) { return {container.begin(), container.end()}; } | |
181 | |||
182 | /** | ||
183 | * @brief Checks whether there is a next item in the iteration with the given @p iter state on the given @p container. | ||
184 | * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef | ||
185 | * @param container Container on which the current iteration is running. | ||
186 | * @param iter The current iteration's state structure. | ||
187 | * @return @c true when there is another item available, @c false otherwise. | ||
188 | */ | ||
189 | 2978 | static constexpr inline bool hasNext([[maybe_unused]] TContainer& container, IteratorState& iter) { return (iter.left != iter.right); } | |
190 | /** | ||
191 | * @brief Checks whether there is a next item in the iteration with the given @p iter state on the given @p container. | ||
192 | * @details This is used for @c CXXIter::SrcCRef | ||
193 | * @param container Container on which the current iteration is running. | ||
194 | * @param iter The current iteration's state structure. | ||
195 | * @return @c true when there is another item available, @c false otherwise. | ||
196 | */ | ||
197 | 184 | static constexpr inline bool hasNext([[maybe_unused]] const TContainer& container, ConstIteratorState& iter) { return (iter.left != iter.right); } | |
198 | |||
199 | /** | ||
200 | * @brief Return the next item in the iteration with the given @p iter state on the given @p container. | ||
201 | * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef | ||
202 | * @param container Container on which the current iteration is running. | ||
203 | * @param iter The current iteration's state structure. | ||
204 | * @return The next item from the current iteration. | ||
205 | */ | ||
206 | 2176 | static constexpr inline ItemRef next([[maybe_unused]] TContainer& container, IteratorState& iter) { return (*iter.left++); } | |
207 | /** | ||
208 | * @brief Return the next item in the iteration with the given @p iter state on the given @p container. | ||
209 | * @details This is used for @c CXXIter::SrcCRef | ||
210 | * @param container Container on which the current iteration is running. | ||
211 | * @param iter The current iteration's state structure. | ||
212 | * @return The next item from the current iteration. | ||
213 | */ | ||
214 | 151 | static constexpr inline ItemConstRef next([[maybe_unused]] const TContainer& container, ConstIteratorState& iter) { return (*iter.left++); } | |
215 | |||
216 | /** | ||
217 | * @brief Return the next item in the iteration with the given @p iter state on the given @p container, without advancing. | ||
218 | * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef | ||
219 | * @param container Container on which the current iteration is running. | ||
220 | * @param iter The current iteration's state structure. | ||
221 | * @return The next item from the current iteration. | ||
222 | * @attention Calling this when @c hasNext() returns @c false is undefined behavior! | ||
223 | */ | ||
224 | 38 | static constexpr inline ItemRef peekNext([[maybe_unused]] TContainer& container, IteratorState& iter) { return (*iter.left); } | |
225 | /** | ||
226 | * @brief Return the next item in the iteration with the given @p iter state on the given @p container, without advancing. | ||
227 | * @details This is used for @c CXXIter::SrcCRef | ||
228 | * @param container Container on which the current iteration is running. | ||
229 | * @param iter The current iteration's state structure. | ||
230 | * @return The next item from the current iteration. | ||
231 | * @attention Calling this when @c hasNext() returns @c false is undefined behavior! | ||
232 | */ | ||
233 | 3 | static constexpr inline ItemConstRef peekNext([[maybe_unused]] const TContainer& container, ConstIteratorState& iter) { return (*iter.left); } | |
234 | |||
235 | /** | ||
236 | * @brief Skip the next @p n elements from the container. | ||
237 | * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef | ||
238 | * @param container Container on which the current iteration is running. | ||
239 | * @param iter The current iteration's state structure. | ||
240 | * @param n The amount of elements to skip. | ||
241 | * @return The amount of actually skipped elements (e.g. if there were less than @p n elements remaining). | ||
242 | */ | ||
243 | 102 | static constexpr inline size_t skipN([[maybe_unused]] const TContainer& container, IteratorState& iter, size_t n) { | |
244 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
102 | size_t skipN = std::min(n, static_cast<size_t>(std::distance(iter.left, iter.right))); |
245 | 102 | iter.left += skipN; | |
246 | 102 | return skipN; | |
247 | } | ||
248 | /** | ||
249 | * @brief Skip the next @p n elements from the container. | ||
250 | * @details This is used for @c CXXIter::SrcCRef | ||
251 | * @param container Container on which the current iteration is running. | ||
252 | * @param iter The current iteration's state structure. | ||
253 | * @param n The amount of elements to skip. | ||
254 | * @return The amount of actually skipped elements (e.g. if there were less than @p n elements remaining). | ||
255 | */ | ||
256 | 7 | static constexpr inline size_t skipN([[maybe_unused]] const TContainer& container, ConstIteratorState& iter, size_t n) { | |
257 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
7 | size_t skipN = std::min(n, static_cast<size_t>(std::distance(iter.left, iter.right))); |
258 | 7 | iter.left += skipN; | |
259 | 7 | return skipN; | |
260 | } | ||
261 | |||
262 | /** | ||
263 | * @name Double-Ended iterator functionality (optional) | ||
264 | */ | ||
265 | //@{ | ||
266 | /** | ||
267 | * @brief Return the next item from the back of the iteration with the given @p iter state on the given @p container. | ||
268 | * @note Implementing this is optional, since not all containers can support this. | ||
269 | * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef | ||
270 | * @param container Container on which the current iteration is running. | ||
271 | * @param iter The current iteration's state structure. | ||
272 | * @return The next item from the back of the current iteration. | ||
273 | */ | ||
274 | 180 | static constexpr inline ItemRef nextBack([[maybe_unused]] TContainer& container, IteratorState& iter) { return (*--iter.right); } | |
275 | /** | ||
276 | * @brief Return the next item from the back of the iteration with the given @p iter state on the given @p container. | ||
277 | * @note Implementing this is optional, since not all containers can support this. | ||
278 | * @details This is used for @c CXXIter::SrcCRef | ||
279 | * @param container Container on which the current iteration is running. | ||
280 | * @param iter The current iteration's state structure. | ||
281 | * @return The next item from the back of the current iteration. | ||
282 | */ | ||
283 | 5 | static constexpr inline ItemConstRef nextBack([[maybe_unused]] const TContainer& container, ConstIteratorState& iter) { return (*--iter.right); } | |
284 | |||
285 | /** | ||
286 | * @brief Skip the next n elements from the back of this iterator. | ||
287 | * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef | ||
288 | * @param container Container on which the current iteration is running. | ||
289 | * @param iter The current iteration's state structure. | ||
290 | * @param n The amount of elements to skip. | ||
291 | * @return The amount of actually skipped elements (e.g. if there were less than @p n elements remaining). | ||
292 | */ | ||
293 | static constexpr inline size_t skipNBack([[maybe_unused]] const TContainer& container, IteratorState& iter, size_t n) { | ||
294 | size_t skipN = std::min(n, static_cast<size_t>(std::distance(iter.left, iter.right))); | ||
295 | iter.right -= skipN; | ||
296 | return skipN; | ||
297 | } | ||
298 | /** | ||
299 | * @brief Skip the next n elements from the back of this iterator. | ||
300 | * @details This is used for @c CXXIter::SrcCRef | ||
301 | * @param container Container on which the current iteration is running. | ||
302 | * @param iter The current iteration's state structure. | ||
303 | * @param n The amount of elements to skip. | ||
304 | * @return The amount of actually skipped elements (e.g. if there were less than @p n elements remaining). | ||
305 | */ | ||
306 | static constexpr inline size_t skipNBack([[maybe_unused]] const TContainer& container, ConstIteratorState& iter, size_t n) { | ||
307 | size_t skipN = std::min(n, static_cast<size_t>(std::distance(iter.left, iter.right))); | ||
308 | iter.right -= skipN; | ||
309 | return skipN; | ||
310 | } | ||
311 | //}@ | ||
312 | |||
313 | }; | ||
314 | |||
315 | } | ||
316 |