Line | Branch | Exec | Source |
---|---|---|---|
1 | #pragma once | ||
2 | |||
3 | #include <memory> | ||
4 | |||
5 | #include "../Common.h" | ||
6 | #include "Concepts.h" | ||
7 | |||
8 | namespace CXXIter { | ||
9 | |||
10 | // ################################################################################################ | ||
11 | // SOURCE (MOVE / CONSUME) | ||
12 | // ################################################################################################ | ||
13 | |||
14 | /** | ||
15 | * @brief CXXIter iterator source that takes over the input item source, and moves its items | ||
16 | * through the element stream, essentially "consuming" them. | ||
17 | */ | ||
18 | template<typename TContainer> | ||
19 | requires concepts::SourceContainer<std::remove_cvref_t<TContainer>> | ||
20 | class SrcMov : public IterApi<SrcMov<TContainer>> { | ||
21 | friend struct trait::Iterator<SrcMov<TContainer>>; | ||
22 | friend struct trait::DoubleEndedIterator<SrcMov<TContainer>>; | ||
23 | friend struct trait::ExactSizeIterator<SrcMov<TContainer>>; | ||
24 | friend struct trait::ContiguousMemoryIterator<SrcMov<TContainer>>; | ||
25 | using Src = trait::Source<TContainer>; | ||
26 | private: | ||
27 | std::unique_ptr<TContainer> container; | ||
28 | typename Src::IteratorState iter; | ||
29 | public: | ||
30 | 132 | SrcMov(TContainer&& container) : container(std::make_unique<TContainer>(std::move(container))), iter(Src::initIterator(*this->container)) {} | |
31 | }; | ||
32 | // ------------------------------------------------------------------------------------------------ | ||
33 | /** @private */ | ||
34 | template<typename TContainer> | ||
35 | struct trait::Iterator<SrcMov<TContainer>> { | ||
36 | using Src = trait::Source<TContainer>; | ||
37 | // CXXIter Interface | ||
38 | using Self = SrcMov<TContainer>; | ||
39 | using Item = typename Src::Item; | ||
40 | |||
41 | 424 | static constexpr inline IterValue<Item> next(Self& self) { | |
42 |
2/2✓ Branch 2 taken 59 times.
✓ Branch 3 taken 156 times.
|
424 | if(!Src::hasNext(*self.container, self.iter)) [[unlikely]] { return {}; } |
43 | 307 | return std::move(Src::next(*self.container, self.iter)); | |
44 | } | ||
45 | 22 | static constexpr inline SizeHint sizeHint(const Self& self) { return Src::sizeHint(*self.container); } | |
46 | 8 | static constexpr inline size_t advanceBy(Self& self, size_t n) { | |
47 | 8 | return Src::skipN(*self.container, self.iter, n); | |
48 | } | ||
49 | }; | ||
50 | /** @private */ | ||
51 | template<typename TContainer> | ||
52 | requires concepts::DoubleEndedSourceContainer<std::remove_cvref_t<TContainer>> | ||
53 | struct trait::DoubleEndedIterator<SrcMov<TContainer>> { | ||
54 | using Src = trait::Source<TContainer>; | ||
55 | using Item = typename Src::Item; | ||
56 | |||
57 | // CXXIter Interface | ||
58 | 148 | static constexpr inline IterValue<Item> nextBack(SrcMov<TContainer>& self) { | |
59 |
2/2✓ Branch 2 taken 20 times.
✓ Branch 3 taken 63 times.
|
148 | if(!Src::hasNext(*self.container, self.iter)) [[unlikely]] { return {}; } |
60 | 111 | return std::move(Src::nextBack(*self.container, self.iter)); | |
61 | } | ||
62 | }; | ||
63 | /** @private */ | ||
64 | template<typename TContainer> | ||
65 | struct trait::ExactSizeIterator<SrcMov<TContainer>> { | ||
66 | static constexpr inline size_t size(const SrcMov<TContainer>& self) { return self.container->size(); } | ||
67 | }; | ||
68 | /** @private */ | ||
69 | template<typename TContainer> | ||
70 | requires util::ContiguousMemoryContainer<TContainer> | ||
71 | struct trait::ContiguousMemoryIterator<SrcMov<TContainer>> { | ||
72 | using ItemPtr = std::add_pointer_t<std::remove_reference_t<typename SrcMov<TContainer>::Item>>; | ||
73 | 1 | static constexpr inline ItemPtr currentPtr(SrcMov<TContainer>& self) { | |
74 | 1 | return &trait::Source<TContainer>::peekNext(*self.container, self.iter); | |
75 | } | ||
76 | }; | ||
77 | |||
78 | |||
79 | |||
80 | // ################################################################################################ | ||
81 | // SOURCE (MUTABLE REFERENCE) | ||
82 | // ################################################################################################ | ||
83 | |||
84 | /** | ||
85 | * @brief CXXIter iterator source that mutably borrows the input item source, and passes mutable | ||
86 | * references to the items of the source through the iterator. | ||
87 | * @details This allows the iterator to modify the items while leaving them in the original | ||
88 | * item source. | ||
89 | */ | ||
90 | template<typename TContainer> | ||
91 | requires concepts::SourceContainer<std::remove_cvref_t<TContainer>> | ||
92 | class SrcRef : public IterApi<SrcRef<TContainer>> { | ||
93 | friend struct trait::Iterator<SrcRef<TContainer>>; | ||
94 | friend struct trait::DoubleEndedIterator<SrcRef<TContainer>>; | ||
95 | friend struct trait::ExactSizeIterator<SrcRef<TContainer>>; | ||
96 | friend struct trait::ContiguousMemoryIterator<SrcRef<TContainer>>; | ||
97 | using Src = trait::Source<TContainer>; | ||
98 | private: | ||
99 | TContainer& container; | ||
100 | typename Src::IteratorState iter; | ||
101 | public: | ||
102 | 743 | SrcRef(TContainer& container) : container(container), iter(Src::initIterator(this->container)) {} | |
103 | }; | ||
104 | // ------------------------------------------------------------------------------------------------ | ||
105 | /** @private */ | ||
106 | template<typename TContainer> | ||
107 | struct trait::Iterator<SrcRef<TContainer>> { | ||
108 | using Src = trait::Source<TContainer>; | ||
109 | // CXXIter Interface | ||
110 | using Self = SrcRef<TContainer>; | ||
111 | using Item = typename Src::ItemRef; | ||
112 | |||
113 | 2322 | static constexpr inline IterValue<Item> next(Self& self) { | |
114 |
2/2✓ Branch 1 taken 227 times.
✓ Branch 2 taken 934 times.
|
2322 | if(!Src::hasNext(self.container, self.iter)) [[unlikely]] { return {}; } |
115 | 1868 | return Src::next(self.container, self.iter); | |
116 | } | ||
117 | 508 | static constexpr inline SizeHint sizeHint(const Self& self) { return Src::sizeHint(self.container); } | |
118 | 94 | static constexpr inline size_t advanceBy(Self& self, size_t n) { | |
119 | 94 | return Src::skipN(self.container, self.iter, n); | |
120 | } | ||
121 | }; | ||
122 | /** @private */ | ||
123 | template<typename TContainer> | ||
124 | requires concepts::DoubleEndedSourceContainer<std::remove_cvref_t<TContainer>> | ||
125 | struct trait::DoubleEndedIterator<SrcRef<TContainer>> { | ||
126 | using Src = trait::Source<TContainer>; | ||
127 | using Item = typename Src::ItemRef; | ||
128 | |||
129 | // CXXIter Interface | ||
130 | 57 | static constexpr inline IterValue<Item> nextBack(SrcRef<TContainer>& self) { | |
131 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 27 times.
|
57 | if(!Src::hasNext(self.container, self.iter)) [[unlikely]] { return {}; } |
132 | 44 | return Src::nextBack(self.container, self.iter); | |
133 | } | ||
134 | }; | ||
135 | /** @private */ | ||
136 | template<typename TContainer> | ||
137 | struct trait::ExactSizeIterator<SrcRef<TContainer>> { | ||
138 | 24 | static constexpr inline size_t size(const SrcRef<TContainer>& self) { return self.container.size(); } | |
139 | }; | ||
140 | /** @private */ | ||
141 | template<typename TContainer> | ||
142 | requires util::ContiguousMemoryContainer<TContainer> | ||
143 | struct trait::ContiguousMemoryIterator<SrcRef<TContainer>> { | ||
144 | using ItemPtr = std::add_pointer_t<std::remove_reference_t<typename SrcRef<TContainer>::Item>>; | ||
145 | 37 | static constexpr inline ItemPtr currentPtr(SrcRef<TContainer>& self) { | |
146 | 37 | return &trait::Source<TContainer>::peekNext(self.container, self.iter); | |
147 | } | ||
148 | }; | ||
149 | |||
150 | |||
151 | |||
152 | // ################################################################################################ | ||
153 | // SOURCE (CONST REFERENCE) | ||
154 | // ################################################################################################ | ||
155 | |||
156 | /** | ||
157 | * @brief CXXIter iterator source that immutably borrows the input item source, and passes immutable | ||
158 | * references to the items of the source through the iterator. | ||
159 | * @details This guarantees the original source to stay untouched & unmodified. | ||
160 | */ | ||
161 | template<typename TContainer> | ||
162 | requires concepts::SourceContainer<std::remove_cvref_t<TContainer>> | ||
163 | class SrcCRef : public IterApi<SrcCRef<TContainer>> { | ||
164 | friend struct trait::Iterator<SrcCRef<TContainer>>; | ||
165 | friend struct trait::DoubleEndedIterator<SrcCRef<TContainer>>; | ||
166 | friend struct trait::ExactSizeIterator<SrcCRef<TContainer>>; | ||
167 | friend struct trait::ContiguousMemoryIterator<SrcCRef<TContainer>>; | ||
168 | using Src = trait::Source<TContainer>; | ||
169 | private: | ||
170 | const TContainer& container; | ||
171 | typename Src::ConstIteratorState iter; | ||
172 | public: | ||
173 | 78 | constexpr SrcCRef(const TContainer& container) : container(container), iter(Src::initIterator(this->container)) {} | |
174 | }; | ||
175 | // ------------------------------------------------------------------------------------------------ | ||
176 | /** @private */ | ||
177 | template<typename TContainer> | ||
178 | struct trait::Iterator<SrcCRef<TContainer>> { | ||
179 | using Src = trait::Source<TContainer>; | ||
180 | // CXXIter Interface | ||
181 | using Self = SrcCRef<TContainer>; | ||
182 | using Item = typename Src::ItemConstRef; | ||
183 | |||
184 | 108 | static constexpr inline IterValue<Item> next(Self& self) { | |
185 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 17 times.
|
108 | if(!Src::hasNext(self.container, self.iter)) [[unlikely]] { return {}; } |
186 | 89 | return Src::next(self.container, self.iter); | |
187 | } | ||
188 | 6 | static constexpr inline SizeHint sizeHint(const Self& self) { return Src::sizeHint(self.container); } | |
189 | 7 | static constexpr inline size_t advanceBy(Self& self, size_t n) { | |
190 | 7 | return Src::skipN(self.container, self.iter, n); | |
191 | } | ||
192 | }; | ||
193 | /** @private */ | ||
194 | template<typename TContainer> | ||
195 | requires concepts::DoubleEndedSourceContainer<std::remove_cvref_t<TContainer>> | ||
196 | struct trait::DoubleEndedIterator<SrcCRef<TContainer>> { | ||
197 | using Src = trait::Source<TContainer>; | ||
198 | using Item = typename Src::ItemConstRef; | ||
199 | |||
200 | // CXXIter Interface | ||
201 | 8 | static constexpr inline IterValue<Item> nextBack(SrcCRef<TContainer>& self) { | |
202 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
|
8 | if(!Src::hasNext(self.container, self.iter)) [[unlikely]] { return {}; } |
203 | 5 | return Src::nextBack(self.container, self.iter); | |
204 | } | ||
205 | }; | ||
206 | /** @private */ | ||
207 | template<typename TContainer> | ||
208 | struct trait::ExactSizeIterator<SrcCRef<TContainer>> { | ||
209 | 2 | static constexpr inline size_t size(const SrcCRef<TContainer>& self) { return self.container.size(); } | |
210 | }; | ||
211 | /** @private */ | ||
212 | template<typename TContainer> | ||
213 | requires util::ContiguousMemoryContainer<TContainer> | ||
214 | struct trait::ContiguousMemoryIterator<SrcCRef<TContainer>> { | ||
215 | using ItemPtr = std::add_pointer_t<std::remove_reference_t<typename SrcCRef<TContainer>::Item>>; | ||
216 | 3 | static constexpr inline ItemPtr currentPtr(SrcCRef<TContainer>& self) { | |
217 | 3 | return &trait::Source<TContainer>::peekNext(self.container, self.iter); | |
218 | } | ||
219 | }; | ||
220 | |||
221 | } | ||
222 |