Line | Branch | Exec | Source |
---|---|---|---|
1 | #pragma once | ||
2 | |||
3 | #include <cstdlib> | ||
4 | #include <optional> | ||
5 | |||
6 | #include "../Common.h" | ||
7 | #include "../util/TraitImpl.h" | ||
8 | |||
9 | namespace CXXIter { | ||
10 | |||
11 | // ################################################################################################ | ||
12 | // GENERATOR EMPTY | ||
13 | // ################################################################################################ | ||
14 | /** @private */ | ||
15 | template<typename TItem> | ||
16 | class Empty : public IterApi<Empty<TItem>> { | ||
17 | friend struct trait::Iterator<Empty<TItem>>; | ||
18 | friend struct trait::ExactSizeIterator<Empty<TItem>>; | ||
19 | }; | ||
20 | // ------------------------------------------------------------------------------------------------ | ||
21 | /** @private */ | ||
22 | template<typename TItem> | ||
23 | struct trait::Iterator<Empty<TItem>> { | ||
24 | // CXXIter Interface | ||
25 | using Self = Empty<TItem>; | ||
26 | using Item = TItem; | ||
27 | |||
28 | 1 | static constexpr inline IterValue<Item> next(Self&) { return {}; } | |
29 | 13 | static constexpr inline SizeHint sizeHint(const Self&) { return SizeHint(0, 0); } | |
30 | static constexpr inline size_t advanceBy(Self&, size_t) { return 0; } | ||
31 | }; | ||
32 | /** @private */ | ||
33 | template<typename TItem> | ||
34 | struct trait::ExactSizeIterator<Empty<TItem>> { | ||
35 | 1 | static constexpr inline size_t size(const Empty<TItem>&) { return 0; } | |
36 | }; | ||
37 | |||
38 | |||
39 | // ################################################################################################ | ||
40 | // GENERATOR FUNCTION | ||
41 | // ################################################################################################ | ||
42 | /** @private */ | ||
43 | template<typename TItem, typename TGeneratorFn> | ||
44 | class FunctionGenerator : public IterApi<FunctionGenerator<TItem, TGeneratorFn>> { | ||
45 | friend struct trait::Iterator<FunctionGenerator<TItem, TGeneratorFn>>; | ||
46 | friend struct trait::ExactSizeIterator<FunctionGenerator<TItem, TGeneratorFn>>; | ||
47 | private: | ||
48 | TGeneratorFn generatorFn; | ||
49 | public: | ||
50 | 1 | FunctionGenerator(TGeneratorFn generatorFn) : generatorFn(generatorFn) {} | |
51 | }; | ||
52 | // ------------------------------------------------------------------------------------------------ | ||
53 | /** @private */ | ||
54 | template<typename TItem, typename TGeneratorFn> | ||
55 | struct trait::Iterator<FunctionGenerator<TItem, TGeneratorFn>> { | ||
56 | // CXXIter Interface | ||
57 | using Self = FunctionGenerator<TItem, TGeneratorFn>; | ||
58 | using Item = TItem; | ||
59 | |||
60 | 100 | static constexpr inline IterValue<Item> next(Self& self) { | |
61 |
1/2✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
|
100 | auto item = self.generatorFn(); |
62 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
|
100 | if(!item.has_value()) [[unlikely]] { return {}; } |
63 |
1/2✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
|
100 | return item.value(); |
64 | } | ||
65 | 1 | static constexpr inline SizeHint sizeHint(const Self&) { return SizeHint(); } | |
66 | static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); } | ||
67 | }; | ||
68 | |||
69 | |||
70 | |||
71 | // ################################################################################################ | ||
72 | // GENERATOR REPEAT | ||
73 | // ################################################################################################ | ||
74 | /** @private */ | ||
75 | template<typename TItem> | ||
76 | class Repeater : public IterApi<Repeater<TItem>> { | ||
77 | friend struct trait::Iterator<Repeater<TItem>>; | ||
78 | friend struct trait::ExactSizeIterator<Repeater<TItem>>; | ||
79 | private: | ||
80 | TItem item; | ||
81 | std::optional<size_t> repetitions; | ||
82 | size_t repetitionsRemaining; | ||
83 | public: | ||
84 | 40 | Repeater(const TItem& item, std::optional<size_t> repetitions) : item(item), repetitions(repetitions), repetitionsRemaining(repetitions.value_or(0)) {} | |
85 | }; | ||
86 | // ------------------------------------------------------------------------------------------------ | ||
87 | /** @private */ | ||
88 | template<typename TItem> | ||
89 | struct trait::Iterator<Repeater<TItem>> { | ||
90 | // CXXIter Interface | ||
91 | using Self = Repeater<TItem>; | ||
92 | using Item = TItem; | ||
93 | |||
94 | 18 | static constexpr inline IterValue<Item> next(Self& self) { | |
95 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 7 times.
|
18 | if(self.repetitions.has_value()) { |
96 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if(self.repetitionsRemaining == 0) { return {}; } |
97 | 3 | self.repetitionsRemaining -= 1; | |
98 | } | ||
99 | 17 | return self.item; | |
100 | } | ||
101 | 24 | static constexpr inline SizeHint sizeHint(const Self& self) { | |
102 | return SizeHint( | ||
103 | self.repetitions.value_or(SizeHint::INFINITE), | ||
104 | self.repetitions | ||
105 | 24 | ); | |
106 | } | ||
107 | static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); } | ||
108 | }; | ||
109 | /** @private */ | ||
110 | template<typename TItem> | ||
111 | struct trait::ExactSizeIterator<Repeater<TItem>> { | ||
112 | 1 | static constexpr inline size_t size(const Repeater<TItem>& self) { return trait::Iterator<Repeater<TItem>>::sizeHint(self).lowerBound; } | |
113 | }; | ||
114 | |||
115 | |||
116 | |||
117 | // ################################################################################################ | ||
118 | // GENERATOR RANGE | ||
119 | // ################################################################################################ | ||
120 | /** @private */ | ||
121 | template<typename TValue> | ||
122 | class Range : public IterApi<Range<TValue>> { | ||
123 | friend struct trait::Iterator<Range<TValue>>; | ||
124 | friend struct trait::ExactSizeIterator<Range<TValue>>; | ||
125 | private: | ||
126 | TValue current; | ||
127 | TValue from; | ||
128 | TValue to; | ||
129 | TValue step; | ||
130 | public: | ||
131 | 6 | constexpr Range(TValue from, TValue to, TValue step) : current(from), from(from), to(to), step(step) {} | |
132 | }; | ||
133 | // ------------------------------------------------------------------------------------------------ | ||
134 | /** @private */ | ||
135 | template<typename TValue> | ||
136 | struct trait::Iterator<Range<TValue>> { | ||
137 | // CXXIter Interface | ||
138 | using Self = Range<TValue>; | ||
139 | using Item = TValue; | ||
140 | |||
141 | 26 | static constexpr inline IterValue<Item> next(Self& self) { | |
142 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
|
26 | if(self.current > self.to) [[unlikely]] { return {}; } |
143 | 21 | TValue current = self.current; | |
144 | 21 | self.current += self.step; | |
145 | 21 | return current; | |
146 | } | ||
147 | 7 | static constexpr inline SizeHint sizeHint(const Self& self) { | |
148 | 7 | size_t cnt = static_cast<size_t>((self.to - self.from) / self.step) + 1; | |
149 | 7 | return SizeHint(cnt, cnt); | |
150 | } | ||
151 | static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); } | ||
152 | }; | ||
153 | /** @private */ | ||
154 | template<typename TItem> | ||
155 | struct trait::ExactSizeIterator<Range<TItem>> { | ||
156 | 1 | static constexpr inline size_t size(const Range<TItem>& self) { return trait::Iterator<Range<TItem>>::sizeHint(self).lowerBound; } | |
157 | }; | ||
158 | |||
159 | |||
160 | |||
161 | #ifdef CXXITER_HAS_COROUTINE | ||
162 | // ################################################################################################ | ||
163 | // COROUTINE GENERATOR | ||
164 | // ################################################################################################ | ||
165 | /** @private */ | ||
166 | template<typename TGenerator> | ||
167 | class CoroutineGenerator : public IterApi<CoroutineGenerator<TGenerator>> { | ||
168 | friend struct trait::Iterator<CoroutineGenerator<TGenerator>>; | ||
169 | friend struct trait::ExactSizeIterator<CoroutineGenerator<TGenerator>>; | ||
170 | private: | ||
171 | TGenerator generator; | ||
172 | public: | ||
173 | 2 | CoroutineGenerator(TGenerator&& generator) : generator(std::forward<TGenerator>(generator)) {} | |
174 | }; | ||
175 | // ------------------------------------------------------------------------------------------------ | ||
176 | /** @private */ | ||
177 | template<typename TGeneratorFn> | ||
178 | struct trait::Iterator<CoroutineGenerator<TGeneratorFn>> { | ||
179 | // CXXIter Interface | ||
180 | using Self = CoroutineGenerator<TGeneratorFn>; | ||
181 | using Item = typename TGeneratorFn::value_type; | ||
182 | |||
183 | 1003 | static constexpr inline IterValue<Item> next(Self& self) { | |
184 | 1003 | return self.generator.next(); | |
185 | } | ||
186 | 2 | static constexpr inline SizeHint sizeHint(const Self&) { return SizeHint(); } | |
187 | static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); } | ||
188 | }; | ||
189 | #endif | ||
190 | |||
191 | } | ||
192 |