| 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 |