@@ -136,69 +136,57 @@ SeriesIterator::SeriesIterator(Series series) : m_series(std::move(series))
136136 }
137137}
138138
139- SeriesIterator &SeriesIterator::operator ++()
139+ std::optional<SeriesIterator *>
140+ SeriesIterator::nextIterationInStep (Iteration ¤tIteration)
140141{
141- if (!m_series.has_value ())
142+ using ret_t = std::optional<SeriesIterator *>;
143+
144+ m_iterationsInCurrentStep.pop_front ();
145+ if (m_iterationsInCurrentStep.empty ())
142146 {
143- *this = end ();
144- return *this ;
147+ return ret_t {};
145148 }
146- Series &series = m_series.value ();
147- auto &iterations = series.iterations ;
148- auto ¤tIteration = iterations[m_currentIteration];
149149 auto oldIterationIndex = m_currentIteration;
150+ m_currentIteration = *m_iterationsInCurrentStep.begin ();
151+ auto &series = m_series.value ();
150152
151- m_iterationsInCurrentStep.pop_front ();
152- if (!m_iterationsInCurrentStep.empty ())
153+ switch (series.iterationEncoding ())
153154 {
154- m_currentIteration = *m_iterationsInCurrentStep.begin ();
155- switch (series.iterationEncoding ())
155+ case IterationEncoding::groupBased:
156+ case IterationEncoding::variableBased: {
157+ if (!currentIteration.closed ())
156158 {
157- case IterationEncoding::groupBased:
158- case IterationEncoding::variableBased: {
159- if (!currentIteration.closed ())
160- {
161- currentIteration.get ().m_closed =
162- internal::CloseStatus::ClosedInFrontend;
163- }
164- auto begin = series.iterations .find (oldIterationIndex);
165- auto end = begin;
166- ++end;
167- series.flush_impl (
168- begin,
169- end,
170- FlushLevel::UserFlush,
171- /* flushIOHandler = */ true );
172-
173- series.iterations [m_currentIteration].open ();
174- return *this ;
175- }
176- case IterationEncoding::fileBased:
177- if (!currentIteration.closed ())
178- {
179- currentIteration.close ();
180- }
181- series.iterations [m_currentIteration].open ();
182- series.iterations [m_currentIteration].beginStep ();
183- return *this ;
159+ currentIteration.get ().m_closed =
160+ internal::CloseStatus::ClosedInFrontend;
184161 }
185- throw std::runtime_error (" Unreachable!" );
186- }
162+ auto begin = series.iterations .find (oldIterationIndex);
163+ auto end = begin;
164+ ++end;
165+ series.flush_impl (
166+ begin,
167+ end,
168+ FlushLevel::UserFlush,
169+ /* flushIOHandler = */ true );
187170
188- // The currently active iterations have been exhausted.
189- // Now see if there are further iterations to be found.
190-
191- if (series.iterationEncoding () == IterationEncoding::fileBased)
192- {
193- // this one is handled above, stream is over once it proceeds to here
194- *this = end ();
195- return *this ;
171+ series.iterations [m_currentIteration].open ();
172+ return {this };
196173 }
197-
198- if (!currentIteration.closed ())
199- {
200- currentIteration.close ();
174+ case IterationEncoding::fileBased:
175+ if (!currentIteration.closed ())
176+ {
177+ currentIteration.close ();
178+ }
179+ series.iterations [m_currentIteration].open ();
180+ series.iterations [m_currentIteration].beginStep ();
181+ return {this };
201182 }
183+ throw std::runtime_error (" Unreachable!" );
184+ }
185+
186+ std::optional<SeriesIterator *>
187+ SeriesIterator::nextStep (Iteration ¤tIteration)
188+ {
189+ using ret_t = std::optional<SeriesIterator *>;
202190
203191 // since we are in group-based iteration layout, it does not
204192 // matter which iteration we begin a step upon
@@ -217,18 +205,19 @@ SeriesIterator &SeriesIterator::operator++()
217205 * Fallback implementation: Assume that each step corresponds
218206 * with an iteration in ascending order.
219207 */
220- auto it = iterations.find (m_currentIteration);
221- auto itEnd = iterations.end ();
208+ auto &series = m_series.value ();
209+ auto it = series.iterations .find (m_currentIteration);
210+ auto itEnd = series.iterations .end ();
222211 if (it == itEnd)
223212 {
224213 *this = end ();
225- return * this ;
214+ return { this } ;
226215 }
227216 ++it;
228217 if (it == itEnd)
229218 {
230219 *this = end ();
231- return * this ;
220+ return { this } ;
232221 }
233222 m_iterationsInCurrentStep = {it->first };
234223 }
@@ -237,8 +226,51 @@ SeriesIterator &SeriesIterator::operator++()
237226 if (status == AdvanceStatus::OVER)
238227 {
239228 *this = end ();
240- return *this ;
229+ return {this };
230+ }
231+
232+ return ret_t {};
233+ }
234+
235+ std::optional<SeriesIterator *> SeriesIterator::loopBody ()
236+ {
237+ using ret_t = std::optional<SeriesIterator *>;
238+
239+ Series &series = m_series.value ();
240+ auto &iterations = series.iterations ;
241+ auto ¤tIteration = iterations[m_currentIteration];
242+
243+ {
244+ auto option = nextIterationInStep (currentIteration);
245+ if (option.has_value ())
246+ {
247+ return option;
248+ }
241249 }
250+
251+ // The currently active iterations have been exhausted.
252+ // Now see if there are further iterations to be found.
253+
254+ if (series.iterationEncoding () == IterationEncoding::fileBased)
255+ {
256+ // this one is handled above, stream is over once it proceeds to here
257+ *this = end ();
258+ return {this };
259+ }
260+
261+ if (!currentIteration.closed ())
262+ {
263+ currentIteration.close ();
264+ }
265+
266+ {
267+ auto option = nextStep (currentIteration);
268+ if (option.has_value ())
269+ {
270+ return option;
271+ }
272+ }
273+
242274 currentIteration.setStepStatus (StepStatus::DuringStep);
243275
244276 auto iteration = iterations.at (m_currentIteration);
@@ -248,12 +280,31 @@ SeriesIterator &SeriesIterator::operator++()
248280 }
249281 else
250282 {
251- // we had this one already, skip it
252- // @todo remove recursive call
283+ // we had this iteration already, skip it
253284 iteration.endStep ();
254- return operator ++();
285+ return ret_t {}; // empty, go into next iteration
286+ }
287+ return {this };
288+ }
289+
290+ SeriesIterator &SeriesIterator::operator ++()
291+ {
292+ if (!m_series.has_value ())
293+ {
294+ *this = end ();
295+ return *this ;
255296 }
256- return *this ;
297+ std::optional<SeriesIterator *> res;
298+ /*
299+ * loopBody() might return an empty option to indicate a skipped iteration.
300+ * Loop until it returns something real for us.
301+ */
302+ do
303+ {
304+ res = loopBody ();
305+ } while (!res.has_value ());
306+
307+ return *res.value ();
257308}
258309
259310IndexedIteration SeriesIterator::operator *()
0 commit comments