Embedded Template Library 1.0
circular_iterator.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) 2022 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_CIRCULAR_ITERATOR_INCLUDED
32#define ETL_CIRCULAR_ITERATOR_INCLUDED
33
34#include "platform.h"
35#include "iterator.h"
36#include "static_assert.h"
37
39
40namespace etl
41{
42 namespace private_circular_iterator
43 {
44 //***************************************************************************
46 //***************************************************************************
47 template <typename TIterator>
49 : public etl::iterator<typename etl::iterator_traits<TIterator>::iterator_category, typename etl::iterator_traits<TIterator>::value_type>
50 {
51 public:
52
53 typedef typename etl::iterator_traits<TIterator>::value_type value_type;
54 typedef typename etl::iterator_traits<TIterator>::difference_type difference_type;
55 typedef typename etl::iterator_traits<TIterator>::pointer pointer;
56 typedef typename etl::iterator_traits<TIterator>::reference reference;
57 typedef typename etl::iterator_traits<TIterator>::iterator_category iterator_category;
58
59 //***************************************************************************
61 //***************************************************************************
62 ETL_CONSTEXPR14 circular_iterator_common()
63 : itr_begin(TIterator())
64 , itr_end(TIterator())
65 , itr(TIterator())
66 {
67 }
68
69 //***************************************************************************
71 //***************************************************************************
72 ETL_CONSTEXPR14 circular_iterator_common(TIterator itr_begin_, TIterator itr_end_, TIterator start_)
73 : itr_begin(itr_begin_)
74 , itr_end(itr_end_)
75 , itr(start_)
76 {
77 }
78
79 //***************************************************************************
81 //***************************************************************************
83 : itr_begin(other.itr_begin)
84 , itr_end(other.itr_end)
85 , itr(other.itr)
86 {
87 }
88
89 //***************************************************************************
91 //***************************************************************************
93 {
94 itr_begin = other.itr_begin;
95 itr_end = other.itr_end;
96 itr = other.itr;
97
98 return *this;
99 }
100
101 //***************************************************************************
103 //***************************************************************************
104 ETL_CONSTEXPR14 TIterator begin() const
105 {
106 return itr_begin;
107 }
108
109 //***************************************************************************
111 //***************************************************************************
112 ETL_CONSTEXPR14 TIterator end() const
113 {
114 return itr_end;
115 }
116
117 //***************************************************************************
119 //***************************************************************************
120 ETL_CONSTEXPR14 size_t size() const
121 {
122 return etl::distance(itr_begin, itr_end);
123 }
124
125 //***************************************************************************
127 //***************************************************************************
128 ETL_CONSTEXPR14 bool empty() const
129 {
130 return (itr_begin == itr_end);
131 }
132
133 //***************************************************************************
135 //***************************************************************************
136 ETL_CONSTEXPR14 value_type operator *()
137 {
138 return *itr;
139 }
140
141 //***************************************************************************
143 //***************************************************************************
144 ETL_CONSTEXPR14 const value_type operator *() const
145 {
146 return *itr;
147 }
148
149 //***************************************************************************
151 //***************************************************************************
152 ETL_CONSTEXPR14 TIterator operator ->()
153 {
154 return itr;
155 }
156
157 //***************************************************************************
159 //***************************************************************************
160 ETL_CONSTEXPR14 const TIterator operator ->() const
161 {
162 return itr;
163 }
164
165 //***************************************************************************
167 //***************************************************************************
168 ETL_CONSTEXPR14 operator TIterator() const
169 {
170 return itr;
171 }
172
173 //***************************************************************************
175 //***************************************************************************
176 ETL_CONSTEXPR14 TIterator current() const
177 {
178 return itr;
179 }
180
181 protected:
182
183 TIterator itr_begin;
184 TIterator itr_end;
185 TIterator itr;
186 };
187
188 //***************************************************************************
192 //***************************************************************************
193 template <typename TIterator, typename TTag = typename etl::iterator_traits<TIterator>::iterator_category>
195 {
196 ETL_STATIC_ASSERT((etl::is_same<TTag, ETL_OR_STD::input_iterator_tag>::value_type), "input_iterator_catagory is not supported by circular_iterator");
197 ETL_STATIC_ASSERT((etl::is_same<TTag, ETL_OR_STD::output_iterator_tag>::value_type), "output_iterator_catagory is not supported by circular_iterator");
198 };
199
200 //***************************************************************************
205 template <typename TIterator>
206 class circular_iterator_impl<TIterator, ETL_OR_STD::forward_iterator_tag>
207 : public circular_iterator_common<TIterator>
208 {
209 private:
210
212
213 public:
214
215 using common_t::operator=;
216
217 typedef typename common_t::value_type value_type;
218 typedef typename common_t::difference_type difference_type;
219 typedef typename common_t::pointer pointer;
220 typedef typename common_t::reference reference;
221 typedef typename common_t::iterator_category iterator_category;
222
223 //***************************************************************************
225 //***************************************************************************
226 ETL_CONSTEXPR14 circular_iterator_impl()
227 : common_t()
228 {
229 }
230
231 //***************************************************************************
233 //***************************************************************************
234 ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_)
235 : common_t(itr_begin_, itr_end_, itr_begin_)
236 {
237 }
238
239 //***************************************************************************
241 //***************************************************************************
242 ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_, TIterator start_)
243 : common_t(itr_begin_, itr_end_, start_)
244 {
245 }
246
247 //***************************************************************************
249 //***************************************************************************
250 ETL_CONSTEXPR14 circular_iterator_impl(const circular_iterator_impl& other)
251 : common_t(other)
252 {
253 }
254
255 //***************************************************************************
257 //***************************************************************************
258 ETL_CONSTEXPR14 circular_iterator_impl& operator =(const circular_iterator_impl& other)
259 {
260 common_t::operator=(other);
261
262 return *this;
263 }
264
265 //***************************************************************************
267 //***************************************************************************
268 ETL_CONSTEXPR14 circular_iterator_impl& operator ++()
269 {
270 if (++this->itr == this->itr_end)
271 {
272 this->itr = this->itr_begin;
273 }
274
275 return *this;
276 }
277
278 //***************************************************************************
280 //***************************************************************************
281 ETL_CONSTEXPR14 circular_iterator_impl operator ++(int)
282 {
283 circular_iterator_impl original(*this);
284
285 ++(*this);
286
287 return (original);
288 }
289 };
290
291 //***************************************************************************
296 template <typename TIterator>
298 : public circular_iterator_common<TIterator>
299 {
300 private:
301
303
304 public:
305
306 using common_t::operator=;
307
308 typedef typename common_t::value_type value_type;
309 typedef typename common_t::difference_type difference_type;
310 typedef typename common_t::pointer pointer;
311 typedef typename common_t::reference reference;
312 typedef typename common_t::iterator_category iterator_category;
313
314 //***************************************************************************
316 //***************************************************************************
317 ETL_CONSTEXPR14 circular_iterator_impl()
318 : common_t()
319 {
320 }
321
322 //***************************************************************************
324 //***************************************************************************
325 ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_)
326 : common_t(itr_begin_, itr_end_, itr_begin_)
327 {
328 }
329
330 //***************************************************************************
332 //***************************************************************************
333 ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_, TIterator start_)
334 : common_t(itr_begin_, itr_end_, start_)
335 {
336 }
337
338 //***************************************************************************
340 //***************************************************************************
341 ETL_CONSTEXPR14 circular_iterator_impl(const circular_iterator_impl& other)
342 : common_t(other)
343 {
344 }
345
346 //***************************************************************************
348 //***************************************************************************
349 ETL_CONSTEXPR14 circular_iterator_impl& operator =(const circular_iterator_impl& other)
350 {
351 common_t::operator=(other);
352
353 return *this;
354 }
355
356 //***************************************************************************
358 //***************************************************************************
359 ETL_CONSTEXPR14 circular_iterator_impl& operator ++()
360 {
361 if (++this->itr == this->itr_end)
362 {
363 this->itr = this->itr_begin;
364 }
365
366 return *this;
367 }
368
369 //***************************************************************************
371 //***************************************************************************
372 ETL_CONSTEXPR14 circular_iterator_impl operator ++(int)
373 {
374 circular_iterator_impl original(*this);
375
376 ++(*this);
377
378 return (original);
379 }
380
381 //***************************************************************************
383 //***************************************************************************
384 ETL_CONSTEXPR14 circular_iterator_impl& operator --()
385 {
386 if (this->itr == this->itr_begin)
387 {
388 typename etl::reverse_iterator<TIterator> ritr(this->itr_end);
389 ++ritr;
390 this->itr = ritr.base();
391 }
392 else
393 {
394 --this->itr;
395 }
396
397 return *this;
398 }
399
400 //***************************************************************************
402 //***************************************************************************
403 ETL_CONSTEXPR14 circular_iterator_impl operator --(int)
404 {
405 circular_iterator_impl original(*this);
406
407 --(*this);
408
409 return (original);
410 }
411 };
412
413 //***************************************************************************
417 //***************************************************************************
418 template <typename TIterator>
421 {
422 private:
423
425
426 public:
427
428 using common_t::operator=;
429
430 typedef typename common_t::value_type value_type;
431 typedef typename common_t::difference_type difference_type;
432 typedef typename common_t::pointer pointer;
433 typedef typename common_t::reference reference;
434 typedef typename common_t::iterator_category iterator_category;
435
436 //***************************************************************************
438 //***************************************************************************
439 ETL_CONSTEXPR14 circular_iterator_impl()
440 : common_t()
441 {
442 }
443
444 //***************************************************************************
446 //***************************************************************************
447 ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_)
448 : common_t(itr_begin_, itr_end_, itr_begin_)
449 {
450 }
451
452 //***************************************************************************
454 //***************************************************************************
455 ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_, TIterator start_)
456 : common_t(itr_begin_, itr_end_, start_)
457 {
458 }
459
460 //***************************************************************************
462 //***************************************************************************
463 ETL_CONSTEXPR14 circular_iterator_impl(const circular_iterator_impl& other)
464 : common_t(other)
465 {
466 }
467
468 //***************************************************************************
470 //***************************************************************************
471 ETL_CONSTEXPR14 circular_iterator_impl& operator =(const circular_iterator_impl& other)
472 {
473 common_t::operator=(other);
474
475 return *this;
476 }
477
478 //***************************************************************************
480 //***************************************************************************
481 ETL_CONSTEXPR14 circular_iterator_impl& operator ++()
482 {
483 if (++this->itr == this->itr_end)
484 {
485 this->itr = this->itr_begin;
486 }
487
488 return *this;
489 }
490
491 //***************************************************************************
493 //***************************************************************************
494 ETL_CONSTEXPR14 circular_iterator_impl operator ++(int)
495 {
496 circular_iterator_impl original(*this);
497
498 ++(*this);
499
500 return (original);
501 }
502
503 //***************************************************************************
505 //***************************************************************************
506 ETL_CONSTEXPR14 circular_iterator_impl& operator --()
507 {
508 if (this->itr == this->itr_begin)
509 {
510 typename etl::reverse_iterator<TIterator> ritr(this->itr_end);
511 ++ritr;
512 this->itr = ritr.base();
513 }
514 else
515 {
516 --this->itr;
517 }
518
519 return *this;
520 }
521
522 //***************************************************************************
524 //***************************************************************************
525 ETL_CONSTEXPR14 circular_iterator_impl operator --(int)
526 {
527 circular_iterator_impl original(*this);
528
529 --(*this);
530
531 return (original);
532 }
533
534 //***************************************************************************
536 //***************************************************************************
537 ETL_CONSTEXPR14 circular_iterator_impl& operator +=(difference_type offset)
538 {
539 const difference_type length = difference_type(this->size());
540 offset %= length;
541
542 if (offset != 0)
543 {
544 const difference_type distance_from_begin = etl::distance(this->itr_begin, this->itr);
545 const difference_type distance_to_end = etl::distance(this->itr, this->itr_end);
546
547 if (offset > 0)
548 {
549 if (distance_to_end > offset)
550 {
551 offset = distance_from_begin + offset;
552 }
553 else
554 {
555 offset = offset - distance_to_end;
556 }
557 }
558 else
559 {
560 offset = -offset;
561
562 if (distance_from_begin >= offset)
563 {
564 offset = distance_from_begin - offset;
565 }
566 else
567 {
568 offset = offset - distance_from_begin;
569 offset = length - offset;
570 }
571 }
572
573 this->itr = this->itr_begin + offset;
574 }
575
576 return *this;
577 }
578
579 //***************************************************************************
581 //***************************************************************************
582 ETL_CONSTEXPR14 circular_iterator_impl& operator -=(typename etl::iterator_traits<TIterator>::difference_type offset)
583 {
584 return operator +=(-offset);
585 }
586 };
587 }
588
589 //***************************************************************************
593 //**************************************************************************
594 template <typename TIterator>
595 class circular_iterator ETL_FINAL
596 : public etl::private_circular_iterator::circular_iterator_impl<TIterator, typename etl::iterator_traits<TIterator>::iterator_category>
597 {
598 private:
599
601
602 public:
603
604 using impl_t::operator=;
605
606 typedef typename impl_t::value_type value_type;
607 typedef typename impl_t::difference_type difference_type;
608 typedef typename impl_t::pointer pointer;
609 typedef typename impl_t::reference reference;
610 typedef typename impl_t::iterator_category iterator_category;
611
612 //***************************************************************************
614 //***************************************************************************
615 ETL_CONSTEXPR14 circular_iterator()
616 : impl_t()
617 {
618 }
619
620 //***************************************************************************
622 //***************************************************************************
623 ETL_CONSTEXPR14 circular_iterator(TIterator itr_begin_, TIterator itr_end_)
624 : impl_t(itr_begin_, itr_end_, itr_begin_)
625 {
626 }
627
628 //***************************************************************************
630 //***************************************************************************
631 ETL_CONSTEXPR14 circular_iterator(TIterator itr_begin_, TIterator itr_end_, TIterator start_)
632 : impl_t(itr_begin_, itr_end_, start_)
633 {
634 }
635
636 //***************************************************************************
638 //***************************************************************************
639 ETL_CONSTEXPR14 circular_iterator(const circular_iterator& other)
640 : impl_t(other)
641 {
642 }
643
644 //***************************************************************************
646 //***************************************************************************
647 ETL_CONSTEXPR14 circular_iterator& operator =(const circular_iterator& other)
648 {
649 impl_t::operator=(other);
650
651 return *this;
652 }
653 };
654
655 //*****************************************************************************
657 //*****************************************************************************
658 template <typename TIterator>
659 ETL_CONSTEXPR14 etl::circular_iterator<TIterator> operator +(etl::circular_iterator<TIterator>& lhs,
660 typename etl::iterator_traits<TIterator>::difference_type offset)
661 {
662 etl::circular_iterator<TIterator> result(lhs);
663 result += offset;
664
665 return result;
666 }
667
668 //*****************************************************************************
670 //*****************************************************************************
671 template <typename TIterator>
672 ETL_CONSTEXPR14 etl::circular_iterator<TIterator> operator -(etl::circular_iterator<TIterator>& lhs,
673 typename etl::iterator_traits<TIterator>::difference_type offset)
674 {
675 etl::circular_iterator<TIterator> result(lhs);
676 result -= offset;
677
678 return result;
679 }
680
681 //*****************************************************************************
683 //*****************************************************************************
684 template <typename TIterator>
685 ETL_CONSTEXPR14 typename etl::iterator_traits<TIterator>::difference_type operator -(etl::circular_iterator<TIterator>& lhs,
686 etl::circular_iterator<TIterator>& rhs)
687 {
688 return TIterator(lhs) - TIterator(rhs);
689 }
690
691 //*****************************************************************************
693 //*****************************************************************************
694 template <typename TIterator>
695 ETL_CONSTEXPR14 bool operator ==(const etl::circular_iterator<TIterator>& lhs,
696 const etl::circular_iterator<TIterator>& rhs)
697 {
698 return TIterator(lhs) == TIterator(rhs);
699 }
700
701 //*****************************************************************************
703 //*****************************************************************************
704 template <typename TIterator>
705 ETL_CONSTEXPR14 bool operator ==(const etl::circular_iterator<TIterator>& lhs,
706 TIterator rhs)
707 {
708 return TIterator(lhs) == rhs;
709 }
710
711 //*****************************************************************************
713 //*****************************************************************************
714 template <typename TIterator>
715 ETL_CONSTEXPR14 bool operator ==(TIterator lhs,
716 const etl::circular_iterator<TIterator>& rhs)
717 {
718 return lhs == TIterator(rhs);
719 }
720
721
722 //*****************************************************************************
724 //*****************************************************************************
725 template <typename TIterator>
726 ETL_CONSTEXPR14 bool operator !=(const etl::circular_iterator<TIterator>& lhs,
727 const etl::circular_iterator<TIterator>& rhs)
728 {
729 return !(lhs == rhs);
730 }
731
732 //*****************************************************************************
734 //*****************************************************************************
735 template <typename TIterator>
736 ETL_CONSTEXPR14 bool operator !=(const etl::circular_iterator<TIterator>& lhs,
737 TIterator rhs)
738 {
739 return !(lhs == rhs);
740 }
741
742 //*****************************************************************************
744 //*****************************************************************************
745 template <typename TIterator>
746 ETL_CONSTEXPR14 bool operator !=(TIterator& lhs,
747 const etl::circular_iterator<TIterator>& rhs)
748 {
749 return !(lhs == rhs);
750 }
751}
752
753#endif
Common circular iterator implementation.
Definition: circular_iterator.h:50
ETL_CONSTEXPR14 TIterator current() const
Conversion to base iterator type.
Definition: circular_iterator.h:176
ETL_CONSTEXPR14 value_type operator*()
Dereference operator.
Definition: circular_iterator.h:136
TIterator itr_end
The underlying end iterator.
Definition: circular_iterator.h:184
ETL_CONSTEXPR14 bool empty() const
Is there nothing to iterate over?
Definition: circular_iterator.h:128
ETL_CONSTEXPR14 TIterator operator->()
-> operator.
Definition: circular_iterator.h:152
ETL_CONSTEXPR14 circular_iterator_common()
Default constructor.
Definition: circular_iterator.h:62
ETL_CONSTEXPR14 TIterator begin() const
Beginning of the range.
Definition: circular_iterator.h:104
TIterator itr_begin
The underlying begin iterator.
Definition: circular_iterator.h:183
ETL_CONSTEXPR14 TIterator end() const
End of the range.
Definition: circular_iterator.h:112
ETL_CONSTEXPR14 size_t size() const
How long is the range?
Definition: circular_iterator.h:120
TIterator itr
The underlying iterator.
Definition: circular_iterator.h:185
ETL_CONSTEXPR14 circular_iterator_common & operator=(const circular_iterator_common &other)
Assignment.
Definition: circular_iterator.h:92
Definition: iterator.h:228
Definition: circular_iterator.h:597
bitset_ext
Definition: absolute.h:38
ETL_CONSTEXPR14 etl::circular_iterator< TIterator > operator-(etl::circular_iterator< TIterator > &lhs, typename etl::iterator_traits< TIterator >::difference_type offset)
Definition: circular_iterator.h:672
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:645
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:633
ETL_CONSTEXPR14 etl::circular_iterator< TIterator > operator+(etl::circular_iterator< TIterator > &lhs, typename etl::iterator_traits< TIterator >::difference_type offset)
Definition: circular_iterator.h:659
Definition: iterator.h:53
Definition: iterator.h:52
iterator
Definition: iterator.h:399
Definition: iterator.h:54