Embedded Template Library 1.0
Loading...
Searching...
No Matches
multi_range.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2020 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_MULTI_LOOP_INCLUDED
32#define ETL_MULTI_LOOP_INCLUDED
33
34#include "platform.h"
35#include "nullptr.h"
36#include "functional.h"
37#include "exception.h"
38#include "error_handler.h"
39
40namespace etl
41{
42 //***************************************************************************
44 //***************************************************************************
54
55 //***************************************************************************
57 //***************************************************************************
59 {
60 public:
61
63 : etl::multi_range_exception(ETL_ERROR_TEXT("multi_range:circular reference", ETL_MULTI_LOOP_FILE_ID"A"), file_name_, line_number_)
64 {
65 }
66 };
67
68 //***************************************************************************
70 //***************************************************************************
72 {
73 public:
74
75 //***************************************************************************
77 //***************************************************************************
79 {
81
82 // Remember what the next range was.
83 imulti_range* next = inner;
84
85 // Append the new range
86 inner = &inner_range;
87
88 // Link to the original next range.
89 inner_range.set_last(next);
90
91 return *this;
92 }
93
94 //***************************************************************************
96 //***************************************************************************
98 {
100
101 if (inner != ETL_NULLPTR)
102 {
103 inner->append(inner_range);
104 }
105 else
106 {
107 inner = &inner_range;
108 }
109
110 return *this;
111 }
112
113 //***************************************************************************
115 //***************************************************************************
116 void detach()
117 {
118 inner = ETL_NULLPTR;
119 }
120
121 //***************************************************************************
123 //***************************************************************************
125 {
126 if (inner != ETL_NULLPTR)
127 {
128 inner->detach_all();
129 }
130
131 detach();
132 }
133
134 //***************************************************************************
136 //***************************************************************************
137 bool completed() const
138 {
139 return has_completed;
140 }
141
142 //***************************************************************************
144 //***************************************************************************
145 size_t number_of_ranges() const
146 {
147 size_t count = 1UL;
148
149 imulti_range* p_range = inner;
150
151 while (p_range != ETL_NULLPTR)
152 {
153 ++count;
154 p_range = p_range->inner;
155 }
156
157 return count;
158 }
159
160 //***************************************************************************
162 //***************************************************************************
164 {
165 size_t count = 0UL;
166
167 for (start(); !completed(); next())
168 {
169 ++count;
170 }
171
172 return count;
173 }
174
175 //***************************************************************************
177 //***************************************************************************
178 virtual void next() = 0;
179 virtual void start() = 0;
180
181 protected:
182
183 //***************************************************************************
185 //***************************************************************************
187 : has_completed(true)
188 , inner(ETL_NULLPTR)
189 {
190 }
191
192 //***************************************************************************
194 //***************************************************************************
196 {
197 imulti_range* range = &inner_range;
198
199 while (range != ETL_NULLPTR)
200 {
201 if (range == this)
202 {
203 return false;
204 }
205
206 range = range->inner;
207 }
208
209 return true;
210 }
211
212 //***************************************************************************
214 //***************************************************************************
216 {
217 // Find the last range.
218 imulti_range* range = this;
219
220 while (range->inner != ETL_NULLPTR)
221 {
222 range = range->inner;
223 }
224
225 range->inner = next;
226 }
227
228 bool has_completed;
229 imulti_range* inner;
230 };
231
232 //***************************************************************************
235 //***************************************************************************
236 template <typename T>
238 {
239 public:
240
241 typedef T value_type;
242 typedef const T& const_reference;
243
244 //***************************************************************************
246 //***************************************************************************
248 {
249 typedef T value_type;
250
251 virtual void operator()(value_type& value) = 0;
252 };
253
254 //***************************************************************************
256 //***************************************************************************
257 struct forward_step : public step_type
258 {
259 typedef T value_type;
260
261 virtual void operator()(value_type& value)
262 {
263 ++value;
264 }
265 };
266
267 //***************************************************************************
269 //***************************************************************************
271 {
272 typedef T value_type;
273
274 explicit forward_step_by(const value_type& step_value_)
275 : step_value(step_value_)
276 {
277 }
278
279 virtual void operator()(value_type& value)
280 {
281 value += step_value;
282 }
283
284 const value_type step_value;
285 };
286
287 //***************************************************************************
289 //***************************************************************************
290 struct reverse_step : public step_type
291 {
292 typedef T value_type;
293
294 virtual void operator()(value_type& value)
295 {
296 --value;
297 }
298 };
299
300 //***************************************************************************
302 //***************************************************************************
304 {
305 typedef T value_type;
306
307 explicit reverse_step_by(const value_type& step_value_)
308 : step_value(step_value_)
309 {
310 }
311
312 virtual void operator()(value_type& value)
313 {
314 value -= step_value;
315 }
316
317 const value_type step_value;
318 };
319
320 //***************************************************************************
322 //***************************************************************************
324 {
325 typedef T value_type;
326
327 virtual bool operator()(const value_type& lhs, const value_type& rhs) const = 0;
328 };
329
330 //***************************************************************************
332 //***************************************************************************
334 {
335 typedef T value_type;
336
337 virtual bool operator()(const value_type& lhs, const value_type& rhs) const ETL_OVERRIDE
338 {
340 }
341 };
342
343 //***************************************************************************
345 //***************************************************************************
347 {
348 typedef T value_type;
349
350 virtual bool operator()(const value_type& lhs, const value_type& rhs) const ETL_OVERRIDE
351 {
352 return etl::less<value_type>()(lhs, rhs);
353 }
354 };
355
356 //***************************************************************************
358 //***************************************************************************
360 {
361 typedef T value_type;
362
363 virtual bool operator()(const value_type& lhs, const value_type& rhs) const ETL_OVERRIDE
364 {
366 }
367 };
368
369 //***************************************************************************
373 //***************************************************************************
376 : first(first_)
377 , last(last_)
378 , current(first_)
379 , p_stepper(&default_stepper)
380 , p_compare(&default_compare)
381 {
382 }
383
384 //***************************************************************************
388 //***************************************************************************
392 : first(first_)
393 , last(last_)
394 , current(first_)
395 , p_stepper(&stepper_)
396 , p_compare(&default_compare)
397 {
398 }
399
400 //***************************************************************************
404 //***************************************************************************
408 : first(first_)
409 , last(last_)
410 , current(first_)
411 , p_stepper(&default_stepper)
412 , p_compare(&compare_)
413 {
414 }
415
416 //***************************************************************************
420 //***************************************************************************
425 : first(first_)
426 , last(last_)
427 , current(first_)
428 , p_stepper(&stepper_)
429 , p_compare(&compare_)
430 {
431 }
432
433 //***************************************************************************
435 //***************************************************************************
437 {
438 return first;
439 }
440
441 //***************************************************************************
444 //***************************************************************************
446 {
447 return last;
448 }
449
450 //***************************************************************************
452 //***************************************************************************
453 void start() ETL_OVERRIDE
454 {
455 if (inner != ETL_NULLPTR)
456 {
457 inner->start();
458 }
459
460 current = first;
461 has_completed = !(*p_compare)(current, last); // Check for null range.
462 }
463
464 //***************************************************************************
466 //***************************************************************************
467 void next() ETL_OVERRIDE
468 {
469 has_completed = false;
470
471 if (inner != ETL_NULLPTR)
472 {
473 inner->next();
474
475 if (inner->completed())
476 {
477 has_completed = step();
478 }
479 }
480 else
481 {
482 has_completed = step();
483 }
484 }
485
486 //***************************************************************************
488 //***************************************************************************
490 {
491 return current;
492 }
493
494 private:
495
496 //***************************************************************************
498 //***************************************************************************
499 bool step()
500 {
501 (*p_stepper)(current);
502
503 const bool has_rolled_over = !(*p_compare)(current, last);
504
505 if (has_rolled_over)
506 {
507 current = first;
508 }
509
510 return has_rolled_over;
511 }
512
513 multi_range() ETL_DELETE;
514 multi_range(const multi_range&) ETL_DELETE;
515 multi_range& operator =(const multi_range&) ETL_DELETE;
516
517 value_type first;
518 value_type last;
519 value_type current;
520
521 step_type* p_stepper;
522 forward_step default_stepper;
523
524 compare_type* p_compare;
525 not_equal_compare default_compare;
526 };
527}
528
529#endif
The base class for multi_range.
Definition multi_range.h:72
virtual void next()=0
Pure virtual functions.
imulti_range()
Constructor.
Definition multi_range.h:186
size_t number_of_iterations()
Gets the total number of iterations over all ranges, from this range inclusive.
Definition multi_range.h:163
void set_last(imulti_range *next)
Set the inner range of the last linked range.
Definition multi_range.h:215
void detach_all()
Unlinks this and all inner ranges.
Definition multi_range.h:124
bool is_valid(imulti_range &inner_range)
Checks that there are no circular references.
Definition multi_range.h:195
imulti_range & insert(imulti_range &inner_range)
Insert after this range.
Definition multi_range.h:78
void detach()
Unlinks this range from its inner.
Definition multi_range.h:116
size_t number_of_ranges() const
Gets the total number of ranges, from this range inclusive.
Definition multi_range.h:145
imulti_range & append(imulti_range &inner_range)
Append to the most inner range.
Definition multi_range.h:97
Circular reference exception.
Definition multi_range.h:59
Exception for the multi_range.
Definition multi_range.h:46
Definition multi_range.h:238
const_reference end()
Definition multi_range.h:445
void start() ETL_OVERRIDE
Initialises the ranges to the starting values.
Definition multi_range.h:453
multi_range(value_type first_, value_type last_)
Definition multi_range.h:374
multi_range(value_type first_, value_type last_, compare_type &compare_)
Definition multi_range.h:405
const_reference begin()
Get a const reference to the starting value of the range.
Definition multi_range.h:436
multi_range(value_type first_, value_type last_, step_type &stepper_, compare_type &compare_)
Definition multi_range.h:421
const_reference value() const
Returns a const reference to the current range value.
Definition multi_range.h:489
void next() ETL_OVERRIDE
Step to the next logical values in the ranges.
Definition multi_range.h:467
multi_range(value_type first_, value_type last_, step_type &stepper_)
Definition multi_range.h:389
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
Definition exception.h:47
bitset_ext
Definition absolute.h:38
Definition multi_range.h:324
Definition multi_range.h:271
Definition multi_range.h:258
Definition multi_range.h:360
Definition multi_range.h:347
Definition multi_range.h:334
Definition multi_range.h:304
Definition multi_range.h:291
Definition multi_range.h:248
pair holds two objects of arbitrary type
Definition utility.h:164