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 "error_handler.h"
36#include "exception.h"
37#include "functional.h"
38#include "nullptr.h"
39
40namespace etl
41{
42 //***************************************************************************
44 //***************************************************************************
45 class multi_range_exception : public etl::exception
46 {
47 public:
48
49 multi_range_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
50 : exception(reason_, file_name_, line_number_)
51 {
52 }
53 };
54
55 //***************************************************************************
57 //***************************************************************************
58 class multi_range_circular_reference : public etl::multi_range_exception
59 {
60 public:
61
62 multi_range_circular_reference(string_type file_name_, numeric_type line_number_)
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 {
80 ETL_ASSERT(is_valid(inner_range), ETL_ERROR(multi_range_circular_reference));
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 {
99 ETL_ASSERT(is_valid(inner_range), ETL_ERROR(multi_range_circular_reference));
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 //***************************************************************************
163 //***************************************************************************
165 {
166 size_t count = 0UL;
167
168 for (start(); !completed(); next())
169 {
170 ++count;
171 }
172
173 return count;
174 }
175
176 //***************************************************************************
178 //***************************************************************************
179 virtual void next() = 0;
180 virtual void start() = 0;
181
182 protected:
183
184 //***************************************************************************
186 //***************************************************************************
188 : has_completed(true)
189 , inner(ETL_NULLPTR)
190 {
191 }
192
193 //***************************************************************************
195 //***************************************************************************
196 bool is_valid(imulti_range& inner_range)
197 {
198 imulti_range* range = &inner_range;
199
200 while (range != ETL_NULLPTR)
201 {
202 if (range == this)
203 {
204 return false;
205 }
206
207 range = range->inner;
208 }
209
210 return true;
211 }
212
213 //***************************************************************************
215 //***************************************************************************
217 {
218 // Find the last range.
219 imulti_range* range = this;
220
221 while (range->inner != ETL_NULLPTR)
222 {
223 range = range->inner;
224 }
225
226 range->inner = next;
227 }
228
229 bool has_completed;
230 imulti_range* inner;
231 };
232
233 //***************************************************************************
236 //***************************************************************************
237 template <typename T>
239 {
240 public:
241
242 typedef T value_type;
243 typedef const T& const_reference;
244
245 //***************************************************************************
247 //***************************************************************************
249 {
250 typedef T value_type;
251
252 virtual void operator()(value_type& value) = 0;
253 };
254
255 //***************************************************************************
257 //***************************************************************************
258 struct forward_step : public step_type
259 {
260 typedef T value_type;
261
262 virtual void operator()(value_type& value)
263 {
264 ++value;
265 }
266 };
267
268 //***************************************************************************
270 //***************************************************************************
271 struct forward_step_by : public step_type
272 {
273 typedef T value_type;
274
275 explicit forward_step_by(const value_type& step_value_)
276 : step_value(step_value_)
277 {
278 }
279
280 virtual void operator()(value_type& value)
281 {
282 value += step_value;
283 }
284
285 const value_type step_value;
286 };
287
288 //***************************************************************************
290 //***************************************************************************
291 struct reverse_step : public step_type
292 {
293 typedef T value_type;
294
295 virtual void operator()(value_type& value)
296 {
297 --value;
298 }
299 };
300
301 //***************************************************************************
303 //***************************************************************************
304 struct reverse_step_by : public step_type
305 {
306 typedef T value_type;
307
308 explicit reverse_step_by(const value_type& step_value_)
309 : step_value(step_value_)
310 {
311 }
312
313 virtual void operator()(value_type& value)
314 {
315 value -= step_value;
316 }
317
318 const value_type step_value;
319 };
320
321 //***************************************************************************
323 //***************************************************************************
325 {
326 typedef T value_type;
327
328 virtual bool operator()(const value_type& lhs, const value_type& rhs) const = 0;
329 };
330
331 //***************************************************************************
333 //***************************************************************************
335 {
336 typedef T value_type;
337
338 virtual bool operator()(const value_type& lhs, const value_type& rhs) const ETL_OVERRIDE
339 {
340 return etl::not_equal_to<value_type>()(lhs, rhs);
341 }
342 };
343
344 //***************************************************************************
346 //***************************************************************************
348 {
349 typedef T value_type;
350
351 virtual bool operator()(const value_type& lhs, const value_type& rhs) const ETL_OVERRIDE
352 {
353 return etl::less<value_type>()(lhs, rhs);
354 }
355 };
356
357 //***************************************************************************
359 //***************************************************************************
361 {
362 typedef T value_type;
363
364 virtual bool operator()(const value_type& lhs, const value_type& rhs) const ETL_OVERRIDE
365 {
366 return etl::greater<value_type>()(lhs, rhs);
367 }
368 };
369
370 //***************************************************************************
375 //***************************************************************************
376 multi_range(value_type first_, value_type last_)
377 : first(first_)
378 , last(last_)
379 , current(first_)
380 , p_stepper(&default_stepper)
381 , p_compare(&default_compare)
382 {
383 }
384
385 //***************************************************************************
390 //***************************************************************************
391 multi_range(value_type first_, value_type last_, step_type& stepper_)
392 : first(first_)
393 , last(last_)
394 , current(first_)
395 , p_stepper(&stepper_)
396 , p_compare(&default_compare)
397 {
398 }
399
400 //***************************************************************************
404 //***************************************************************************
405 multi_range(value_type first_, value_type last_, compare_type& compare_)
406 : first(first_)
407 , last(last_)
408 , current(first_)
409 , p_stepper(&default_stepper)
410 , p_compare(&compare_)
411 {
412 }
413
414 //***************************************************************************
419 //***************************************************************************
420 multi_range(value_type first_, value_type last_, step_type& stepper_, compare_type& compare_)
421 : first(first_)
422 , last(last_)
423 , current(first_)
424 , p_stepper(&stepper_)
425 , p_compare(&compare_)
426 {
427 }
428
429 //***************************************************************************
431 //***************************************************************************
432 const_reference begin()
433 {
434 return first;
435 }
436
437 //***************************************************************************
440 //***************************************************************************
441 const_reference end()
442 {
443 return last;
444 }
445
446 //***************************************************************************
448 //***************************************************************************
449 void start() ETL_OVERRIDE
450 {
451 if (inner != ETL_NULLPTR)
452 {
453 inner->start();
454 }
455
456 current = first;
457 has_completed = !(*p_compare)(current, last); // Check for null range.
458 }
459
460 //***************************************************************************
462 //***************************************************************************
463 void next() ETL_OVERRIDE
464 {
465 has_completed = false;
466
467 if (inner != ETL_NULLPTR)
468 {
469 inner->next();
470
471 if (inner->completed())
472 {
473 has_completed = step();
474 }
475 }
476 else
477 {
478 has_completed = step();
479 }
480 }
481
482 //***************************************************************************
484 //***************************************************************************
485 const_reference value() const
486 {
487 return current;
488 }
489
490 private:
491
492 //***************************************************************************
494 //***************************************************************************
495 bool step()
496 {
497 (*p_stepper)(current);
498
499 const bool has_rolled_over = !(*p_compare)(current, last);
500
501 if (has_rolled_over)
502 {
503 current = first;
504 }
505
506 return has_rolled_over;
507 }
508
509 multi_range() ETL_DELETE;
510 multi_range(const multi_range&) ETL_DELETE;
511 multi_range& operator=(const multi_range&) ETL_DELETE;
512
513 value_type first;
514 value_type last;
515 value_type current;
516
517 step_type* p_stepper;
518 forward_step default_stepper;
519
520 compare_type* p_compare;
521 not_equal_compare default_compare;
522 };
523} // namespace etl
524
525#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:187
size_t number_of_iterations()
Definition multi_range.h:164
void set_last(imulti_range *next)
Set the inner range of the last linked range.
Definition multi_range.h:216
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:196
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
const_reference end()
Definition multi_range.h:441
void start() ETL_OVERRIDE
Initialises the ranges to the starting values.
Definition multi_range.h:449
multi_range(value_type first_, value_type last_)
Definition multi_range.h:376
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:432
multi_range(value_type first_, value_type last_, step_type &stepper_, compare_type &compare_)
Definition multi_range.h:420
const_reference value() const
Returns a const reference to the current range value.
Definition multi_range.h:485
void next() ETL_OVERRIDE
Step to the next logical values in the ranges.
Definition multi_range.h:463
multi_range(value_type first_, value_type last_, step_type &stepper_)
Definition multi_range.h:391
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
bitset_ext
Definition absolute.h:40
Definition functional.h:253
Definition functional.h:201
Definition multi_range.h:325
Definition multi_range.h:259
Definition multi_range.h:361
Definition multi_range.h:348
Definition multi_range.h:335
Definition multi_range.h:292
Definition multi_range.h:249
Definition functional.h:332