Embedded Template Library 1.0
Loading...
Searching...
No Matches
ranges.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) 2026 BMW AG
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_RANGES_INCLUDED
32#define ETL_RANGES_INCLUDED
33
34#include "platform.h"
35
36#include "error_handler.h"
37#include "invoke.h"
38#include "iterator.h"
39#include "limits.h"
40#include "tuple.h"
41#include "type_traits.h"
43
44#if ETL_USING_CPP17
45
46namespace etl
47{
48 namespace ranges
49 {
50 //*************************************************************************
52 //*************************************************************************
53
54 namespace private_ranges
55 {
56 template <typename T, typename Enable = void>
57 struct iterator_trait;
58
59 template <typename T>
60 struct iterator_trait<T, etl::enable_if_t<etl::is_class_v<T>>>
61 {
62 using iterator = typename etl::conditional_t< etl::is_const_v<T>, typename T::const_iterator, typename T::iterator>;
63 using const_iterator = typename T::const_iterator;
64
65 using value_type = typename etl::iterator_traits<const_iterator>::value_type;
66 using difference_type = typename etl::iterator_traits<const_iterator>::difference_type;
67 using pointer = typename etl::iterator_traits<const_iterator>::pointer;
68 using reference = typename etl::iterator_traits<const_iterator>::reference;
69 };
70
71 template <typename T>
72 struct iterator_trait< T, etl::enable_if_t<etl::is_reference_v<T> && !etl::is_array_v<etl::remove_reference_t<T>>>>
73 {
74 using iterator =
75 typename etl::conditional_t< etl::is_const_v<etl::remove_reference_t<T>>, typename etl::remove_reference<T>::type::const_iterator,
76 typename etl::remove_reference<T>::type::iterator>;
77 using const_iterator = typename etl::remove_reference<T>::type::const_iterator;
78
79 using value_type = typename etl::iterator_traits<iterator>::value_type;
80 using difference_type = typename etl::iterator_traits<iterator>::difference_type;
81 using pointer = typename etl::iterator_traits<iterator>::pointer;
82 using reference = typename etl::iterator_traits<iterator>::reference;
83 };
84
85 template <typename T>
86 struct iterator_trait< T, etl::enable_if_t<etl::is_array_v<etl::remove_reference_t<T>>>>
87 {
88 using value_type = typename etl::remove_all_extents<etl::remove_reference_t<T>>::type;
89 using iterator = value_type*;
90 using const_iterator = const value_type*;
91 using difference_type = ptrdiff_t;
92 using pointer = const value_type*;
93 using reference = const value_type&;
94 };
95 } // namespace private_ranges
96
97 template <class D>
98 class view_interface
99 {
100 public:
101
102 view_interface() = default;
103
104 constexpr bool empty() const
105 {
106 return cbegin() == cend();
107 }
108
109 auto cbegin() const
110 {
111 return static_cast<const D*>(this)->begin();
112 }
113
114 auto cend() const
115 {
116 return static_cast<const D*>(this)->end();
117 }
118
119 operator bool() const
120 {
121 return !empty();
122 }
123
124 size_t size() const
125 {
126 return static_cast<size_t>(etl::distance(cbegin(), cend()));
127 }
128
129 constexpr decltype(auto) front()
130 {
131 return *(static_cast<D*>(this)->begin());
132 }
133
134 constexpr decltype(auto) front() const
135 {
136 return *cbegin();
137 }
138
139 template < typename D2 = D,
140 etl::enable_if_t< etl::is_bidirectional_iterator_concept< decltype(etl::declval<const D2&>().begin())>::value, int> = 0>
141 constexpr decltype(auto) back()
142 {
143 return *(static_cast<D*>(this)->end() - 1);
144 }
145
146 template < typename D2 = D,
147 etl::enable_if_t< etl::is_bidirectional_iterator_concept< decltype(etl::declval<const D2&>().begin())>::value, int> = 0>
148 constexpr decltype(auto) back() const
149 {
150 return *etl::prev(cend());
151 }
152
153 constexpr decltype(auto) operator[](size_t i)
154 {
155 auto it{static_cast<D*>(this)->begin()};
156 etl::advance(it, i);
157 return *it;
158 }
159
160 template < typename D2 = D, etl::enable_if_t<etl::is_random_access_iterator< decltype(etl::declval<const D2&>().begin())>::value, int> = 0>
161 constexpr decltype(auto) operator[](size_t i)
162 {
163 return static_cast<D*>(this)->begin()[i];
164 }
165
166 template < typename D2 = D, etl::enable_if_t<etl::is_random_access_iterator< decltype(etl::declval<const D2&>().begin())>::value, int> = 0>
167 constexpr decltype(auto) operator[](size_t i) const
168 {
169 return cbegin()[i];
170 }
171 };
172
173 template <class I>
174 class range_iterator
175 {
176 public:
177
178 auto get() const
179 {
180 return **(static_cast<const I*>(this));
181 }
182 };
183
184 template <class I, class S = I>
185 class subrange : public etl::ranges::view_interface<subrange<I, S>>
186 {
187 public:
188
189 subrange(I i, S s)
190 : _begin{i}
191 , _end{s}
192 {
193 }
194
195 constexpr I begin() const
196 {
197 return _begin;
198 }
199
200 constexpr S end() const
201 {
202 return _end;
203 }
204
205 constexpr subrange& advance(etl::iter_difference_t<I> n)
206 {
207 etl::advance(_begin, n);
208 return *this;
209 }
210
211 constexpr subrange prev(etl::iter_difference_t<I> n = 1)
212 {
213 auto result = subrange{_begin, _end};
214 result.advance(-n);
215 return result;
216 }
217
218 constexpr subrange next(etl::iter_difference_t<I> n = 1)
219 {
220 auto result = subrange{_begin, _end};
221 result.advance(n);
222 return result;
223 }
224
225 private:
226
227 I _begin;
228 S _end;
229 };
230
231 template <class I, class S>
232 subrange(I, S) -> subrange<I, S>;
233
234 template <class T>
235 class empty_view : public etl::ranges::view_interface<empty_view<T>>
236 {
237 public:
238
239 using iterator = T*;
240
241 constexpr empty_view() = default;
242
243 static constexpr iterator begin() noexcept
244 {
245 return nullptr;
246 }
247
248 static constexpr iterator end() noexcept
249 {
250 return nullptr;
251 }
252
253 static constexpr T* data() noexcept
254 {
255 return nullptr;
256 }
257
258 static constexpr size_t size() noexcept
259 {
260 return 0;
261 }
262
263 static constexpr bool empty() noexcept
264 {
265 return true;
266 }
267 };
268
269 struct dangling
270 {
271 constexpr dangling() noexcept = default;
272
273 template <class... Args>
274 constexpr dangling(Args&&...) noexcept
275 {
276 }
277 };
278
279 template <class T>
280 constexpr bool enable_borrowed_range = false;
281
282 template <class T>
283 struct is_borrowed_range
284 {
285 static constexpr bool value = etl::is_range_v<T> || etl::ranges::enable_borrowed_range<T>;
286 };
287
288 template <typename T>
289 inline constexpr bool is_borrowed_range_v = is_borrowed_range<T>::value;
290
291 template <class T>
292 using borrowed_iterator_t = etl::conditional_t<etl::ranges::is_borrowed_range_v<T>, etl::ranges::iterator_t<T>, etl::ranges::dangling>;
293
294 template <class T>
295 using borrowed_subrange_t =
296 etl::conditional_t<etl::ranges::is_borrowed_range_v<T>, etl::ranges::subrange<etl::ranges::iterator_t<T>>, etl::ranges::dangling>;
297
298 namespace views
299 {
300 template <class T>
301 constexpr empty_view<T> empty{};
302 }
303
304 template <class T>
305 class single_view : public etl::ranges::view_interface<single_view<T>>
306 {
307 public:
308
309 using value_type = T;
310 using iterator = value_type*;
311 using const_iterator = const value_type*;
312
313 constexpr single_view(const T& t) noexcept
314 : _value(t)
315 {
316 }
317
318 constexpr single_view(T&& t) noexcept
319 : _value(etl::move(t))
320 {
321 }
322
323 constexpr single_view(const single_view<T>& other)
324 : _value(other._value)
325 {
326 }
327
328 constexpr single_view(single_view<T>&& other)
329 : _value(etl::move(other._value))
330 {
331 }
332
333 constexpr single_view& operator=(const single_view<T>& other)
334 {
335 _value = other._value;
336 return *this;
337 }
338
339 constexpr single_view& operator=(single_view<T>&& other)
340 {
341 _value = etl::move(other._value);
342 return *this;
343 }
344
345 constexpr iterator begin() noexcept
346 {
347 return data();
348 }
349
350 constexpr const_iterator begin() const noexcept
351 {
352 return data();
353 }
354
355 constexpr iterator end() noexcept
356 {
357 return data() + 1;
358 }
359
360 constexpr const_iterator end() const noexcept
361 {
362 return data() + 1;
363 }
364
365 constexpr const T* data() const noexcept
366 {
367 return &_value;
368 }
369
370 constexpr T* data() noexcept
371 {
372 return &_value;
373 }
374
375 constexpr size_t size() const noexcept
376 {
377 return 1;
378 }
379
380 constexpr bool empty() const noexcept
381 {
382 return false;
383 }
384
385 private:
386
387 value_type _value;
388 };
389
390 template <class T>
391 single_view(T) -> single_view<T>;
392
393 namespace views
394 {
395 namespace private_views
396 {
397 struct single
398 {
399 template <typename T>
400 constexpr auto operator()(T&& t) const
401 {
402 return etl::ranges::single_view(t);
403 }
404 };
405 } // namespace private_views
406
407 inline constexpr private_views::single single;
408 } // namespace views
409
410 template <typename T>
411 struct iota_iterator : public range_iterator<iota_iterator<T>>
412 {
413 public:
414
415 using value_type = T;
416 using difference_type = ptrdiff_t;
417 using pointer = T*;
418 using reference = T&;
419
420 using iterator_category = ETL_OR_STD::random_access_iterator_tag;
421
422 constexpr explicit iota_iterator(T i)
423 : _i{i}
424 {
425 }
426
427 constexpr iota_iterator(const iota_iterator& other)
428 : _i{other._i}
429 {
430 }
431
432 iota_iterator& operator++()
433 {
434 ++_i;
435 return *this;
436 }
437
438 iota_iterator operator++(int)
439 {
440 iota_iterator tmp = *this;
441 _i++;
442 return tmp;
443 }
444
445 iota_iterator& operator--()
446 {
447 --_i;
448 return *this;
449 }
450
451 iota_iterator operator--(int)
452 {
453 iota_iterator tmp = *this;
454 _i--;
455 return tmp;
456 }
457
458 iota_iterator& operator+=(difference_type n)
459 {
460 _i += n;
461 return *this;
462 }
463
464 iota_iterator operator+(difference_type n) const
465 {
466 return iota_iterator{static_cast<value_type>(_i + n)};
467 }
468
469 iota_iterator operator-(difference_type n) const
470 {
471 return iota_iterator{static_cast<value_type>(_i - n)};
472 }
473
474 difference_type operator-(iota_iterator other) const
475 {
476 return _i - other._i;
477 }
478
479 iota_iterator& operator=(const iota_iterator& other)
480 {
481 _i = other._i;
482 return *this;
483 }
484
485 constexpr bool operator==(const iota_iterator& other) const
486 {
487 return _i == other._i;
488 }
489
490 constexpr bool operator!=(const iota_iterator& other) const
491 {
492 return _i != other._i;
493 }
494
495 constexpr value_type operator*() const
496 {
497 return _i;
498 }
499
500 constexpr value_type operator*()
501 {
502 return _i;
503 }
504
505 private:
506
507 value_type _i;
508 };
509
510 template <class T>
511 class iota_view : public etl::ranges::view_interface<iota_view<T>>
512 {
513 public:
514
515 using iterator = iota_iterator<T>;
516 using const_iterator = iota_iterator<T>;
517
518 iota_view() = default;
519
520 constexpr explicit iota_view(T value, T bound = etl::numeric_limits<T>::max())
521 : _value(value)
522 , _bound(bound)
523 {
524 }
525
526 constexpr iterator begin() const noexcept
527 {
528 return iterator(_value);
529 }
530
531 constexpr iterator end() const noexcept
532 {
533 return iterator(_bound);
534 }
535
536 constexpr size_t size() const noexcept
537 {
538 if (_bound == etl::numeric_limits<T>::max())
539 {
540 return etl::numeric_limits<T>::max();
541 }
542 return static_cast<size_t>(_bound - _value);
543 }
544
545 constexpr bool empty() const noexcept
546 {
547 return _value == _bound;
548 }
549
550 private:
551
552 T _value;
553 T _bound;
554 };
555
556 template <class T>
557 iota_view(T) -> iota_view<T>;
558
559 namespace views
560 {
561 namespace private_views
562 {
563 struct iota
564 {
565 template <typename T, typename B>
566 constexpr auto operator()(T&& t, B&& b) const
567 {
568 return etl::ranges::iota_view(t, b);
569 }
570 };
571 } // namespace private_views
572
573 inline constexpr private_views::iota iota;
574 } // namespace views
575
576 template <typename T, typename B = T>
577 struct repeat_iterator : public range_iterator<repeat_iterator<T, B>>
578 {
579 public:
580
581 using value_type = T;
582 using difference_type = ptrdiff_t;
583 using pointer = T*;
584 using reference = T&;
585
586 using iterator_category = ETL_OR_STD::random_access_iterator_tag;
587
588 constexpr explicit repeat_iterator(T value, B i = etl::numeric_limits<B>::max())
589 : _value{value}
590 , _i{i}
591 {
592 }
593
594 constexpr repeat_iterator(const repeat_iterator& other) = default;
595
596 repeat_iterator& operator++()
597 {
598 --_i;
599 return *this;
600 }
601
602 repeat_iterator operator++(int)
603 {
604 repeat_iterator tmp(*this);
605 _i--;
606 return tmp;
607 }
608
609 repeat_iterator& operator--()
610 {
611 ++_i;
612 return *this;
613 }
614
615 repeat_iterator operator--(int)
616 {
617 repeat_iterator tmp(*this);
618 _i++;
619 return tmp;
620 }
621
622 repeat_iterator& operator+=(difference_type n)
623 {
624 _i -= static_cast<B>(n);
625 return *this;
626 }
627
628 repeat_iterator operator+(difference_type n) const
629 {
630 return repeat_iterator{_value, static_cast<B>(_i - static_cast<B>(n))};
631 }
632
633 repeat_iterator operator-(difference_type n) const
634 {
635 return repeat_iterator{_value, static_cast<B>(_i + static_cast<B>(n))};
636 }
637
638 difference_type operator-(repeat_iterator other) const
639 {
640 return other._i - _i;
641 }
642
643 repeat_iterator& operator=(const repeat_iterator& other)
644 {
645 _i = other._i;
646 _value = other._value;
647 return *this;
648 }
649
650 constexpr bool operator==(const repeat_iterator& other) const
651 {
652 return _i == other._i;
653 }
654
655 constexpr bool operator!=(const repeat_iterator& other) const
656 {
657 return _i != other._i;
658 }
659
660 constexpr value_type operator*() const
661 {
662 return _value;
663 }
664
665 constexpr value_type operator*()
666 {
667 return _value;
668 }
669
670 private:
671
672 value_type _value;
673 B _i;
674 };
675
676 template <class T, class B = T>
677 class repeat_view : public etl::ranges::view_interface<repeat_view<T>>
678 {
679 public:
680
681 using iterator = repeat_iterator<T, B>;
682 using const_iterator = repeat_iterator<T, B>;
683
684 repeat_view() = default;
685
686 constexpr explicit repeat_view(T value, B bound = etl::numeric_limits<B>::max())
687 : _value(value)
688 , _bound(bound)
689 {
690 }
691
692 constexpr iterator begin() const noexcept
693 {
694 return iterator(_value, _bound);
695 }
696
697 constexpr iterator end() const noexcept
698 {
699 return iterator(_value, 0);
700 }
701
702 constexpr size_t size() const noexcept
703 {
704 return static_cast<size_t>(_bound);
705 }
706
707 constexpr bool empty() const noexcept
708 {
709 return _bound == 0;
710 }
711
712 private:
713
714 T _value;
715 B _bound;
716 };
717
718 template <class T, class B = T>
719 repeat_view(T, B = B()) -> repeat_view<T, B>;
720
721 namespace views
722 {
723 namespace private_views
724 {
725 struct repeat
726 {
727 template <typename T, typename B>
728 constexpr auto operator()(T&& t, B&& b) const
729 {
730 return etl::ranges::repeat_view(t, b);
731 }
732 };
733 } // namespace private_views
734
735 inline constexpr private_views::repeat repeat;
736 } // namespace views
737
738 template <class Range>
739 class range_adapter_closure
740 {
741 };
742
743 template <class Range>
744 class ref_view : public etl::ranges::view_interface<ref_view<Range>>
745 {
746 public:
747
748 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
749 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
750 using pointer = typename etl::ranges::private_ranges::iterator_trait<Range>::pointer;
751
752 ref_view(Range& r)
753 : _r{&r}
754 {
755 }
756
757 constexpr Range& base() const
758 {
759 return *_r;
760 }
761
762 constexpr iterator begin() const
763 {
764 return iterator(ETL_OR_STD::begin(*_r));
765 }
766
767 constexpr iterator end() const
768 {
769 return iterator(ETL_OR_STD::end(*_r));
770 }
771
772 constexpr bool empty() const
773 {
774 return begin() == end();
775 }
776
777 constexpr size_t size() const
778 {
779 return static_cast<size_t>(etl::distance(begin(), end()));
780 }
781
782 constexpr pointer data() const
783 {
784 return &(*begin());
785 }
786
787 private:
788
789 Range* _r;
790 };
791
792 template <class Range>
793 ref_view(Range&) -> ref_view<Range>;
794
795 struct ref_range_adapter_closure : public range_adapter_closure<ref_range_adapter_closure>
796 {
797 template <typename Range>
798 using target_view_type = ref_view<Range>;
799
800 ref_range_adapter_closure() = default;
801
802 template <typename Range>
803 ref_view<Range> operator()(Range& r)
804 {
805 return ref_view<Range>(r);
806 }
807 };
808
809 namespace views
810 {
811 namespace private_views
812 {
813 struct ref
814 {
815 template <class Range>
816 constexpr auto operator()(Range& r) const
817 {
818 return ranges::ref_view(r);
819 }
820
821 constexpr auto operator()() const
822 {
823 return ranges::ref_range_adapter_closure();
824 }
825 };
826 } // namespace private_views
827
828 inline constexpr private_views::ref ref;
829 } // namespace views
830
831 template <class Range>
832 class owning_view : public etl::ranges::view_interface<owning_view<Range>>
833 {
834 public:
835
836 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
837 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
838 using pointer = typename etl::ranges::private_ranges::iterator_trait<Range>::pointer;
839
840 owning_view() = default;
841
842 owning_view(owning_view&& other) = default;
843
844 constexpr owning_view(Range&& r)
845 : _r(etl::move(r))
846 {
847 }
848
849 owning_view& operator=(const owning_view&) = delete;
850
851 owning_view& operator=(owning_view&& other)
852 {
853 _r = etl::move(other._r);
854 return *this;
855 }
856
857 constexpr Range& base() noexcept
858 {
859 return _r;
860 }
861
862 constexpr iterator begin() const
863 {
864 return iterator(ETL_OR_STD::begin(_r));
865 }
866
867 constexpr iterator end() const
868 {
869 return iterator(ETL_OR_STD::end(_r));
870 }
871
872 constexpr bool empty() const
873 {
874 return begin() == end();
875 }
876
877 constexpr size_t size() const
878 {
879 return static_cast<size_t>(etl::distance(begin(), end()));
880 }
881
882 constexpr pointer data()
883 {
884 return &(*begin());
885 }
886
887 private:
888
889 Range _r;
890 };
891
892 template <class Range>
893 owning_view(Range&&) -> owning_view<Range>;
894
895 struct owning_range_adapter_closure : public range_adapter_closure<owning_range_adapter_closure>
896 {
897 template <typename Range, typename CleanRange = etl::remove_reference_t<Range>>
898 using target_view_type = owning_view<CleanRange>;
899
900 owning_range_adapter_closure() = default;
901
902 template <typename Range, typename CleanRange = etl::remove_reference_t<Range>>
903 owning_view<CleanRange> operator()(Range&& r)
904 {
905 return owning_view<CleanRange>(etl::move(r));
906 }
907 };
908
909 namespace views
910 {
911 namespace private_views
912 {
913 struct owning
914 {
915 template <class Range>
916 constexpr auto operator()(Range&& r) const
917 {
918 return ranges::owning_view(etl::forward<Range>(r));
919 }
920
921 constexpr auto operator()() const
922 {
923 return ranges::owning_range_adapter_closure();
924 }
925 };
926 } // namespace private_views
927
928 inline constexpr private_views::owning owning;
929 } // namespace views
930
931 namespace views
932 {
933 namespace private_views
934 {
935 struct all
936 {
937 template < class Range,
938 etl::enable_if_t<etl::is_base_of_v< etl::ranges::view_interface<etl::decay_t<Range>>, etl::decay_t<Range>>, int> = 0>
939 constexpr etl::decay_t<Range> operator()(Range&& r) const
940 {
941 return r;
942 }
943
944 template < class Range,
945 etl::enable_if_t<!etl::is_base_of_v< etl::ranges::view_interface<etl::decay_t<Range>>, etl::decay_t<Range>>, int> = 0>
946 constexpr auto operator()(Range&& r) const
947 {
948 if constexpr (etl::is_lvalue_reference_v<Range>)
949 {
950 return etl::ranges::ref_view(etl::forward<Range>(r));
951 }
952 else
953 {
954 return etl::ranges::owning_view(etl::forward<Range>(r));
955 }
956 }
957 };
958 } // namespace private_views
959
960 inline constexpr private_views::all all;
961
962 template <typename R>
963 using all_t = decltype(views::all(etl::declval<R>()));
964 } // namespace views
965
966 template <class Range, class Pred>
967 class filter_iterator
968 {
969 public:
970
971 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
972
973 using iterator = typename trait::iterator;
974 using const_iterator = typename trait::const_iterator;
975 using value_type = typename trait::value_type;
976 using difference_type = typename trait::difference_type;
977 using pointer = typename trait::pointer;
978 using reference = typename trait::reference;
979
980 using iterator_category = ETL_OR_STD::bidirectional_iterator_tag;
981
982 filter_iterator(const_iterator it, const_iterator it_end, const Pred& p)
983 : _it{it}
984 , _it_begin{it}
985 , _it_end{it_end}
986 , _p{p}
987 {
988 while (_it != _it_end && !_p(*_it))
989 {
990 ++_it;
991 }
992 }
993
994 filter_iterator(const filter_iterator& other)
995 : _it{other._it}
996 , _it_begin{other._it_begin}
997 , _it_end{other._it_end}
998 , _p{other._p}
999 {
1000 while (_it != _it_end && !_p(*_it))
1001 {
1002 ++_it;
1003 }
1004 }
1005
1006 filter_iterator& operator++()
1007 {
1008 ++_it;
1009 while (_it != _it_end && !_p(*_it))
1010 {
1011 ++_it;
1012 }
1013 return *this;
1014 }
1015
1016 filter_iterator operator++(int)
1017 {
1018 filter_iterator tmp = *this;
1019
1020 _it++;
1021 while (_it != _it_end && !_p(*_it))
1022 {
1023 _it++;
1024 }
1025
1026 return tmp;
1027 }
1028
1029 filter_iterator& operator--()
1030 {
1031 --_it;
1032 while (_it != _it_begin && !_p(*_it))
1033 {
1034 --_it;
1035 }
1036 return *this;
1037 }
1038
1039 filter_iterator operator--(int)
1040 {
1041 filter_iterator tmp = *this;
1042
1043 _it--;
1044 while (_it != _it_begin && !_p(*_it))
1045 {
1046 _it--;
1047 }
1048
1049 return tmp;
1050 }
1051
1052 filter_iterator& operator+=(size_t n)
1053 {
1054 for (size_t i = 0; i < n; i++)
1055 {
1056 if (_it != _it_end)
1057 {
1058 ++(*this);
1059 }
1060 }
1061
1062 return *this;
1063 }
1064
1065 filter_iterator& operator-=(size_t n)
1066 {
1067 for (size_t i = 0; i < n; i++)
1068 {
1069 if (_it != _it_begin)
1070 {
1071 --(*this);
1072 }
1073 }
1074
1075 return *this;
1076 }
1077
1078 filter_iterator& operator=(const filter_iterator& other)
1079 {
1080 _it = other._it;
1081 _it_begin = other._it_begin;
1082 _it_end = other._it_end;
1083 ETL_ASSERT(&_p == &other._p, ETL_ERROR_GENERIC("Predicates need to be the same"));
1084 return *this;
1085 }
1086
1087 value_type operator*()
1088 {
1089 return *_it;
1090 }
1091
1092 bool operator==(const filter_iterator& other) const
1093 {
1094 return other._it == _it;
1095 }
1096
1097 bool operator!=(const filter_iterator& other) const
1098 {
1099 return !(*this == other);
1100 }
1101
1102 private:
1103
1104 const_iterator _it;
1105 const_iterator _it_begin;
1106 const_iterator _it_end;
1107 const Pred& _p;
1108 };
1109
1110 template <class Range, class Pred>
1111 constexpr typename filter_iterator<Range, Pred>::difference_type operator-(const filter_iterator<Range, Pred>& lhs,
1112 const filter_iterator<Range, Pred>& rhs)
1113 {
1114 typename filter_iterator<Range, Pred>::difference_type result{0};
1115 filter_iterator<Range, Pred> it_up{rhs};
1116 while (it_up != lhs)
1117 {
1118 ++it_up;
1119 ++result;
1120 }
1121 return result;
1122 }
1123
1124 template <class Range, typename Pred>
1125 class filter_view : public etl::ranges::view_interface<filter_view<Range, Pred>>
1126 {
1127 public:
1128
1129 using iterator = filter_iterator<Range, Pred>;
1130 using const_iterator = filter_iterator<Range, Pred>;
1131
1132 filter_view(Range&& r, const Pred& pred)
1133 : _pred{pred}
1134 , _r{etl::move(r)}
1135 {
1136 }
1137
1138 constexpr Range& base() const&
1139 {
1140 return _r;
1141 }
1142
1143 constexpr const Pred& pred() const
1144 {
1145 return _pred;
1146 }
1147
1148 constexpr const_iterator begin() const
1149 {
1150 return const_iterator(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r), _pred);
1151 }
1152
1153 constexpr const_iterator end() const
1154 {
1155 return const_iterator(ETL_OR_STD::cend(_r), ETL_OR_STD::cend(_r), _pred);
1156 }
1157
1158 private:
1159
1160 const Pred _pred;
1161 Range _r;
1162 };
1163
1164 template <class Range, typename Pred>
1165 filter_view(Range&&, Pred) -> filter_view<views::all_t<Range>, Pred>;
1166
1167 template <typename Pred>
1168 struct filter_range_adapter_closure : public range_adapter_closure<filter_range_adapter_closure<Pred>>
1169 {
1170 template <typename Range>
1171 using target_view_type = filter_view<Range, Pred>;
1172
1173 filter_range_adapter_closure(const Pred& p)
1174 : _p{p}
1175 {
1176 }
1177
1178 template <typename Range>
1179 constexpr auto operator()(Range&& r)
1180 {
1181 return filter_view(views::all(etl::forward<Range>(r)), _p);
1182 }
1183
1184 const Pred _p;
1185 };
1186
1187 namespace views
1188 {
1189 namespace private_views
1190 {
1191 struct filter
1192 {
1193 template <class Range, typename Pred>
1194 constexpr auto operator()(Range&& r, const Pred& p) const
1195 {
1196 return filter_view(views::all(etl::forward<Range>(r)), p);
1197 }
1198
1199 template <typename Pred>
1200 constexpr auto operator()(const Pred& p) const
1201 {
1202 return ranges::filter_range_adapter_closure<Pred>(p);
1203 }
1204 };
1205 } // namespace private_views
1206
1207 inline constexpr private_views::filter filter;
1208 } // namespace views
1209
1210 template <class Range, class Fun>
1211 class transform_iterator
1212 {
1213 public:
1214
1215 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
1216
1217 using iterator = typename trait::iterator;
1218 using const_iterator = typename trait::const_iterator;
1219 using value_type = typename trait::value_type;
1220 using difference_type = typename trait::difference_type;
1221 using pointer = typename trait::pointer;
1222 using reference = typename trait::reference;
1223
1224 using iterator_category = ETL_OR_STD::forward_iterator_tag;
1225
1226 transform_iterator(const_iterator it, const Fun& f)
1227 : _it(it)
1228 , _f(f)
1229 {
1230 }
1231
1232 transform_iterator(const transform_iterator& other)
1233 : _it{other._it}
1234 , _f{other._f}
1235 {
1236 }
1237
1238 transform_iterator& operator++()
1239 {
1240 ++_it;
1241 return *this;
1242 }
1243
1244 transform_iterator operator++(int)
1245 {
1246 transform_iterator tmp = *this;
1247 _it++;
1248 return tmp;
1249 }
1250
1251 transform_iterator& operator=(const transform_iterator& other)
1252 {
1253 _it = other._it;
1254 ETL_ASSERT(&_f == &other._f, ETL_ERROR_GENERIC("Transform functions need to be the same"));
1255 return *this;
1256 }
1257
1258 value_type operator*()
1259 {
1260 return static_cast<value_type>(_f(*_it));
1261 }
1262
1263 bool operator==(const transform_iterator& other) const
1264 {
1265 return other._it == _it;
1266 }
1267
1268 bool operator!=(const transform_iterator& other) const
1269 {
1270 return !(*this == other);
1271 }
1272
1273 private:
1274
1275 const_iterator _it;
1276 const Fun& _f;
1277 };
1278
1279 template <class Range, typename Fun>
1280 class transform_view : public etl::ranges::view_interface<transform_view<Range, Fun>>
1281 {
1282 public:
1283
1284 using iterator = transform_iterator<Range, Fun>;
1285 using const_iterator = transform_iterator<Range, Fun>;
1286
1287 transform_view(Range&& r, const Fun& fun)
1288 : _fun{fun}
1289 , _r{etl::move(r)}
1290 {
1291 }
1292
1293 constexpr Range& base() const&
1294 {
1295 return _r;
1296 }
1297
1298 constexpr const_iterator begin() const
1299 {
1300 return const_iterator(ETL_OR_STD::begin(_r), _fun);
1301 }
1302
1303 constexpr const_iterator end() const
1304 {
1305 return const_iterator(ETL_OR_STD::end(_r), _fun);
1306 }
1307
1308 constexpr size_t size() const
1309 {
1310 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
1311 }
1312
1313 private:
1314
1315 const Fun _fun;
1316 Range _r;
1317 };
1318
1319 template <class Range, typename Fun>
1320 transform_view(Range&&, Fun) -> transform_view<views::all_t<Range>, Fun>;
1321
1322 template <typename Fun>
1323 struct transform_range_adapter_closure : public range_adapter_closure<transform_range_adapter_closure<Fun>>
1324 {
1325 template <typename Range>
1326 using target_view_type = transform_view<Range, Fun>;
1327
1328 transform_range_adapter_closure(const Fun& f)
1329 : _f{f}
1330 {
1331 }
1332
1333 template <typename Range>
1334 constexpr auto operator()(Range&& r)
1335 {
1336 return transform_view(views::all(etl::forward<Range>(r)), _f);
1337 }
1338
1339 const Fun _f;
1340 };
1341
1342 namespace views
1343 {
1344 namespace private_views
1345 {
1346 struct transform
1347 {
1348 template <class Range, typename Fun>
1349 constexpr auto operator()(Range&& r, const Fun& f) const
1350 {
1351 return transform_view(views::all(etl::forward<Range>(r)), f);
1352 }
1353
1354 template <typename Fun>
1355 constexpr auto operator()(const Fun& f) const
1356 {
1357 return ranges::transform_range_adapter_closure<Fun>(f);
1358 }
1359 };
1360 } // namespace private_views
1361
1362 inline constexpr private_views::transform transform;
1363 } // namespace views
1364
1365 template <class Range>
1366 class as_rvalue_view : public etl::ranges::view_interface<as_rvalue_view<Range>>
1367 {
1368 public:
1369
1370 using iterator = typename etl::move_iterator< typename etl::ranges::private_ranges::iterator_trait<Range>::iterator>;
1371
1372 as_rvalue_view(const as_rvalue_view& other) = default;
1373
1374 as_rvalue_view(Range&& r)
1375 : _r{etl::move(r)}
1376 {
1377 }
1378
1379 constexpr Range& base() const
1380 {
1381 return _r;
1382 }
1383
1384 constexpr iterator begin() const
1385 {
1386 return iterator(ETL_OR_STD::begin(_r));
1387 }
1388
1389 constexpr iterator end() const
1390 {
1391 return iterator(ETL_OR_STD::end(_r));
1392 }
1393
1394 constexpr size_t size() const
1395 {
1396 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
1397 }
1398
1399 private:
1400
1401 Range _r;
1402 };
1403
1404 template <class Range>
1405 as_rvalue_view(Range&&) -> as_rvalue_view<views::all_t<Range>>;
1406
1407 struct as_rvalue_range_adapter_closure : public range_adapter_closure<as_rvalue_range_adapter_closure>
1408 {
1409 template <typename Range>
1410 using target_view_type = as_rvalue_view<Range>;
1411
1412 as_rvalue_range_adapter_closure() = default;
1413
1414 template <typename Range>
1415 constexpr auto operator()(Range&& r)
1416 {
1417 return as_rvalue_view(views::all(etl::forward<Range>(r)));
1418 }
1419 };
1420
1421 namespace views
1422 {
1423 namespace private_views
1424 {
1425 struct as_rvalue
1426 {
1427 template <class Range>
1428 constexpr auto operator()(Range&& r) const
1429 {
1430 return as_rvalue_view(views::all(etl::forward<Range>(r)));
1431 }
1432
1433 constexpr auto operator()() const
1434 {
1435 return ranges::as_rvalue_range_adapter_closure();
1436 }
1437 };
1438 } // namespace private_views
1439
1440 inline constexpr private_views::as_rvalue as_rvalue;
1441 } // namespace views
1442
1443 template <class Range>
1444 class as_const_view : public etl::ranges::view_interface<as_const_view<Range>>
1445 {
1446 public:
1447
1448 using iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
1449 using const_iterator = iterator;
1450
1451 as_const_view(const as_const_view& other) = default;
1452
1453 as_const_view(Range&& r)
1454 : _r{etl::move(r)}
1455 {
1456 }
1457
1458 constexpr Range& base() const
1459 {
1460 return _r;
1461 }
1462
1463 constexpr iterator begin() const
1464 {
1465 return ETL_OR_STD::cbegin(_r);
1466 }
1467
1468 constexpr iterator end() const
1469 {
1470 return ETL_OR_STD::cend(_r);
1471 }
1472
1473 constexpr size_t size() const
1474 {
1475 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
1476 }
1477
1478 private:
1479
1480 mutable Range _r;
1481 };
1482
1483 template <class Range>
1484 as_const_view(Range&&) -> as_const_view<views::all_t<Range>>;
1485
1486 struct as_const_range_adapter_closure : public range_adapter_closure<as_const_range_adapter_closure>
1487 {
1488 template <typename Range>
1489 using target_view_type = as_const_view<Range>;
1490
1491 as_const_range_adapter_closure() = default;
1492
1493 template <typename Range>
1494 constexpr auto operator()(Range&& r)
1495 {
1496 return as_const_view(views::all(etl::forward<Range>(r)));
1497 }
1498 };
1499
1500 namespace views
1501 {
1502 namespace private_views
1503 {
1504 struct as_const
1505 {
1506 template <class Range>
1507 constexpr auto operator()(Range&& r) const
1508 {
1509 return as_const_view(views::all(etl::forward<Range>(r)));
1510 }
1511
1512 constexpr auto operator()() const
1513 {
1514 return ranges::as_const_range_adapter_closure();
1515 }
1516 };
1517 } // namespace private_views
1518
1519 inline constexpr private_views::as_const as_const;
1520 } // namespace views
1521
1522 //*************************************************************************
1526 //*************************************************************************
1527 namespace private_ranges
1528 {
1529 template <typename T>
1530 struct cache_latest_cache
1531 {
1532 cache_latest_cache()
1533 : _has_value{false}
1534 , _value{}
1535 {
1536 }
1537
1538 cache_latest_cache(const cache_latest_cache&) = delete;
1539 cache_latest_cache& operator=(const cache_latest_cache&) = delete;
1540
1541 bool has_value() const
1542 {
1543 return _has_value;
1544 }
1545
1546 void set(const T& v)
1547 {
1548 _value = v;
1549 _has_value = true;
1550 }
1551
1552 void reset()
1553 {
1554 _has_value = false;
1555 }
1556
1557 T& value()
1558 {
1559 return _value;
1560 }
1561
1562 bool _has_value;
1563 T _value;
1564 };
1565 } // namespace private_ranges
1566
1567 //*************************************************************************
1569 //*************************************************************************
1570 template <class Range>
1571 class cache_latest_iterator
1572 {
1573 public:
1574
1575 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
1576
1577 using iterator = typename trait::iterator;
1578 using const_iterator = typename trait::const_iterator;
1579 using value_type = typename trait::value_type;
1580 using difference_type = typename trait::difference_type;
1581 using pointer = value_type*;
1582 using reference = value_type&;
1583
1584 using iterator_category = ETL_OR_STD::forward_iterator_tag;
1585
1586 cache_latest_iterator() = default;
1587
1588 cache_latest_iterator(const_iterator it, private_ranges::cache_latest_cache<value_type>* cache)
1589 : _it(it)
1590 , _cache(cache)
1591 {
1592 }
1593
1594 cache_latest_iterator(const cache_latest_iterator& other)
1595 : _it(other._it)
1596 , _cache(other._cache)
1597 {
1598 }
1599
1600 cache_latest_iterator& operator++()
1601 {
1602 ++_it;
1603 if (_cache)
1604 {
1605 _cache->reset();
1606 }
1607 return *this;
1608 }
1609
1610 cache_latest_iterator operator++(int)
1611 {
1612 cache_latest_iterator tmp = *this;
1613 ++(*this);
1614 return tmp;
1615 }
1616
1617 cache_latest_iterator& operator=(const cache_latest_iterator& other)
1618 {
1619 _it = other._it;
1620 _cache = other._cache;
1621 return *this;
1622 }
1623
1624 reference operator*() const
1625 {
1626 if (_cache && !_cache->has_value())
1627 {
1628 _cache->set(*_it);
1629 }
1630 return _cache->value();
1631 }
1632
1633 pointer operator->() const
1634 {
1635 return &(**this);
1636 }
1637
1638 bool operator==(const cache_latest_iterator& other) const
1639 {
1640 return other._it == _it;
1641 }
1642
1643 bool operator!=(const cache_latest_iterator& other) const
1644 {
1645 return !(*this == other);
1646 }
1647
1648 private:
1649
1650 mutable const_iterator _it;
1651 private_ranges::cache_latest_cache<value_type>* _cache;
1652 };
1653
1654 //*************************************************************************
1659 //*************************************************************************
1660 template <class Range>
1661 class cache_latest_view : public etl::ranges::view_interface<cache_latest_view<Range>>
1662 {
1663 public:
1664
1665 using iterator = cache_latest_iterator<Range>;
1666 using const_iterator = cache_latest_iterator<Range>;
1667 using value_type = typename etl::ranges::private_ranges::iterator_trait<Range>::value_type;
1668
1669 cache_latest_view(Range&& r)
1670 : _r{etl::move(r)}
1671 , _cache{}
1672 {
1673 }
1674
1675 cache_latest_view(const cache_latest_view& other)
1676 : _r{other._r}
1677 , _cache{}
1678 {
1679 }
1680
1681 constexpr Range& base() const&
1682 {
1683 return _r;
1684 }
1685
1686 constexpr iterator begin() const
1687 {
1688 _cache.reset();
1689 return iterator(ETL_OR_STD::begin(_r), &_cache);
1690 }
1691
1692 constexpr iterator end() const
1693 {
1694 return iterator(ETL_OR_STD::end(_r), &_cache);
1695 }
1696
1697 constexpr size_t size() const
1698 {
1699 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
1700 }
1701
1702 private:
1703
1704 mutable Range _r;
1705 mutable private_ranges::cache_latest_cache<value_type> _cache;
1706 };
1707
1708 template <class Range>
1709 cache_latest_view(Range&&) -> cache_latest_view<views::all_t<Range>>;
1710
1711 struct cache_latest_range_adapter_closure : public range_adapter_closure<cache_latest_range_adapter_closure>
1712 {
1713 template <typename Range>
1714 using target_view_type = cache_latest_view<Range>;
1715
1716 cache_latest_range_adapter_closure() = default;
1717
1718 template <typename Range>
1719 constexpr auto operator()(Range&& r)
1720 {
1721 return cache_latest_view(views::all(etl::forward<Range>(r)));
1722 }
1723 };
1724
1725 namespace views
1726 {
1727 namespace private_views
1728 {
1729 struct cache_latest
1730 {
1731 template <class Range>
1732 constexpr auto operator()(Range&& r) const
1733 {
1734 return cache_latest_view(views::all(etl::forward<Range>(r)));
1735 }
1736
1737 constexpr auto operator()() const
1738 {
1739 return ranges::cache_latest_range_adapter_closure();
1740 }
1741 };
1742 } // namespace private_views
1743
1744 inline constexpr private_views::cache_latest cache_latest;
1745 } // namespace views
1746
1747 template <class Range>
1748 class reverse_view : public etl::ranges::view_interface<reverse_view<Range>>
1749 {
1750 public:
1751
1752 using iterator = ETL_OR_STD::reverse_iterator< typename etl::ranges::private_ranges::iterator_trait<Range>::iterator>;
1753 using const_iterator = ETL_OR_STD::reverse_iterator< typename etl::ranges::private_ranges::iterator_trait<Range>::const_iterator>;
1754 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
1755
1756 constexpr reverse_view(Range&& r)
1757 : _r{etl::move(r)}
1758 {
1759 }
1760
1761 reverse_view(const reverse_view& other) = default;
1762
1763 constexpr Range base() const&
1764 {
1765 return _r;
1766 }
1767
1768 constexpr iterator begin() const
1769 {
1770 return iterator(ETL_OR_STD::end(_r));
1771 }
1772
1773 constexpr iterator end() const
1774 {
1775 return iterator(ETL_OR_STD::begin(_r));
1776 }
1777
1778 constexpr size_t size() const
1779 {
1780 return static_cast<size_t>(etl::distance(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r)));
1781 }
1782
1783 private:
1784
1785 Range _r;
1786 };
1787
1788 template <class Range>
1789 reverse_view(Range&&) -> reverse_view<views::all_t<Range>>;
1790
1791 template <typename T>
1792 struct is_reverse_view : etl::false_type
1793 {
1794 };
1795
1796 template <typename Range>
1797 struct is_reverse_view<reverse_view<Range>> : etl::true_type
1798 {
1799 };
1800
1801 namespace views
1802 {
1803 namespace private_views
1804 {
1805 struct reverse
1806 {
1807 template <class Range>
1808 constexpr auto operator()(Range&& r) const
1809 {
1810 if constexpr (is_reverse_view<etl::remove_cv_t< etl::remove_reference_t<Range>>>::value)
1811 {
1812 return r.base();
1813 }
1814 else
1815 {
1816 return reverse_view(views::all(etl::forward<Range>(r)));
1817 }
1818 }
1819 };
1820 } // namespace private_views
1821
1822 inline constexpr private_views::reverse reverse;
1823 } // namespace views
1824
1825 template <class Range>
1826 class drop_view : public etl::ranges::view_interface<drop_view<Range>>
1827 {
1828 public:
1829
1830 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
1831 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
1832 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
1833
1834 constexpr drop_view(Range&& r, size_t drop_n)
1835 : _r{etl::move(r)}
1836 , _drop_n{drop_n}
1837 , _begin_cache{ETL_OR_STD::end(_r)}
1838 , _begin_cache_valid{false}
1839 {
1840 }
1841
1842 drop_view(const drop_view& other) = default;
1843
1844 constexpr Range base() const&
1845 {
1846 return _r;
1847 }
1848
1849 constexpr iterator begin() const
1850 {
1851 if (!_begin_cache_valid)
1852 {
1853 _begin_cache = drop_begin();
1854 _begin_cache_valid = true;
1855 }
1856 return _begin_cache;
1857 }
1858
1859 constexpr iterator end() const
1860 {
1861 return iterator(ETL_OR_STD::end(_r));
1862 }
1863
1864 constexpr size_t size() const
1865 {
1866 if (!_begin_cache_valid)
1867 {
1868 _begin_cache = drop_begin();
1869 _begin_cache_valid = true;
1870 }
1871 return static_cast<size_t>(etl::distance(_begin_cache, ETL_OR_STD::end(_r)));
1872 }
1873
1874 private:
1875
1876 constexpr iterator drop_begin() const
1877 {
1878 iterator result{ETL_OR_STD::end(_r)};
1879 if (static_cast<difference_type>(_drop_n) < etl::distance(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r)))
1880 {
1881 result = ETL_OR_STD::begin(_r);
1882 etl::advance(result, _drop_n);
1883 }
1884 return result;
1885 }
1886
1887 Range _r;
1888 size_t _drop_n;
1889 mutable iterator _begin_cache;
1890 mutable bool _begin_cache_valid;
1891 };
1892
1893 template <class Range>
1894 drop_view(Range&&) -> drop_view<views::all_t<Range>>;
1895
1896 struct drop_range_adapter_closure : public range_adapter_closure<drop_range_adapter_closure>
1897 {
1898 template <typename Range>
1899 using target_view_type = drop_view<Range>;
1900
1901 constexpr drop_range_adapter_closure(size_t drop_n)
1902 : _drop_n{drop_n}
1903 {
1904 }
1905
1906 template <typename Range>
1907 constexpr auto operator()(Range&& r) const
1908 {
1909 return drop_view(views::all(etl::forward<Range>(r)), _drop_n);
1910 }
1911
1912 const size_t _drop_n;
1913 };
1914
1915 namespace views
1916 {
1917 namespace private_views
1918 {
1919 struct drop
1920 {
1921 template <class Range>
1922 constexpr auto operator()(Range&& r, size_t drop_n) const
1923 {
1924 return drop_view(views::all(etl::forward<Range>(r)), drop_n);
1925 }
1926
1927 constexpr auto operator()(size_t drop_n) const
1928 {
1929 return ranges::drop_range_adapter_closure(drop_n);
1930 }
1931 };
1932 } // namespace private_views
1933
1934 inline constexpr private_views::drop drop;
1935 } // namespace views
1936
1937 template <class Range, class Pred>
1938 class drop_while_view : public etl::ranges::view_interface<drop_while_view<Range, Pred>>
1939 {
1940 public:
1941
1942 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
1943 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
1944
1945 constexpr drop_while_view(Range&& r, Pred pred)
1946 : _r{etl::move(r)}
1947 , _pred{pred}
1948 , _begin_cache{}
1949 , _begin_cache_valid{false}
1950 {
1951 }
1952
1953 constexpr const Range base() const&
1954 {
1955 return _r;
1956 }
1957
1958 constexpr const Pred& pred() const
1959 {
1960 return _pred;
1961 }
1962
1963 constexpr const_iterator begin() const
1964 {
1965 if (!_begin_cache_valid)
1966 {
1967 const_iterator result{ETL_OR_STD::cbegin(_r)};
1968 while (result != ETL_OR_STD::cend(_r) && _pred(*result))
1969 {
1970 ++result;
1971 }
1972 _begin_cache = result;
1973 _begin_cache_valid = true;
1974 }
1975 return _begin_cache;
1976 }
1977
1978 constexpr const_iterator end() const
1979 {
1980 return const_iterator(ETL_OR_STD::cend(_r));
1981 }
1982
1983 private:
1984
1985 Range _r;
1986 Pred _pred;
1987 mutable const_iterator _begin_cache;
1988 mutable bool _begin_cache_valid;
1989 };
1990
1991 template <class Range, class Pred>
1992 drop_while_view(Range&&, Pred) -> drop_while_view<views::all_t<Range>, Pred>;
1993
1994 template <typename Pred>
1995 struct drop_while_range_adapter_closure : public range_adapter_closure<drop_while_range_adapter_closure<Pred>>
1996 {
1997 template <typename Range>
1998 using target_view_type = drop_while_view<Range, Pred>;
1999
2000 constexpr drop_while_range_adapter_closure(Pred& pred)
2001 : _pred{pred}
2002 {
2003 }
2004
2005 template <typename Range>
2006 constexpr auto operator()(Range&& r) const
2007 {
2008 return drop_while_view(views::all(etl::forward<Range>(r)), _pred);
2009 }
2010
2011 Pred _pred;
2012 };
2013
2014 namespace views
2015 {
2016 namespace private_views
2017 {
2018 struct drop_while
2019 {
2020 template <class Range, class Pred>
2021 constexpr auto operator()(Range&& r, Pred pred) const
2022 {
2023 return drop_while_view(views::all(etl::forward<Range>(r)), pred);
2024 }
2025
2026 template <class Pred>
2027 constexpr auto operator()(Pred pred) const
2028 {
2029 return ranges::drop_while_range_adapter_closure(pred);
2030 }
2031 };
2032 } // namespace private_views
2033
2034 inline constexpr private_views::drop_while drop_while;
2035 } // namespace views
2036
2037 // Own implementation instead of using etl::min to avoid including
2038 // algorithm.h
2039 namespace private_views
2040 {
2041 template <typename T>
2042 constexpr T min(T a, T b)
2043 {
2044 return a < b ? a : b;
2045 }
2046 } // namespace private_views
2047
2048 template <class Range>
2049 class take_view : public etl::ranges::view_interface<take_view<Range>>
2050 {
2051 public:
2052
2053 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
2054 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
2055 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
2056
2057 constexpr take_view(Range&& r, ranges::range_difference_t<Range> take_n)
2058 : _r{etl::move(r)}
2059 , _take_n{private_views::min<ranges::range_difference_t<Range>>(take_n, etl::distance(ETL_OR_STD::cbegin(r), ETL_OR_STD::cend(r)))}
2060 {
2061 }
2062
2063 take_view(const take_view& other) = default;
2064
2065 constexpr Range base() const&
2066 {
2067 return _r;
2068 }
2069
2070 constexpr iterator begin() const
2071 {
2072 return iterator(ETL_OR_STD::begin(_r));
2073 }
2074
2075 constexpr iterator end() const
2076 {
2077 iterator result{begin()};
2078 etl::advance(result, _take_n);
2079 return result;
2080 }
2081
2082 constexpr ranges::range_difference_t<Range> size() const
2083 {
2084 return _take_n;
2085 }
2086
2087 private:
2088
2089 Range _r;
2090 ranges::range_difference_t<Range> _take_n;
2091 };
2092
2093 template <class Range>
2094 take_view(Range&&, ranges::range_difference_t<Range>) -> take_view<views::all_t<Range>>;
2095
2096 struct take_range_adapter_closure : public range_adapter_closure<take_range_adapter_closure>
2097 {
2098 template <typename Range>
2099 using target_view_type = take_view<Range>;
2100
2101 template <class DifferenceType>
2102 constexpr take_range_adapter_closure(DifferenceType take_n)
2103 : _take_n{static_cast<size_t>(take_n)}
2104 {
2105 }
2106
2107 template <typename Range>
2108 constexpr auto operator()(Range&& r) const
2109 {
2110 return take_view(views::all(etl::forward<Range>(r)), static_cast<ranges::range_difference_t<Range>>(_take_n));
2111 }
2112
2113 const size_t _take_n;
2114 };
2115
2116 namespace views
2117 {
2118 namespace private_views
2119 {
2120 struct take
2121 {
2122 template <class Range>
2123 constexpr auto operator()(Range&& r, ranges::range_difference_t<Range> take_n) const
2124 {
2125 return take_view(views::all(etl::forward<Range>(r)), take_n);
2126 }
2127
2128 template <class DifferenceType>
2129 constexpr auto operator()(DifferenceType take_n) const
2130 {
2131 return ranges::take_range_adapter_closure(take_n);
2132 }
2133 };
2134 } // namespace private_views
2135
2136 inline constexpr private_views::take take;
2137 } // namespace views
2138
2139 template <class Range, class Pred>
2140 class take_while_view : public etl::ranges::view_interface<take_while_view<Range, Pred>>
2141 {
2142 public:
2143
2144 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
2145 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
2146 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
2147
2148 constexpr take_while_view(Range&& r, Pred pred)
2149 : _r{etl::move(r)}
2150 , _pred{etl::move(pred)}
2151 , _end_cache{}
2152 , _end_cache_valid{false}
2153 {
2154 }
2155
2156 constexpr const Range base() const&
2157 {
2158 return _r;
2159 }
2160
2161 constexpr const Pred& pred() const
2162 {
2163 return _pred;
2164 }
2165
2166 constexpr auto begin() const
2167 {
2168 return ETL_OR_STD::begin(_r);
2169 }
2170
2171 constexpr auto end() const
2172 {
2173 if (!_end_cache_valid)
2174 {
2175 iterator result{ETL_OR_STD::begin(_r)};
2176 while (result != ETL_OR_STD::end(_r) && _pred(*result))
2177 {
2178 ++result;
2179 }
2180 _end_cache = result;
2181 _end_cache_valid = true;
2182 }
2183 return _end_cache;
2184 }
2185
2186 private:
2187
2188 Range _r;
2189 Pred _pred;
2190 mutable iterator _end_cache;
2191 mutable bool _end_cache_valid;
2192 };
2193
2194 template <class Range, class Pred>
2195 take_while_view(Range&&, Pred) -> take_while_view<views::all_t<Range>, Pred>;
2196
2197 template <typename Pred>
2198 struct take_while_range_adapter_closure : public range_adapter_closure<take_while_range_adapter_closure<Pred>>
2199 {
2200 template <typename Range>
2201 using target_view_type = take_while_view<Range, Pred>;
2202
2203 constexpr take_while_range_adapter_closure(Pred pred)
2204 : _pred{etl::move(pred)}
2205 {
2206 }
2207
2208 template <typename Range>
2209 constexpr auto operator()(Range&& r) const
2210 {
2211 return take_while_view(views::all(etl::forward<Range>(r)), _pred);
2212 }
2213
2214 Pred _pred;
2215 };
2216
2217 namespace views
2218 {
2219 namespace private_views
2220 {
2221 struct take_while
2222 {
2223 template <class Range, class Pred>
2224 constexpr auto operator()(Range&& r, Pred&& pred) const
2225 {
2226 return take_while_view(views::all(etl::forward<Range>(r)), etl::forward<Pred>(pred));
2227 }
2228
2229 template <class Pred>
2230 constexpr auto operator()(Pred&& pred) const
2231 {
2232 return ranges::take_while_range_adapter_closure(etl::forward<Pred>(pred));
2233 }
2234 };
2235 } // namespace private_views
2236
2237 inline constexpr private_views::take_while take_while;
2238 } // namespace views
2239
2240 template <class Range>
2241 class join_iterator
2242 {
2243 public:
2244
2245 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
2246
2247 using iterator = typename trait::iterator;
2248 using const_iterator = typename trait::const_iterator;
2249 using difference_type = typename trait::difference_type;
2250
2251 using iterator_category = ETL_OR_STD::forward_iterator_tag;
2252
2253 using InnerRange = decltype(*(ETL_OR_STD::begin(etl::declval<Range>())));
2254 using inner_trait = typename etl::ranges::private_ranges::iterator_trait<InnerRange>;
2255 using inner_iterator = typename inner_trait::iterator;
2256
2257 using value_type = typename inner_trait::value_type;
2258 using pointer = typename inner_trait::pointer;
2259 using reference = typename inner_trait::reference;
2260
2261 join_iterator(iterator it, iterator it_end)
2262 : _it(it)
2263 , _it_end(it_end)
2264 , _inner_it(it != it_end ? ETL_OR_STD::begin(*it) : inner_iterator{})
2265 , _inner_it_end(it != it_end ? ETL_OR_STD::end(*it) : inner_iterator{})
2266 {
2267 adjust_iterator();
2268 }
2269
2270 join_iterator(const join_iterator& other) = default;
2271
2272 join_iterator& operator++()
2273 {
2274 if (_inner_it != _inner_it_end)
2275 {
2276 ++_inner_it;
2277 }
2278
2279 adjust_iterator();
2280
2281 return *this;
2282 }
2283
2284 join_iterator operator++(int)
2285 {
2286 join_iterator tmp{*this};
2287
2288 if (_inner_it != _inner_it_end)
2289 {
2290 _inner_it++;
2291 }
2292
2293 adjust_iterator();
2294
2295 return tmp;
2296 }
2297
2298 join_iterator& operator=(const join_iterator& other)
2299 {
2300 _it = other._it;
2301 _it_end = other._it_end;
2302 _inner_it = other._inner_it;
2303 _inner_it_end = other._inner_it_end;
2304
2305 adjust_iterator();
2306
2307 return *this;
2308 }
2309
2310 reference operator*() const
2311 {
2312 return *_inner_it;
2313 }
2314
2315 constexpr bool operator==(const join_iterator& other) const
2316 {
2317 return (_it == other._it && _inner_it == other._inner_it) || (_it == _it_end && other._it == other._it_end);
2318 }
2319
2320 constexpr bool operator!=(const join_iterator& other) const
2321 {
2322 return !(*this == other);
2323 }
2324
2325 private:
2326
2327 void adjust_iterator()
2328 {
2329 while (_it != _it_end && _inner_it == _inner_it_end)
2330 {
2331 ++_it;
2332 if (_it != _it_end)
2333 {
2334 _inner_it = ETL_OR_STD::begin((*_it));
2335 _inner_it_end = ETL_OR_STD::end((*_it));
2336 }
2337 }
2338 }
2339
2340 iterator _it;
2341 iterator _it_end;
2342 inner_iterator _inner_it;
2343 inner_iterator _inner_it_end;
2344 };
2345
2346 template <class Range>
2347 class join_view : public etl::ranges::view_interface<join_view<Range>>
2348 {
2349 public:
2350
2351 using iterator = join_iterator<Range>;
2352 using const_iterator = join_iterator<Range>;
2353
2354 join_view(Range&& r)
2355 : _r{etl::move(r)}
2356 {
2357 }
2358
2359 constexpr Range base() const&
2360 {
2361 return _r;
2362 }
2363
2364 constexpr iterator begin() const
2365 {
2366 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r));
2367 }
2368
2369 constexpr iterator end() const
2370 {
2371 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r));
2372 }
2373
2374 private:
2375
2376 Range _r;
2377 };
2378
2379 struct join_range_adapter_closure : public range_adapter_closure<join_range_adapter_closure>
2380 {
2381 template <typename Range>
2382 using target_view_type = join_view<Range>;
2383
2384 join_range_adapter_closure() = default;
2385
2386 template <typename Range>
2387 constexpr auto operator()(Range&& r)
2388 {
2389 return join_view(views::all(etl::forward<Range>(r)));
2390 }
2391 };
2392
2393 template <class Range>
2394 explicit join_view(Range&&) -> join_view<views::all_t<Range>>;
2395
2396 namespace views
2397 {
2398 namespace private_views
2399 {
2400 struct join
2401 {
2402 template <class Range>
2403 constexpr auto operator()(Range&& r) const
2404 {
2405 return join_view(views::all(etl::forward<Range>(r)));
2406 }
2407
2408 constexpr auto operator()() const
2409 {
2410 return ranges::join_range_adapter_closure();
2411 }
2412 };
2413 } // namespace private_views
2414
2415 inline constexpr private_views::join join;
2416 } // namespace views
2417
2418 template <class Range, class Pattern>
2419 class join_with_iterator
2420 {
2421 public:
2422
2423 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
2424
2425 using iterator = typename trait::iterator;
2426 using const_iterator = typename trait::const_iterator;
2427 using difference_type = typename trait::difference_type;
2428
2429 using iterator_category = ETL_OR_STD::forward_iterator_tag;
2430
2431 using InnerRange = decltype(*(ETL_OR_STD::begin(etl::declval<Range>())));
2432 using inner_trait = typename etl::ranges::private_ranges::iterator_trait<InnerRange>;
2433 using inner_iterator = typename inner_trait::iterator;
2434
2435 using value_type = typename inner_trait::value_type;
2436 using pointer = typename inner_trait::pointer;
2437 using reference = typename inner_trait::reference;
2438
2439 using pattern_trait = typename etl::ranges::private_ranges::iterator_trait<Pattern>;
2440 using pattern_iterator = typename pattern_trait::iterator;
2441 using pattern_const_iterator = typename pattern_trait::const_iterator;
2442
2443 join_with_iterator(iterator it, iterator it_end, const Pattern& pattern)
2444 : _it(it)
2445 , _it_end(it_end)
2446 , _inner_it(it != it_end ? ETL_OR_STD::begin(*it) : inner_iterator{})
2447 , _inner_it_end(it != it_end ? ETL_OR_STD::end(*it) : inner_iterator{})
2448 , _pattern(pattern)
2449 , _pattern_it(pattern.cend())
2450 , _pattern_it_end(pattern.cend())
2451 {
2452 adjust_iterator();
2453 }
2454
2455 join_with_iterator(const join_with_iterator& other) = default;
2456
2457 join_with_iterator& operator++()
2458 {
2459 if (_pattern_it != _pattern_it_end)
2460 {
2461 ++_pattern_it;
2462 }
2463 else if (_inner_it != _inner_it_end)
2464 {
2465 ++_inner_it;
2466 }
2467
2468 adjust_iterator();
2469
2470 return *this;
2471 }
2472
2473 join_with_iterator operator++(int)
2474 {
2475 join_with_iterator tmp{*this};
2476
2477 if (_pattern_it != _pattern_it_end)
2478 {
2479 _pattern_it++;
2480 }
2481 else if (_inner_it != _inner_it_end)
2482 {
2483 _inner_it++;
2484 }
2485
2486 adjust_iterator();
2487
2488 return tmp;
2489 }
2490
2491 join_with_iterator& operator=(const join_with_iterator& other)
2492 {
2493 _it = other._it;
2494 _it_end = other._it_end;
2495 _inner_it = other._inner_it;
2496 _inner_it_end = other._inner_it_end;
2497 _pattern_it = other._pattern_it;
2498 _pattern_it_end = other._pattern_it_end;
2499
2500 adjust_iterator();
2501
2502 return *this;
2503 }
2504
2505 value_type operator*() const
2506 {
2507 if (_pattern_it != _pattern_it_end)
2508 {
2509 return *_pattern_it;
2510 }
2511 return *_inner_it;
2512 }
2513
2514 constexpr bool operator==(const join_with_iterator& other) const
2515 {
2516 return (_it == other._it && _inner_it == other._inner_it && _pattern_it == other._pattern_it) || (_it == _it_end);
2517 }
2518
2519 constexpr bool operator!=(const join_with_iterator& other) const
2520 {
2521 return !(*this == other);
2522 }
2523
2524 private:
2525
2526 void adjust_iterator()
2527 {
2528 if (_it != _it_end && _inner_it == _inner_it_end && _pattern_it == _pattern_it_end)
2529 {
2530 ++_it;
2531 if (_it != _it_end)
2532 {
2533 _pattern_it = ETL_OR_STD::cbegin(_pattern);
2534 _pattern_it_end = ETL_OR_STD::cend(_pattern);
2535 _inner_it = ETL_OR_STD::begin(*_it);
2536 _inner_it_end = ETL_OR_STD::end(*_it);
2537 }
2538 }
2539 }
2540
2541 iterator _it;
2542 iterator _it_end;
2543 inner_iterator _inner_it;
2544 inner_iterator _inner_it_end;
2545 const Pattern& _pattern;
2546 pattern_const_iterator _pattern_it;
2547 pattern_const_iterator _pattern_it_end;
2548 };
2549
2550 template <class Range, class Pattern>
2551 class join_with_view : public etl::ranges::view_interface<join_with_view<Range, Pattern>>
2552 {
2553 public:
2554
2555 using iterator = join_with_iterator<Range, Pattern>;
2556 using const_iterator = join_with_iterator<Range, Pattern>;
2557
2558 join_with_view(Range&& r, Pattern&& pattern)
2559 : _r{etl::move(r)}
2560 , _pattern{etl::move(pattern)}
2561 {
2562 }
2563
2564 constexpr Range base() const&
2565 {
2566 return _r;
2567 }
2568
2569 constexpr iterator begin() const
2570 {
2571 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _pattern);
2572 }
2573
2574 constexpr iterator end() const
2575 {
2576 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _pattern);
2577 }
2578
2579 private:
2580
2581 Range _r;
2582 Pattern _pattern;
2583 };
2584
2585 // For range as separator
2586 template <class Range, class Pattern>
2587 join_with_view(Range&&, Pattern&&) -> join_with_view<views::all_t<Range>, views::all_t<Pattern>>;
2588
2589 // For single value as separator
2590 template <class Range>
2591 join_with_view(Range&&, etl::ranges::range_value_t<etl::ranges::range_reference_t<Range>>)
2592 -> join_with_view<views::all_t<Range>, etl::ranges::single_view<etl::ranges::range_value_t< etl::ranges::range_reference_t<Range>>>>;
2593
2594 namespace private_ranges
2595 {
2596 template <class Pattern>
2597 constexpr auto make_pattern(Pattern&& pattern)
2598 {
2599 if constexpr (etl::is_base_of_v<etl::ranges::view_interface<Pattern>, Pattern>)
2600 {
2601 return etl::forward<Pattern>(pattern);
2602 }
2603 else
2604 {
2605 return etl::ranges::single_view<Pattern>(etl::forward<Pattern>(pattern));
2606 }
2607 }
2608
2609 template <class Pattern>
2610 constexpr auto make_pattern(const Pattern& pattern)
2611 {
2612 if constexpr (etl::is_array_v<etl::remove_reference_t<Pattern>> || etl::is_range_v<etl::remove_reference_t<Pattern>>)
2613 {
2614 return views::all(pattern);
2615 }
2616 else
2617 {
2618 return etl::ranges::single_view<etl::remove_reference_t<Pattern>>(pattern);
2619 }
2620 }
2621 } // namespace private_ranges
2622
2623 template <class Pattern>
2624 struct join_with_range_adapter_closure : public range_adapter_closure<join_with_range_adapter_closure<Pattern>>
2625 {
2626 template <typename Range>
2627 using target_view_type = join_with_view<Range, Pattern>;
2628
2629 join_with_range_adapter_closure(const Pattern& pattern)
2630 : _pattern(pattern)
2631 {
2632 }
2633
2634 template <typename Range>
2635 constexpr auto operator()(Range&& r)
2636 {
2637 return join_with_view(views::all(etl::forward<Range>(r)), private_ranges::make_pattern<Pattern>(_pattern));
2638 }
2639
2640 const Pattern& _pattern;
2641 };
2642
2643 namespace views
2644 {
2645 namespace private_views
2646 {
2647 struct join_with
2648 {
2649 template <class Range, class Pattern>
2650 constexpr auto operator()(Range&& r, Pattern&& pattern) const
2651 {
2652 return join_with_view(views::all(etl::forward<Range>(r)),
2653 views::all(etl::ranges::private_ranges::make_pattern<Pattern>(etl::forward<Pattern>(pattern))));
2654 }
2655
2656 template <class Pattern>
2657 constexpr auto operator()(const Pattern& pattern) const
2658 {
2659 return ranges::join_with_range_adapter_closure(pattern);
2660 }
2661 };
2662 } // namespace private_views
2663
2664 inline constexpr private_views::join_with join_with;
2665 } // namespace views
2666
2667 template <class Range, class Pattern>
2668 class split_iterator
2669 {
2670 public:
2671
2672 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
2673
2674 using iterator = typename trait::iterator;
2675 using const_iterator = typename trait::const_iterator;
2676 using difference_type = typename trait::difference_type;
2677
2678 using iterator_category = ETL_OR_STD::forward_iterator_tag;
2679
2680 using pattern_trait = typename etl::ranges::private_ranges::iterator_trait<Pattern>;
2681 using pattern_const_iterator = typename pattern_trait::const_iterator;
2682
2683 using value_type = etl::ranges::subrange<const_iterator>;
2684 using pointer = value_type*;
2685 using reference = value_type;
2686
2687 split_iterator(const_iterator it, const_iterator it_end, const Pattern& pattern, bool is_end = false)
2688 : _it(it)
2689 , _it_end(it_end)
2690 , _pattern(pattern)
2691 , _next(find_next())
2692 , _trailing_empty(!is_end && _it == _it_end)
2693 {
2694 }
2695
2696 split_iterator(const split_iterator& other) = default;
2697
2698 split_iterator& operator++()
2699 {
2700 _it = _next;
2701
2702 if (_it != _it_end)
2703 {
2704 // Skip past the delimiter
2705 auto pat_size = etl::distance(ETL_OR_STD::cbegin(_pattern), ETL_OR_STD::cend(_pattern));
2706 for (difference_type i = 0; i < pat_size && _it != _it_end; ++i)
2707 {
2708 ++_it;
2709 }
2710 _next = find_next();
2711 // If we landed exactly at _it_end after skipping the delimiter,
2712 // there is one more trailing empty segment to emit.
2713 if (_it == _it_end && !_trailing_empty)
2714 {
2715 _trailing_empty = true;
2716 }
2717 }
2718 else
2719 {
2720 // We were at _it_end; this was the trailing empty segment.
2721 _trailing_empty = false;
2722 }
2723
2724 return *this;
2725 }
2726
2727 split_iterator operator++(int)
2728 {
2729 split_iterator tmp{*this};
2730 ++(*this);
2731 return tmp;
2732 }
2733
2734 split_iterator& operator=(const split_iterator& other)
2735 {
2736 _it = other._it;
2737 _it_end = other._it_end;
2738 _next = other._next;
2739 _trailing_empty = other._trailing_empty;
2740 return *this;
2741 }
2742
2743 value_type operator*() const
2744 {
2745 return value_type(_it, _next);
2746 }
2747
2748 constexpr bool operator==(const split_iterator& other) const
2749 {
2750 if (_it == _it_end && other._it == other._it_end)
2751 {
2752 return _trailing_empty == other._trailing_empty;
2753 }
2754 return _it == other._it;
2755 }
2756
2757 constexpr bool operator!=(const split_iterator& other) const
2758 {
2759 return !(*this == other);
2760 }
2761
2762 private:
2763
2764 const_iterator find_next() const
2765 {
2766 auto pat_begin = ETL_OR_STD::cbegin(_pattern);
2767 auto pat_end = ETL_OR_STD::cend(_pattern);
2768 auto pat_size = etl::distance(pat_begin, pat_end);
2769
2770 if (pat_size == 0)
2771 {
2772 // Empty pattern: split between each element
2773 auto result = _it;
2774 if (result != _it_end)
2775 {
2776 ++result;
2777 }
2778 return result;
2779 }
2780
2781 for (auto search = _it; search != _it_end; ++search)
2782 {
2783 // Try to match the full pattern starting at 'search'
2784 auto s = search;
2785 auto p = pat_begin;
2786 bool match = true;
2787 while (p != pat_end)
2788 {
2789 if (s == _it_end || !(*s == *p))
2790 {
2791 match = false;
2792 break;
2793 }
2794 ++s;
2795 ++p;
2796 }
2797 if (match)
2798 {
2799 return search;
2800 }
2801 }
2802
2803 return _it_end;
2804 }
2805
2806 const_iterator _it;
2807 const_iterator _it_end;
2808 const Pattern& _pattern;
2809 const_iterator _next;
2810 // there is still one empty segment to emit after the last delimiter if
2811 // the last delimiter is at the end of the range
2812 bool _trailing_empty;
2813 };
2814
2815 template <class Range, class Pattern>
2816 class split_view : public etl::ranges::view_interface<split_view<Range, Pattern>>
2817 {
2818 public:
2819
2820 using iterator = split_iterator<Range, Pattern>;
2821 using const_iterator = split_iterator<Range, Pattern>;
2822
2823 split_view(Range&& r, Pattern&& pattern)
2824 : _r{etl::move(r)}
2825 , _pattern{etl::move(pattern)}
2826 {
2827 }
2828
2829 constexpr Range& base() const&
2830 {
2831 return _r;
2832 }
2833
2834 constexpr const Pattern& pattern() const
2835 {
2836 return _pattern;
2837 }
2838
2839 constexpr iterator begin() const
2840 {
2841 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _pattern);
2842 }
2843
2844 constexpr iterator end() const
2845 {
2846 auto it = iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _pattern, true);
2847 return it;
2848 }
2849
2850 private:
2851
2852 Range _r;
2853 Pattern _pattern;
2854 };
2855
2856 // For range as delimiter (Pattern is a range, not a single value)
2857 template <class Range, class Pattern, etl::enable_if_t<etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
2858 split_view(Range&&, Pattern&&) -> split_view<views::all_t<Range>, views::all_t<Pattern>>;
2859
2860 // For single value as delimiter (Pattern is not a range)
2861 template < class Range, class Pattern, etl::enable_if_t<!etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
2862 split_view(Range&&, Pattern&&) -> split_view<views::all_t<Range>, etl::ranges::single_view<etl::decay_t<Pattern>>>;
2863
2864 template <class Pattern>
2865 struct split_range_adapter_closure : public range_adapter_closure<split_range_adapter_closure<Pattern>>
2866 {
2867 template <typename Range>
2868 using target_view_type = split_view<Range, Pattern>;
2869
2870 split_range_adapter_closure(const Pattern& pattern)
2871 : _pattern(pattern)
2872 {
2873 }
2874
2875 template <typename Range>
2876 constexpr auto operator()(Range&& r)
2877 {
2878 // If Pattern is a range, use views::all. If not, wrap in single_view.
2879 if constexpr (etl::is_class_v<etl::decay_t<Pattern>>)
2880 {
2881 return split_view(views::all(etl::forward<Range>(r)), views::all(_pattern));
2882 }
2883 else
2884 {
2885 return split_view(views::all(etl::forward<Range>(r)), etl::ranges::single_view(_pattern));
2886 }
2887 }
2888
2889 const Pattern& _pattern;
2890 };
2891
2892 namespace views
2893 {
2894 namespace private_views
2895 {
2896 struct split
2897 {
2898 // Range + Pattern (Pattern is a range)
2899 template < class Range, class Pattern, etl::enable_if_t<etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
2900 constexpr auto operator()(Range&& r, Pattern&& pattern) const
2901 {
2902 return split_view(views::all(etl::forward<Range>(r)), views::all(etl::forward<Pattern>(pattern)));
2903 }
2904
2905 // Range + Pattern (Pattern is a single value)
2906 template < class Range, class Pattern, etl::enable_if_t<!etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
2907 constexpr auto operator()(Range&& r, Pattern&& pattern) const
2908 {
2909 return split_view(views::all(etl::forward<Range>(r)), etl::ranges::single_view(pattern));
2910 }
2911
2912 // Pipe closure
2913 template <class Pattern>
2914 constexpr auto operator()(const Pattern& pattern) const
2915 {
2916 return ranges::split_range_adapter_closure<Pattern>(pattern);
2917 }
2918 };
2919 } // namespace private_views
2920
2921 inline constexpr private_views::split split;
2922 } // namespace views
2923
2924 //*************************************************************************
2930 //*************************************************************************
2931
2932 template <class Range, class Pattern>
2933 class lazy_split_view;
2934
2938 template <class Range, class Pattern>
2939 class lazy_split_inner_range
2940 {
2941 public:
2942
2943 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
2944 using const_iterator_type = typename trait::const_iterator;
2945 using value_type = typename trait::value_type;
2946
2947 using pattern_trait = typename etl::ranges::private_ranges::iterator_trait<Pattern>;
2948 using pattern_const_iterator = typename pattern_trait::const_iterator;
2949
2950 class iterator
2951 {
2952 public:
2953
2954 using value_type = typename trait::value_type;
2955 using difference_type = typename trait::difference_type;
2956 using pointer = const value_type*;
2957 using reference = const value_type&;
2958 using iterator_category = ETL_OR_STD::forward_iterator_tag;
2959
2960 iterator() = default;
2961
2962 iterator(const_iterator_type current, const_iterator_type segment_end, bool is_end)
2963 : _current(current)
2964 , _segment_end(segment_end)
2965 , _is_end(is_end || (current == segment_end))
2966 {
2967 }
2968
2969 reference operator*() const
2970 {
2971 return *_current;
2972 }
2973
2974 pointer operator->() const
2975 {
2976 return &(*_current);
2977 }
2978
2979 iterator& operator++()
2980 {
2981 ++_current;
2982 if (_current == _segment_end)
2983 {
2984 _is_end = true;
2985 }
2986 return *this;
2987 }
2988
2989 iterator operator++(int)
2990 {
2991 iterator tmp{*this};
2992 ++(*this);
2993 return tmp;
2994 }
2995
2996 constexpr bool operator==(const iterator& other) const
2997 {
2998 if (_is_end && other._is_end)
2999 {
3000 return true;
3001 }
3002 if (_is_end != other._is_end)
3003 {
3004 return false;
3005 }
3006 return _current == other._current;
3007 }
3008
3009 constexpr bool operator!=(const iterator& other) const
3010 {
3011 return !(*this == other);
3012 }
3013
3014 private:
3015
3016 const_iterator_type _current{};
3017 const_iterator_type _segment_end{};
3018 bool _is_end = true;
3019 };
3020
3021 using const_iterator = iterator;
3022
3023 lazy_split_inner_range(const_iterator_type segment_begin, const_iterator_type segment_end)
3024 : _segment_begin(segment_begin)
3025 , _segment_end(segment_end)
3026 {
3027 }
3028
3029 iterator begin() const
3030 {
3031 return iterator(_segment_begin, _segment_end, false);
3032 }
3033
3034 iterator end() const
3035 {
3036 return iterator(_segment_end, _segment_end, true);
3037 }
3038
3039 bool empty() const
3040 {
3041 return _segment_begin == _segment_end;
3042 }
3043
3044 private:
3045
3046 const_iterator_type _segment_begin;
3047 const_iterator_type _segment_end;
3048 };
3049
3053 template <class Range, class Pattern>
3054 class lazy_split_iterator
3055 {
3056 public:
3057
3058 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
3059
3060 using source_iterator = typename trait::iterator;
3061 using const_iterator = typename trait::const_iterator;
3062 using difference_type = typename trait::difference_type;
3063
3064 using iterator_category = ETL_OR_STD::forward_iterator_tag;
3065
3066 using pattern_trait = typename etl::ranges::private_ranges::iterator_trait<Pattern>;
3067 using pattern_const_iterator = typename pattern_trait::const_iterator;
3068
3069 using value_type = lazy_split_inner_range<Range, Pattern>;
3070 using pointer = value_type*;
3071 using reference = value_type;
3072
3073 lazy_split_iterator(const_iterator it, const_iterator it_end, const Pattern& pattern, bool is_end = false)
3074 : _it(it)
3075 , _it_end(it_end)
3076 , _pattern(pattern)
3077 , _next(find_next())
3078 , _trailing_empty(!is_end && _it == _it_end)
3079 {
3080 }
3081
3082 lazy_split_iterator(const lazy_split_iterator& other) = default;
3083
3084 lazy_split_iterator& operator=(const lazy_split_iterator& other)
3085 {
3086 _it = other._it;
3087 _it_end = other._it_end;
3088 _next = other._next;
3089 _trailing_empty = other._trailing_empty;
3090 return *this;
3091 }
3092
3093 lazy_split_iterator& operator++()
3094 {
3095 _it = _next;
3096
3097 if (_it != _it_end)
3098 {
3099 // Skip past the matched delimiter
3100 auto pat_size = etl::distance(ETL_OR_STD::cbegin(_pattern), ETL_OR_STD::cend(_pattern));
3101 for (difference_type i = 0; i < pat_size && _it != _it_end; ++i)
3102 {
3103 ++_it;
3104 }
3105 _next = find_next();
3106 // If we landed exactly at _it_end after skipping the delimiter,
3107 // there is one more trailing empty segment to emit.
3108 if (_it == _it_end && !_trailing_empty)
3109 {
3110 _trailing_empty = true;
3111 }
3112 }
3113 else
3114 {
3115 // We were at _it_end; this was the trailing empty segment.
3116 _trailing_empty = false;
3117 }
3118
3119 return *this;
3120 }
3121
3122 lazy_split_iterator operator++(int)
3123 {
3124 lazy_split_iterator tmp{*this};
3125 ++(*this);
3126 return tmp;
3127 }
3128
3131 value_type operator*() const
3132 {
3133 return value_type(_it, _next);
3134 }
3135
3136 constexpr bool operator==(const lazy_split_iterator& other) const
3137 {
3138 if (_it == _it_end && other._it == other._it_end)
3139 {
3140 return _trailing_empty == other._trailing_empty;
3141 }
3142 return _it == other._it;
3143 }
3144
3145 constexpr bool operator!=(const lazy_split_iterator& other) const
3146 {
3147 return !(*this == other);
3148 }
3149
3150 private:
3151
3154 const_iterator find_next() const
3155 {
3156 auto pat_begin = ETL_OR_STD::cbegin(_pattern);
3157 auto pat_end = ETL_OR_STD::cend(_pattern);
3158 auto pat_size = etl::distance(pat_begin, pat_end);
3159
3160 if (pat_size == 0)
3161 {
3162 // Empty pattern: split between each element
3163 auto result = _it;
3164 if (result != _it_end)
3165 {
3166 ++result;
3167 }
3168 return result;
3169 }
3170
3171 for (auto search = _it; search != _it_end; ++search)
3172 {
3173 // Try to match the full pattern starting at 'search'
3174 auto s = search;
3175 auto p = pat_begin;
3176 bool match = true;
3177 while (p != pat_end)
3178 {
3179 if (s == _it_end || !(*s == *p))
3180 {
3181 match = false;
3182 break;
3183 }
3184 ++s;
3185 ++p;
3186 }
3187 if (match)
3188 {
3189 return search;
3190 }
3191 }
3192
3193 return _it_end;
3194 }
3195
3196 const_iterator _it;
3197 const_iterator _it_end;
3198 const Pattern& _pattern;
3199 const_iterator _next;
3200 bool _trailing_empty;
3201 };
3202
3203 template <class Range, class Pattern>
3204 class lazy_split_view : public etl::ranges::view_interface<lazy_split_view<Range, Pattern>>
3205 {
3206 public:
3207
3208 using iterator = lazy_split_iterator<Range, Pattern>;
3209 using const_iterator = lazy_split_iterator<Range, Pattern>;
3210
3211 lazy_split_view(Range&& r, Pattern&& pattern)
3212 : _r{etl::move(r)}
3213 , _pattern{etl::move(pattern)}
3214 {
3215 }
3216
3217 constexpr Range& base() const&
3218 {
3219 return _r;
3220 }
3221
3222 constexpr const Pattern& pattern() const
3223 {
3224 return _pattern;
3225 }
3226
3227 constexpr iterator begin() const
3228 {
3229 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _pattern);
3230 }
3231
3232 constexpr iterator end() const
3233 {
3234 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _pattern, true);
3235 }
3236
3237 private:
3238
3239 Range _r;
3240 Pattern _pattern;
3241 };
3242
3243 // Deduction guide: range delimiter (Pattern is a range)
3244 template <class Range, class Pattern, etl::enable_if_t<etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
3245 lazy_split_view(Range&&, Pattern&&) -> lazy_split_view<views::all_t<Range>, views::all_t<Pattern>>;
3246
3247 // Deduction guide: single-value delimiter (Pattern is not a range)
3248 template < class Range, class Pattern, etl::enable_if_t<!etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
3249 lazy_split_view(Range&&, Pattern&&) -> lazy_split_view<views::all_t<Range>, etl::ranges::single_view<etl::decay_t<Pattern>>>;
3250
3251 template <class Pattern>
3252 struct lazy_split_range_adapter_closure : public range_adapter_closure<lazy_split_range_adapter_closure<Pattern>>
3253 {
3254 template <typename Range>
3255 using target_view_type = lazy_split_view<Range, Pattern>;
3256
3257 lazy_split_range_adapter_closure(const Pattern& pattern)
3258 : _pattern(pattern)
3259 {
3260 }
3261
3262 template <typename Range>
3263 constexpr auto operator()(Range&& r)
3264 {
3265 if constexpr (etl::is_class_v<etl::decay_t<Pattern>>)
3266 {
3267 return lazy_split_view(views::all(etl::forward<Range>(r)), views::all(_pattern));
3268 }
3269 else
3270 {
3271 return lazy_split_view(views::all(etl::forward<Range>(r)), etl::ranges::single_view(_pattern));
3272 }
3273 }
3274
3275 const Pattern& _pattern;
3276 };
3277
3278 namespace views
3279 {
3280 namespace private_views
3281 {
3282 struct lazy_split
3283 {
3284 // Range + Pattern (Pattern is a range)
3285 template < class Range, class Pattern, etl::enable_if_t<etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
3286 constexpr auto operator()(Range&& r, Pattern&& pattern) const
3287 {
3288 return lazy_split_view(views::all(etl::forward<Range>(r)), views::all(etl::forward<Pattern>(pattern)));
3289 }
3290
3291 // Range + Pattern (Pattern is a single value)
3292 template < class Range, class Pattern, etl::enable_if_t<!etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
3293 constexpr auto operator()(Range&& r, Pattern&& pattern) const
3294 {
3295 return lazy_split_view(views::all(etl::forward<Range>(r)), etl::ranges::single_view(pattern));
3296 }
3297
3298 // Pipe closure
3299 template <class Pattern>
3300 constexpr auto operator()(const Pattern& pattern) const
3301 {
3302 return ranges::lazy_split_range_adapter_closure<Pattern>(pattern);
3303 }
3304 };
3305 } // namespace private_views
3306
3307 inline constexpr private_views::lazy_split lazy_split;
3308 } // namespace views
3309
3310 namespace views
3311 {
3312 namespace private_views
3313 {
3314 struct counted
3315 {
3316 template <class Iterator, class DifferenceType>
3317 constexpr auto operator()(Iterator&& it, DifferenceType&& count) const
3318 {
3319 using T = etl::decay_t<decltype(it)>;
3320 using D = etl::iter_difference_t<T>;
3321
3322 // contiguous_iterator_tag not yet available
3323 // if constexpr(etl::is_same_v<typename
3324 // etl::iterator_traits<Iterator>::iterator_category,
3325 // ETL_OR_STD::contiguous_iterator_tag>)
3326 //{
3327 // return etl::span(etl::to_address(it),
3328 // static_cast<size_t>(static_cast<etl::iter_difference_t<T>>(count)));
3329 //}
3330 // else
3331 if constexpr (etl::is_same_v< typename etl::iterator_traits< Iterator>::iterator_category, ETL_OR_STD::random_access_iterator_tag>)
3332 {
3333 return etl::ranges::subrange(it, it + static_cast<D>(count));
3334 }
3335 else
3336 {
3337 return etl::ranges::subrange(etl::counted_iterator(it, count), etl::default_sentinel);
3338 }
3339 }
3340 };
3341 } // namespace private_views
3342
3343 inline constexpr private_views::counted counted;
3344 } // namespace views
3345
3346 template <class... Ranges>
3347 class concat_view;
3348
3349 template <class... Ranges>
3350 class concat_iterator
3351 {
3352 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3353
3354 public:
3355
3356 using types = typename etl::type_list<Ranges...>;
3357 using first_range = typename etl::type_list_type_at_index_t<types, 0>;
3358 using value_type = typename etl::ranges::private_ranges::iterator_trait< first_range>::value_type;
3359 using reference = typename etl::ranges::private_ranges::iterator_trait< first_range>::reference;
3360 using difference_type = ptrdiff_t;
3361
3362 using iterator_variant_type = typename concat_view<Ranges...>::iterator_variant_type;
3363
3364 concat_iterator(size_t index, concat_view<Ranges...>& view, iterator_variant_type current)
3365 : _ranges_index{index}
3366 , _view(view)
3367 , _current(current)
3368 {
3369 }
3370
3371 concat_iterator(const concat_iterator& other) = default;
3372
3373 constexpr reference operator*() const
3374 {
3375 return _view.get_value(_ranges_index, _current);
3376 }
3377
3378 constexpr decltype(auto) operator[](difference_type pos) const
3379 {
3380 auto tmp = *this;
3381 if (pos > 0)
3382 {
3383 for (difference_type i = 0; i < pos; ++i)
3384 {
3385 tmp._view.advance(tmp._ranges_index, tmp._current, 1);
3386 }
3387 }
3388 if (pos < 0)
3389 {
3390 for (difference_type i = 0; i < -pos; ++i)
3391 {
3392 tmp._view.advance(tmp._ranges_index, tmp._current, -1);
3393 }
3394 }
3395 return *tmp;
3396 }
3397
3398 constexpr concat_iterator& operator++()
3399 {
3400 _view.advance(_ranges_index, _current, 1);
3401 return *this;
3402 }
3403
3404 constexpr concat_iterator operator++(int)
3405 {
3406 auto result = *this;
3407 _view.advance(_ranges_index, _current, 1);
3408 return result;
3409 }
3410
3411 constexpr concat_iterator& operator--()
3412 {
3413 _view.advance(_ranges_index, _current, -1);
3414 return *this;
3415 }
3416
3417 constexpr concat_iterator operator--(int)
3418 {
3419 auto result = *this;
3420 _view.advance(_ranges_index, _current, -1);
3421 return result;
3422 }
3423
3424 constexpr concat_iterator& operator+=(difference_type n)
3425 {
3426 for (difference_type i = 0; i < n; ++i)
3427 {
3428 _view.advance(_ranges_index, _current, 1);
3429 }
3430 return *this;
3431 }
3432
3433 constexpr concat_iterator& operator-=(difference_type n)
3434 {
3435 for (difference_type i = 0; i < n; ++i)
3436 {
3437 _view.advance(_ranges_index, _current, -1);
3438 }
3439 return *this;
3440 }
3441
3442 friend constexpr bool operator==(const concat_iterator<Ranges...>& x, etl::default_sentinel_t)
3443 {
3444 return x._ranges_index == x._view.number_of_ranges - 1
3445 && etl::get<x._view.number_of_ranges - 1>(x._current) == etl::get<x._view.number_of_ranges - 1>(x._view).end();
3446 }
3447
3448 friend constexpr bool operator==(const concat_iterator<Ranges...>& x, const concat_iterator<Ranges...>& y)
3449 {
3450 return x._ranges_index == y._ranges_index && x._current.index() == y._current.index() && x._current == y._current;
3451 }
3452
3453 friend constexpr bool operator!=(const concat_iterator<Ranges...>& x, etl::default_sentinel_t)
3454 {
3455 return !(x == etl::default_sentinel);
3456 }
3457
3458 friend constexpr bool operator!=(const concat_iterator<Ranges...>& x, const concat_iterator<Ranges...>& y)
3459 {
3460 return !(x == y);
3461 }
3462
3463 private:
3464
3465 size_t _ranges_index;
3466 const concat_view<Ranges...>& _view;
3467 iterator_variant_type _current;
3468 };
3469
3470 template <class... Ranges>
3471 class concat_view : public etl::ranges::view_interface<concat_view<Ranges...>>
3472 {
3473 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3474
3475 public:
3476
3477 using types = typename etl::type_list<Ranges...>;
3478 using first_range = typename etl::type_list_type_at_index_t<types, 0>;
3479 using value_type = typename etl::ranges::private_ranges::iterator_trait< first_range>::value_type;
3480 using reference = typename etl::ranges::private_ranges::iterator_trait< first_range>::reference;
3481 using iterator = concat_iterator<Ranges...>;
3482 using const_iterator = concat_iterator<Ranges...>;
3483 using difference_type = typename etl::make_signed_t<size_t>;
3484
3485 using iterator_variant_type =
3486 etl::ranges::private_ranges::mini_variant< typename etl::ranges::private_ranges::iterator_trait< Ranges>::iterator...>;
3487
3488 using get_value_delegates_type = reference (*)(const iterator_variant_type& /*current*/);
3489 using advance_delegates_type = void (*)(size_t& /*index*/, const etl::tuple<Ranges...>& /*r*/, iterator_variant_type& /*current*/,
3490 difference_type /*n*/);
3491
3492 static constexpr const size_t number_of_ranges = sizeof...(Ranges);
3493
3494 constexpr concat_view(Ranges&&... r)
3495 : _r{etl::move(r)...}
3496 {
3497 set_delegates();
3498 }
3499
3500 concat_view(const concat_view& other) = default;
3501
3502 constexpr iterator begin()
3503 {
3504 iterator_variant_type current;
3505 current.template emplace<0>(etl::get<0>(_r).begin());
3506 return iterator{0, *this, current};
3507 }
3508
3509 constexpr iterator end()
3510 {
3511 iterator_variant_type current;
3512 current.template emplace<number_of_ranges - 1>(etl::get<number_of_ranges - 1>(_r).end());
3513 return iterator{number_of_ranges - 1, *this, current};
3514 }
3515
3516 constexpr size_t size() const
3517 {
3518 return get_size();
3519 }
3520
3521 private:
3522
3523 template <class... Rs>
3524 friend class concat_iterator;
3525
3526 template <size_t n = 0>
3527 constexpr size_t get_size() const
3528 {
3529 if constexpr (n < etl::tuple_size_v<decltype(_r)>)
3530 {
3531 return etl::get<n>(_r).size() + get_size<n + 1>();
3532 }
3533 else
3534 {
3535 return 0;
3536 }
3537 }
3538
3539 // helper to advance iterator index+iterator variant
3540 void advance(size_t& index, iterator_variant_type& current, difference_type n) const
3541 {
3542 advance_delegates[index](index, _r, current, n);
3543 }
3544
3545 template <size_t i = 0>
3546 void set_delegates()
3547 {
3548 if constexpr (i < number_of_ranges)
3549 {
3550 advance_delegates[i] = [](size_t& index, const etl::tuple<Ranges...>& r, iterator_variant_type& current, difference_type n)
3551 {
3552 if (n > 0)
3553 {
3554 auto end = etl::get<i>(r).end();
3555 auto& it = etl::get<i>(current);
3556 if (it != end)
3557 {
3558 ++it;
3559 }
3560 if (it == end)
3561 {
3562 if constexpr (i + 1 < number_of_ranges)
3563 {
3564 current.template emplace<i + 1>(etl::get<i + 1>(r).begin());
3565 index = i + 1;
3566 }
3567 else
3568 {
3569 // at end of last range
3570 ETL_ASSERT(it == end && i + 1 == number_of_ranges, ETL_ERROR_GENERIC("Wrong iterator state at end"));
3571 }
3572 }
3573 }
3574 if (n < 0)
3575 {
3576 auto begin = etl::get<i>(r).begin();
3577 auto& it = etl::get<i>(current);
3578 if (it == begin)
3579 {
3580 if constexpr (i > 0)
3581 {
3582 current.template emplace<i - 1>(etl::get<i - 1>(r).end());
3583 index = i - 1;
3584
3585 auto begin2 = etl::get<i - 1>(r).begin();
3586 auto& it2 = etl::get<i - 1>(current);
3587 if (it2 != begin2)
3588 {
3589 --it2;
3590 }
3591 }
3592 else
3593 {
3594 // at beginning of first range
3595 ETL_ASSERT(it == begin && i == 0, ETL_ERROR_GENERIC("Wrong iterator state at begin"));
3596 }
3597 }
3598 else
3599 {
3600 it--;
3601 }
3602 }
3603 };
3604
3605 get_value_delegates[i] = [](const iterator_variant_type& current) -> reference
3606 {
3607 return *etl::get<i>(current);
3608 };
3609
3610 set_delegates<i + 1>();
3611 }
3612 }
3613
3614 reference get_value(size_t index, const iterator_variant_type& current) const
3615 {
3616 return get_value_delegates[index](current);
3617 }
3618
3619 etl::tuple<Ranges...> _r;
3620 get_value_delegates_type get_value_delegates[number_of_ranges];
3621 advance_delegates_type advance_delegates[number_of_ranges];
3622 };
3623
3624 template <class... Ranges>
3625 concat_view(Ranges&&...) -> concat_view<views::all_t<Ranges>...>;
3626
3627 struct concat_range_adapter_closure : public range_adapter_closure<concat_range_adapter_closure>
3628 {
3629 template <typename... Ranges>
3630 using target_view_type = concat_view<Ranges...>;
3631
3632 constexpr concat_range_adapter_closure() = default;
3633
3634 template <typename... Ranges>
3635 constexpr auto operator()(Ranges&&... r) const
3636 {
3637 return concat_view(views::all(etl::forward<Ranges>(r))...);
3638 }
3639 };
3640
3641 namespace views
3642 {
3643 namespace private_views
3644 {
3645 struct concat
3646 {
3647 template <class... Ranges>
3648 constexpr auto operator()(Ranges&&... r) const
3649 {
3650 return concat_view(views::all(etl::forward<Ranges>(r))...);
3651 }
3652 };
3653 } // namespace private_views
3654
3655 inline constexpr private_views::concat concat;
3656 } // namespace views
3657
3658 //*************************************************************************
3662 //*************************************************************************
3663 template <class... Ranges>
3664 class zip_iterator
3665 {
3666 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3667
3668 public:
3669
3670 using iterators_type = etl::tuple< typename etl::ranges::private_ranges::iterator_trait< Ranges>::const_iterator...>;
3671 using value_type = etl::tuple<typename etl::ranges::private_ranges::iterator_trait< Ranges>::value_type...>;
3672 using difference_type = ptrdiff_t;
3673 using pointer = const value_type*;
3674 using reference = value_type;
3675
3676 using iterator_category = ETL_OR_STD::forward_iterator_tag;
3677
3678 constexpr zip_iterator(iterators_type iters)
3679 : _iters(iters)
3680 {
3681 }
3682
3683 constexpr zip_iterator(const zip_iterator& other) = default;
3684
3685 constexpr zip_iterator& operator=(const zip_iterator& other) = default;
3686
3687 constexpr zip_iterator& operator++()
3688 {
3689 increment(etl::make_index_sequence<sizeof...(Ranges)>{});
3690 return *this;
3691 }
3692
3693 constexpr zip_iterator operator++(int)
3694 {
3695 zip_iterator tmp = *this;
3696 ++(*this);
3697 return tmp;
3698 }
3699
3700 constexpr value_type operator*() const
3701 {
3702 return deref(etl::make_index_sequence<sizeof...(Ranges)>{});
3703 }
3704
3705 friend constexpr bool operator==(const zip_iterator& lhs, const zip_iterator& rhs)
3706 {
3707 return lhs.any_equal(rhs, etl::make_index_sequence<sizeof...(Ranges)>{});
3708 }
3709
3710 friend constexpr bool operator!=(const zip_iterator& lhs, const zip_iterator& rhs)
3711 {
3712 return !(lhs == rhs);
3713 }
3714
3715 private:
3716
3717 template <size_t... Is>
3718 constexpr void increment(etl::index_sequence<Is...>)
3719 {
3720 ((++etl::get<Is>(_iters)), ...);
3721 }
3722
3723 template <size_t... Is>
3724 constexpr value_type deref(etl::index_sequence<Is...>) const
3725 {
3726 return value_type(*etl::get<Is>(_iters)...);
3727 }
3728
3729 // zip terminates when ANY iterator reaches its end (shortest range
3730 // semantics)
3731 template <size_t... Is>
3732 constexpr bool any_equal(const zip_iterator& other, etl::index_sequence<Is...>) const
3733 {
3734 return ((etl::get<Is>(_iters) == etl::get<Is>(other._iters)) || ...);
3735 }
3736
3737 iterators_type _iters;
3738 };
3739
3740 //*************************************************************************
3745 //*************************************************************************
3746 template <class... Ranges>
3747 class zip_view : public etl::ranges::view_interface<zip_view<Ranges...>>
3748 {
3749 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3750
3751 public:
3752
3753 using iterator = zip_iterator<Ranges...>;
3754 using const_iterator = zip_iterator<Ranges...>;
3755
3756 constexpr zip_view(Ranges&&... r)
3757 : _r{etl::move(r)...}
3758 {
3759 }
3760
3761 zip_view(const zip_view& other) = default;
3762
3763 constexpr const_iterator begin() const
3764 {
3765 return make_begin(etl::make_index_sequence<sizeof...(Ranges)>{});
3766 }
3767
3768 constexpr const_iterator end() const
3769 {
3770 return make_end(etl::make_index_sequence<sizeof...(Ranges)>{});
3771 }
3772
3773 constexpr size_t size() const
3774 {
3775 return get_min_size(etl::make_index_sequence<sizeof...(Ranges)>{});
3776 }
3777
3778 private:
3779
3780 template <size_t... Is>
3781 constexpr const_iterator make_begin(etl::index_sequence<Is...>) const
3782 {
3783 return const_iterator(typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...));
3784 }
3785
3786 template <size_t... Is>
3787 constexpr const_iterator make_end(etl::index_sequence<Is...>) const
3788 {
3789 return const_iterator(typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...));
3790 }
3791
3792 template <size_t... Is>
3793 constexpr size_t get_min_size(etl::index_sequence<Is...>) const
3794 {
3795 size_t sizes[] = {static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(etl::get<Is>(_r)), ETL_OR_STD::cend(etl::get<Is>(_r))))...};
3796 size_t min_val = sizes[0];
3797 for (size_t i = 1; i < sizeof...(Ranges); ++i)
3798 {
3799 if (sizes[i] < min_val)
3800 {
3801 min_val = sizes[i];
3802 }
3803 }
3804 return min_val;
3805 }
3806
3807 mutable etl::tuple<Ranges...> _r;
3808 };
3809
3810 template <class... Ranges>
3811 zip_view(Ranges&&...) -> zip_view<views::all_t<Ranges>...>;
3812
3813 namespace views
3814 {
3815 namespace private_views
3816 {
3817 struct zip
3818 {
3819 template <class... Ranges>
3820 constexpr auto operator()(Ranges&&... r) const
3821 {
3822 return zip_view(views::all(etl::forward<Ranges>(r))...);
3823 }
3824 };
3825 } // namespace private_views
3826
3827 inline constexpr private_views::zip zip;
3828 } // namespace views
3829
3830 //*************************************************************************
3834 //*************************************************************************
3835 template <class Fun, class... Ranges>
3836 class zip_transform_iterator
3837 {
3838 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3839
3840 public:
3841
3842 using iterators_type = etl::tuple< typename etl::ranges::private_ranges::iterator_trait< Ranges>::const_iterator...>;
3843 using value_type = etl::invoke_result_t< Fun, typename etl::ranges::private_ranges::iterator_trait<Ranges>::value_type...>;
3844 using difference_type = ptrdiff_t;
3845 using pointer = const value_type*;
3846 using reference = value_type;
3847
3848 using iterator_category = ETL_OR_STD::forward_iterator_tag;
3849
3850 constexpr zip_transform_iterator(Fun f, iterators_type iters)
3851 : _f(f)
3852 , _iters(iters)
3853 {
3854 }
3855
3856 constexpr zip_transform_iterator(const zip_transform_iterator& other) = default;
3857
3858 constexpr zip_transform_iterator& operator=(const zip_transform_iterator& other) = default;
3859
3860 constexpr zip_transform_iterator& operator++()
3861 {
3862 increment(etl::make_index_sequence<sizeof...(Ranges)>{});
3863 return *this;
3864 }
3865
3866 constexpr zip_transform_iterator operator++(int)
3867 {
3868 zip_transform_iterator tmp = *this;
3869 ++(*this);
3870 return tmp;
3871 }
3872
3873 constexpr value_type operator*() const
3874 {
3875 return deref(etl::make_index_sequence<sizeof...(Ranges)>{});
3876 }
3877
3878 friend constexpr bool operator==(const zip_transform_iterator& lhs, const zip_transform_iterator& rhs)
3879 {
3880 return lhs.any_equal(rhs, etl::make_index_sequence<sizeof...(Ranges)>{});
3881 }
3882
3883 friend constexpr bool operator!=(const zip_transform_iterator& lhs, const zip_transform_iterator& rhs)
3884 {
3885 return !(lhs == rhs);
3886 }
3887
3888 private:
3889
3890 template <size_t... Is>
3891 constexpr void increment(etl::index_sequence<Is...>)
3892 {
3893 ((++etl::get<Is>(_iters)), ...);
3894 }
3895
3896 template <size_t... Is>
3897 constexpr value_type deref(etl::index_sequence<Is...>) const
3898 {
3899 return etl::invoke(_f, *etl::get<Is>(_iters)...);
3900 }
3901
3902 // zip terminates when ANY iterator reaches its end (shortest range
3903 // semantics)
3904 template <size_t... Is>
3905 constexpr bool any_equal(const zip_transform_iterator& other, etl::index_sequence<Is...>) const
3906 {
3907 return ((etl::get<Is>(_iters) == etl::get<Is>(other._iters)) || ...);
3908 }
3909
3910 Fun _f;
3911 iterators_type _iters;
3912 };
3913
3914 //*************************************************************************
3920 //*************************************************************************
3921 template <class Fun, class... Ranges>
3922 class zip_transform_view : public etl::ranges::view_interface<zip_transform_view<Fun, Ranges...>>
3923 {
3924 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3925
3926 public:
3927
3928 using iterator = zip_transform_iterator<Fun, Ranges...>;
3929 using const_iterator = zip_transform_iterator<Fun, Ranges...>;
3930
3931 constexpr zip_transform_view(Fun f, Ranges&&... r)
3932 : _f{f}
3933 , _r{etl::move(r)...}
3934 {
3935 }
3936
3937 zip_transform_view(const zip_transform_view& other) = default;
3938
3939 constexpr const_iterator begin() const
3940 {
3941 return make_begin(etl::make_index_sequence<sizeof...(Ranges)>{});
3942 }
3943
3944 constexpr const_iterator end() const
3945 {
3946 return make_end(etl::make_index_sequence<sizeof...(Ranges)>{});
3947 }
3948
3949 constexpr size_t size() const
3950 {
3951 return get_min_size(etl::make_index_sequence<sizeof...(Ranges)>{});
3952 }
3953
3954 private:
3955
3956 template <size_t... Is>
3957 constexpr const_iterator make_begin(etl::index_sequence<Is...>) const
3958 {
3959 return const_iterator(_f, typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...));
3960 }
3961
3962 template <size_t... Is>
3963 constexpr const_iterator make_end(etl::index_sequence<Is...>) const
3964 {
3965 return const_iterator(_f, typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...));
3966 }
3967
3968 template <size_t... Is>
3969 constexpr size_t get_min_size(etl::index_sequence<Is...>) const
3970 {
3971 size_t sizes[] = {static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(etl::get<Is>(_r)), ETL_OR_STD::cend(etl::get<Is>(_r))))...};
3972 size_t min_val = sizes[0];
3973 for (size_t i = 1; i < sizeof...(Ranges); ++i)
3974 {
3975 if (sizes[i] < min_val)
3976 {
3977 min_val = sizes[i];
3978 }
3979 }
3980 return min_val;
3981 }
3982
3983 Fun _f;
3984 mutable etl::tuple<Ranges...> _r;
3985 };
3986
3987 template <class Fun, class... Ranges>
3988 zip_transform_view(Fun, Ranges&&...) -> zip_transform_view<Fun, views::all_t<Ranges>...>;
3989
3990 namespace views
3991 {
3992 namespace private_views
3993 {
3994 struct zip_transform
3995 {
3996 template <class Fun, class... Ranges>
3997 constexpr auto operator()(Fun&& f, Ranges&&... r) const
3998 {
3999 return zip_transform_view(etl::forward<Fun>(f), views::all(etl::forward<Ranges>(r))...);
4000 }
4001 };
4002 } // namespace private_views
4003
4004 inline constexpr private_views::zip_transform zip_transform;
4005 } // namespace views
4006
4007 //*************************************************************************
4011 //*************************************************************************
4012 template <class I, class S>
4013 class common_iterator
4014 {
4015 public:
4016
4017 using value_type = typename etl::iterator_traits<I>::value_type;
4018 using difference_type = typename etl::iterator_traits<I>::difference_type;
4019 using pointer = typename etl::iterator_traits<I>::pointer;
4020 using reference = typename etl::iterator_traits<I>::reference;
4021 using iterator_category = ETL_OR_STD::input_iterator_tag;
4022
4023 constexpr common_iterator()
4024 : _is_sentinel{false}
4025 , _it{}
4026 , _sentinel{}
4027 {
4028 }
4029
4030 constexpr common_iterator(I it)
4031 : _is_sentinel{false}
4032 , _it{it}
4033 , _sentinel{}
4034 {
4035 }
4036
4037 constexpr common_iterator(S s)
4038 : _is_sentinel{true}
4039 , _it{}
4040 , _sentinel{s}
4041 {
4042 }
4043
4044 constexpr common_iterator(const common_iterator& other)
4045 : _is_sentinel{other._is_sentinel}
4046 , _it{other._it}
4047 , _sentinel{other._sentinel}
4048 {
4049 }
4050
4051 constexpr common_iterator& operator=(const common_iterator& other)
4052 {
4053 _is_sentinel = other._is_sentinel;
4054 _it = other._it;
4055 _sentinel = other._sentinel;
4056 return *this;
4057 }
4058
4059 constexpr decltype(auto) operator*() const
4060 {
4061 return *_it;
4062 }
4063
4064 constexpr decltype(auto) operator*()
4065 {
4066 return *_it;
4067 }
4068
4069 constexpr auto operator->() const
4070 {
4071 return &(*_it);
4072 }
4073
4074 constexpr common_iterator& operator++()
4075 {
4076 ++_it;
4077 return *this;
4078 }
4079
4080 constexpr common_iterator operator++(int)
4081 {
4082 common_iterator tmp = *this;
4083 ++_it;
4084 return tmp;
4085 }
4086
4087 friend constexpr bool operator==(const common_iterator& lhs, const common_iterator& rhs)
4088 {
4089 if (lhs._is_sentinel && rhs._is_sentinel)
4090 {
4091 return true;
4092 }
4093 if (!lhs._is_sentinel && !rhs._is_sentinel)
4094 {
4095 return lhs._it == rhs._it;
4096 }
4097 if (lhs._is_sentinel)
4098 {
4099 return rhs._it == lhs._sentinel;
4100 }
4101 return lhs._it == rhs._sentinel;
4102 }
4103
4104 friend constexpr bool operator!=(const common_iterator& lhs, const common_iterator& rhs)
4105 {
4106 return !(lhs == rhs);
4107 }
4108
4109 private:
4110
4111 bool _is_sentinel;
4112 I _it;
4113 S _sentinel;
4114 };
4115
4116 //*************************************************************************
4119 //*************************************************************************
4120 namespace private_ranges
4121 {
4122 template <typename Range, typename = void>
4123 struct is_common_range : etl::false_type
4124 {
4125 };
4126
4127 template <typename Range>
4128 struct is_common_range<
4129 Range,
4130 etl::enable_if_t< etl::is_same_v< decltype(ETL_OR_STD::begin(etl::declval<Range&>())), decltype(ETL_OR_STD::end(etl::declval<Range&>())) > >>
4131 : etl::true_type
4132 {
4133 };
4134 } // namespace private_ranges
4135
4136 //*************************************************************************
4141 //*************************************************************************
4142 template <class Range, bool IsCommon = private_ranges::is_common_range<Range>::value>
4143 class common_view;
4144
4145 // Specialization for ranges that are already common (begin/end same type)
4146 template <class Range>
4147 class common_view<Range, true> : public etl::ranges::view_interface<common_view<Range, true>>
4148 {
4149 public:
4150
4151 using iterator = decltype(ETL_OR_STD::begin(etl::declval<Range&>()));
4152 using const_iterator = decltype(ETL_OR_STD::cbegin(etl::declval<const Range&>()));
4153 using difference_type = typename etl::iterator_traits<iterator>::difference_type;
4154
4155 constexpr common_view(Range&& r)
4156 : _r{etl::move(r)}
4157 {
4158 }
4159
4160 common_view(const common_view& other) = default;
4161
4162 constexpr Range base() const&
4163 {
4164 return _r;
4165 }
4166
4167 constexpr iterator begin() const
4168 {
4169 return iterator(ETL_OR_STD::begin(_r));
4170 }
4171
4172 constexpr iterator end() const
4173 {
4174 return iterator(ETL_OR_STD::end(_r));
4175 }
4176
4177 constexpr size_t size() const
4178 {
4179 return static_cast<size_t>(etl::distance(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r)));
4180 }
4181
4182 private:
4183
4184 Range _r;
4185 };
4186
4187 // Specialization for ranges that are NOT common (begin/end differ)
4188 template <class Range>
4189 class common_view<Range, false> : public etl::ranges::view_interface<common_view<Range, false>>
4190 {
4191 public:
4192
4193 using base_iterator = decltype(ETL_OR_STD::begin(etl::declval<Range&>()));
4194 using base_sentinel = decltype(ETL_OR_STD::end(etl::declval<Range&>()));
4195 using iterator = common_iterator<base_iterator, base_sentinel>;
4196 using const_iterator = iterator;
4197 using difference_type = typename etl::iterator_traits<base_iterator>::difference_type;
4198
4199 constexpr common_view(Range&& r)
4200 : _r{etl::move(r)}
4201 {
4202 }
4203
4204 common_view(const common_view& other) = default;
4205
4206 constexpr Range base() const&
4207 {
4208 return _r;
4209 }
4210
4211 constexpr iterator begin() const
4212 {
4213 return iterator(ETL_OR_STD::begin(_r));
4214 }
4215
4216 constexpr iterator end() const
4217 {
4218 return iterator(ETL_OR_STD::end(_r));
4219 }
4220
4221 private:
4222
4223 Range _r;
4224 };
4225
4226 template <class Range>
4227 common_view(Range&&) -> common_view<views::all_t<Range>>;
4228
4229 struct common_range_adapter_closure : public range_adapter_closure<common_range_adapter_closure>
4230 {
4231 template <typename Range>
4232 using target_view_type = common_view<Range>;
4233
4234 common_range_adapter_closure() = default;
4235
4236 template <typename Range>
4237 constexpr auto operator()(Range&& r)
4238 {
4239 return common_view(views::all(etl::forward<Range>(r)));
4240 }
4241 };
4242
4243 namespace views
4244 {
4245 namespace private_views
4246 {
4247 struct common
4248 {
4249 template <class Range>
4250 constexpr auto operator()(Range&& r) const
4251 {
4252 return common_view(views::all(etl::forward<Range>(r)));
4253 }
4254
4255 constexpr auto operator()() const
4256 {
4257 return ranges::common_range_adapter_closure();
4258 }
4259 };
4260 } // namespace private_views
4261
4262 inline constexpr private_views::common common;
4263 } // namespace views
4264
4265 //*************************************************************************
4269 //*************************************************************************
4270 template <class Range>
4271 class enumerate_iterator
4272 {
4273 public:
4274
4275 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
4276
4277 using base_iterator = typename trait::const_iterator;
4278 using base_value_type = typename trait::value_type;
4279 using value_type = etl::tuple<size_t, base_value_type>;
4280 using difference_type = typename trait::difference_type;
4281 using pointer = const value_type*;
4282 using reference = value_type;
4283
4284 using iterator_category = ETL_OR_STD::forward_iterator_tag;
4285
4286 enumerate_iterator(base_iterator it, size_t index)
4287 : _it(it)
4288 , _index(index)
4289 {
4290 }
4291
4292 enumerate_iterator(const enumerate_iterator& other)
4293 : _it{other._it}
4294 , _index{other._index}
4295 {
4296 }
4297
4298 enumerate_iterator& operator++()
4299 {
4300 ++_it;
4301 ++_index;
4302 return *this;
4303 }
4304
4305 enumerate_iterator operator++(int)
4306 {
4307 enumerate_iterator tmp = *this;
4308 ++_it;
4309 ++_index;
4310 return tmp;
4311 }
4312
4313 enumerate_iterator& operator=(const enumerate_iterator& other)
4314 {
4315 _it = other._it;
4316 _index = other._index;
4317 return *this;
4318 }
4319
4320 value_type operator*() const
4321 {
4322 return value_type(_index, *_it);
4323 }
4324
4325 bool operator==(const enumerate_iterator& other) const
4326 {
4327 return other._it == _it;
4328 }
4329
4330 bool operator!=(const enumerate_iterator& other) const
4331 {
4332 return !(*this == other);
4333 }
4334
4335 private:
4336
4337 base_iterator _it;
4338 size_t _index;
4339 };
4340
4341 //*************************************************************************
4345 //*************************************************************************
4346 template <class Range>
4347 class enumerate_view : public etl::ranges::view_interface<enumerate_view<Range>>
4348 {
4349 public:
4350
4351 using iterator = enumerate_iterator<Range>;
4352 using const_iterator = enumerate_iterator<Range>;
4353
4354 enumerate_view(Range&& r)
4355 : _r{etl::move(r)}
4356 {
4357 }
4358
4359 enumerate_view(const enumerate_view& other) = default;
4360
4361 constexpr Range& base() const&
4362 {
4363 return _r;
4364 }
4365
4366 constexpr const_iterator begin() const
4367 {
4368 return const_iterator(ETL_OR_STD::begin(_r), 0);
4369 }
4370
4371 constexpr const_iterator end() const
4372 {
4373 return const_iterator(ETL_OR_STD::end(_r), static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r))));
4374 }
4375
4376 constexpr size_t size() const
4377 {
4378 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
4379 }
4380
4381 private:
4382
4383 mutable Range _r;
4384 };
4385
4386 template <class Range>
4387 enumerate_view(Range&&) -> enumerate_view<views::all_t<Range>>;
4388
4389 struct enumerate_range_adapter_closure : public range_adapter_closure<enumerate_range_adapter_closure>
4390 {
4391 template <typename Range>
4392 using target_view_type = enumerate_view<Range>;
4393
4394 enumerate_range_adapter_closure() = default;
4395
4396 template <typename Range>
4397 constexpr auto operator()(Range&& r)
4398 {
4399 return enumerate_view(views::all(etl::forward<Range>(r)));
4400 }
4401 };
4402
4403 namespace views
4404 {
4405 namespace private_views
4406 {
4407 struct enumerate
4408 {
4409 template <class Range>
4410 constexpr auto operator()(Range&& r) const
4411 {
4412 return enumerate_view(views::all(etl::forward<Range>(r)));
4413 }
4414
4415 constexpr auto operator()() const
4416 {
4417 return ranges::enumerate_range_adapter_closure();
4418 }
4419 };
4420 } // namespace private_views
4421
4422 inline constexpr private_views::enumerate enumerate;
4423 } // namespace views
4424
4425 //*************************************************************************
4429 //*************************************************************************
4430 template <class Range, size_t N>
4431 class elements_iterator
4432 {
4433 public:
4434
4435 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
4436
4437 using base_iterator = typename trait::const_iterator;
4438 using base_value_type = typename trait::value_type;
4439 using value_type = etl::tuple_element_t<N, base_value_type>;
4440 using difference_type = typename trait::difference_type;
4441 using pointer = const value_type*;
4442 using reference = const value_type&;
4443
4444 using iterator_category = ETL_OR_STD::forward_iterator_tag;
4445
4446 elements_iterator(base_iterator it)
4447 : _it(it)
4448 {
4449 }
4450
4451 elements_iterator(const elements_iterator& other)
4452 : _it{other._it}
4453 {
4454 }
4455
4456 elements_iterator& operator++()
4457 {
4458 ++_it;
4459 return *this;
4460 }
4461
4462 elements_iterator operator++(int)
4463 {
4464 elements_iterator tmp = *this;
4465 _it++;
4466 return tmp;
4467 }
4468
4469 elements_iterator& operator=(const elements_iterator& other)
4470 {
4471 _it = other._it;
4472 return *this;
4473 }
4474
4475 decltype(auto) operator*() const
4476 {
4477 using etl::get;
4478 return get<N>(*_it);
4479 }
4480
4481 bool operator==(const elements_iterator& other) const
4482 {
4483 return other._it == _it;
4484 }
4485
4486 bool operator!=(const elements_iterator& other) const
4487 {
4488 return !(*this == other);
4489 }
4490
4491 private:
4492
4493 base_iterator _it;
4494 };
4495
4496 //*************************************************************************
4500 //*************************************************************************
4501 template <class Range, size_t N>
4502 class elements_view : public etl::ranges::view_interface<elements_view<Range, N>>
4503 {
4504 public:
4505
4506 using iterator = elements_iterator<Range, N>;
4507 using const_iterator = elements_iterator<Range, N>;
4508
4509 elements_view(Range&& r)
4510 : _r{etl::move(r)}
4511 {
4512 }
4513
4514 elements_view(const elements_view& other) = default;
4515
4516 constexpr Range& base() const&
4517 {
4518 return _r;
4519 }
4520
4521 constexpr const_iterator begin() const
4522 {
4523 return const_iterator(ETL_OR_STD::begin(_r));
4524 }
4525
4526 constexpr const_iterator end() const
4527 {
4528 return const_iterator(ETL_OR_STD::end(_r));
4529 }
4530
4531 constexpr size_t size() const
4532 {
4533 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
4534 }
4535
4536 private:
4537
4538 mutable Range _r;
4539 };
4540
4541 template <class Range, size_t N>
4542 elements_view(Range&&, etl::integral_constant<size_t, N>) -> elements_view<views::all_t<Range>, N>;
4543
4544 template <size_t N>
4545 struct elements_range_adapter_closure : public range_adapter_closure<elements_range_adapter_closure<N>>
4546 {
4547 template <typename Range>
4548 using target_view_type = elements_view<Range, N>;
4549
4550 elements_range_adapter_closure() = default;
4551
4552 template <typename Range>
4553 constexpr auto operator()(Range&& r)
4554 {
4555 return elements_view<views::all_t<Range>, N>(views::all(etl::forward<Range>(r)));
4556 }
4557 };
4558
4560 template <class Range>
4561 using keys_view = elements_view<Range, 0>;
4562
4564 template <class Range>
4565 using values_view = elements_view<Range, 1>;
4566
4567 namespace views
4568 {
4569 namespace private_views
4570 {
4571 template <size_t N>
4572 struct elements_fn
4573 {
4574 template <class Range>
4575 constexpr auto operator()(Range&& r) const
4576 {
4577 return elements_view<views::all_t<Range>, N>(views::all(etl::forward<Range>(r)));
4578 }
4579
4580 constexpr auto operator()() const
4581 {
4582 return ranges::elements_range_adapter_closure<N>();
4583 }
4584 };
4585 } // namespace private_views
4586
4587 template <size_t N>
4588 inline constexpr private_views::elements_fn<N> elements{};
4589
4590 inline constexpr private_views::elements_fn<0> keys{};
4591 inline constexpr private_views::elements_fn<1> values{};
4592 } // namespace views
4593
4594 //*************************************************************************
4596 //*************************************************************************
4597 namespace private_ranges
4598 {
4599 template <typename T, size_t N, typename = etl::make_index_sequence<N>>
4600 struct repeat_tuple;
4601
4602 template <typename T, size_t N, size_t... Is>
4603 struct repeat_tuple<T, N, etl::index_sequence<Is...>>
4604 {
4605 template <size_t>
4606 using always = T;
4607
4608 using type = etl::tuple<always<Is>...>;
4609 };
4610
4611 template <typename T, size_t N>
4612 using repeat_tuple_t = typename repeat_tuple<T, N>::type;
4613
4616 template <typename Fun, typename T, size_t N, typename = etl::make_index_sequence<N>>
4617 struct repeat_invoke_result;
4618
4619 template <typename Fun, typename T, size_t N, size_t... Is>
4620 struct repeat_invoke_result<Fun, T, N, etl::index_sequence<Is...>>
4621 {
4622 template <size_t>
4623 using always = T;
4624
4625 using type = etl::invoke_result_t<Fun, always<Is>...>;
4626 };
4627
4628 template <typename Fun, typename T, size_t N>
4629 using repeat_invoke_result_t = typename repeat_invoke_result<Fun, T, N>::type;
4630 } // namespace private_ranges
4631
4632 //*************************************************************************
4637 //*************************************************************************
4638 template <class Range, size_t N>
4639 class adjacent_iterator
4640 {
4641 static_assert(N > 0, "adjacent window size must be > 0");
4642
4643 public:
4644
4645 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
4646
4647 using base_iterator = typename trait::const_iterator;
4648 using base_value_type = typename trait::value_type;
4649 using value_type = private_ranges::repeat_tuple_t<base_value_type, N>;
4650 using difference_type = typename trait::difference_type;
4651 using pointer = const value_type*;
4652 using reference = value_type;
4653
4654 using iterator_category = ETL_OR_STD::forward_iterator_tag;
4655
4657 template <size_t... Is>
4658 constexpr adjacent_iterator(base_iterator first, base_iterator last, etl::index_sequence<Is...>)
4659 : _iters{advance_copy(first, last, Is)...}
4660 , _end{last}
4661 {
4662 }
4663
4664 constexpr adjacent_iterator(const adjacent_iterator& other) = default;
4665
4666 constexpr adjacent_iterator& operator=(const adjacent_iterator& other) = default;
4667
4668 constexpr adjacent_iterator& operator++()
4669 {
4670 increment(etl::make_index_sequence<N>{});
4671 return *this;
4672 }
4673
4674 constexpr adjacent_iterator operator++(int)
4675 {
4676 adjacent_iterator tmp = *this;
4677 ++(*this);
4678 return tmp;
4679 }
4680
4681 constexpr value_type operator*() const
4682 {
4683 return deref(etl::make_index_sequence<N>{});
4684 }
4685
4686 friend constexpr bool operator==(const adjacent_iterator& lhs, const adjacent_iterator& rhs)
4687 {
4688 // Compare the last iterator in the window (index N-1).
4689 // When it reaches end, the window is exhausted.
4690 return lhs._iters[N - 1] == rhs._iters[N - 1];
4691 }
4692
4693 friend constexpr bool operator!=(const adjacent_iterator& lhs, const adjacent_iterator& rhs)
4694 {
4695 return !(lhs == rhs);
4696 }
4697
4698 private:
4699
4700 static constexpr base_iterator advance_copy(base_iterator it, base_iterator last, size_t n)
4701 {
4702 for (size_t i = 0; i < n && it != last; ++i)
4703 {
4704 ++it;
4705 }
4706 return it;
4707 }
4708
4709 template <size_t... Is>
4710 constexpr void increment(etl::index_sequence<Is...>)
4711 {
4712 ((void)((_iters[Is] != _end) ? (void)++_iters[Is] : (void)0), ...);
4713 }
4714
4715 template <size_t... Is>
4716 constexpr value_type deref(etl::index_sequence<Is...>) const
4717 {
4718 return value_type(*_iters[Is]...);
4719 }
4720
4721 base_iterator _iters[N];
4722 base_iterator _end;
4723 };
4724
4725 //*************************************************************************
4732 //*************************************************************************
4733 template <class Range, size_t N>
4734 class adjacent_view : public etl::ranges::view_interface<adjacent_view<Range, N>>
4735 {
4736 static_assert(N > 0, "adjacent window size must be > 0");
4737
4738 public:
4739
4740 using iterator = adjacent_iterator<Range, N>;
4741 using const_iterator = adjacent_iterator<Range, N>;
4742
4743 constexpr adjacent_view(Range&& r)
4744 : _r{etl::move(r)}
4745 {
4746 }
4747
4748 adjacent_view(const adjacent_view& other) = default;
4749
4750 constexpr Range& base() const&
4751 {
4752 return _r;
4753 }
4754
4755 constexpr const_iterator begin() const
4756 {
4757 return const_iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), etl::make_index_sequence<N>{});
4758 }
4759
4760 constexpr const_iterator end() const
4761 {
4762 // The end iterator has all N internal iterators at the end position.
4763 return const_iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), etl::make_index_sequence<N>{});
4764 }
4765
4766 constexpr size_t size() const
4767 {
4768 auto total = static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
4769 return (total >= N) ? (total - N + 1) : 0;
4770 }
4771
4772 private:
4773
4774 mutable Range _r;
4775 };
4776
4777 template <class Range, size_t N>
4778 adjacent_view(Range&&, etl::integral_constant<size_t, N>) -> adjacent_view<views::all_t<Range>, N>;
4779
4780 template <size_t N>
4781 struct adjacent_range_adapter_closure : public range_adapter_closure<adjacent_range_adapter_closure<N>>
4782 {
4783 template <typename Range>
4784 using target_view_type = adjacent_view<Range, N>;
4785
4786 adjacent_range_adapter_closure() = default;
4787
4788 template <typename Range>
4789 constexpr auto operator()(Range&& r)
4790 {
4791 return adjacent_view<views::all_t<Range>, N>(views::all(etl::forward<Range>(r)));
4792 }
4793 };
4794
4795 namespace views
4796 {
4797 namespace private_views
4798 {
4799 template <size_t N>
4800 struct adjacent_fn
4801 {
4802 template <class Range>
4803 constexpr auto operator()(Range&& r) const
4804 {
4805 return adjacent_view<views::all_t<Range>, N>(views::all(etl::forward<Range>(r)));
4806 }
4807
4808 constexpr auto operator()() const
4809 {
4810 return ranges::adjacent_range_adapter_closure<N>();
4811 }
4812 };
4813 } // namespace private_views
4814
4815 template <size_t N>
4816 inline constexpr private_views::adjacent_fn<N> adjacent{};
4817
4819 inline constexpr private_views::adjacent_fn<2> pairwise{};
4820 } // namespace views
4821
4822 //*************************************************************************
4827 //*************************************************************************
4828 template <class Range, class Fun, size_t N>
4829 class adjacent_transform_iterator
4830 {
4831 static_assert(N > 0, "adjacent window size must be > 0");
4832
4833 public:
4834
4835 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
4836
4837 using base_iterator = typename trait::const_iterator;
4838 using base_value_type = typename trait::value_type;
4839 using value_type = private_ranges::repeat_invoke_result_t<Fun, base_value_type, N>;
4840 using difference_type = typename trait::difference_type;
4841 using pointer = const value_type*;
4842 using reference = value_type;
4843
4844 using iterator_category = ETL_OR_STD::forward_iterator_tag;
4845
4848 template <size_t... Is>
4849 constexpr adjacent_transform_iterator(Fun f, base_iterator first, base_iterator last, etl::index_sequence<Is...>)
4850 : _f{f}
4851 , _iters{advance_copy(first, last, Is)...}
4852 , _end{last}
4853 {
4854 }
4855
4856 constexpr adjacent_transform_iterator(const adjacent_transform_iterator& other) = default;
4857
4858 constexpr adjacent_transform_iterator& operator=(const adjacent_transform_iterator& other) = default;
4859
4860 constexpr adjacent_transform_iterator& operator++()
4861 {
4862 increment(etl::make_index_sequence<N>{});
4863 return *this;
4864 }
4865
4866 constexpr adjacent_transform_iterator operator++(int)
4867 {
4868 adjacent_transform_iterator tmp = *this;
4869 ++(*this);
4870 return tmp;
4871 }
4872
4873 constexpr value_type operator*() const
4874 {
4875 return deref(etl::make_index_sequence<N>{});
4876 }
4877
4878 friend constexpr bool operator==(const adjacent_transform_iterator& lhs, const adjacent_transform_iterator& rhs)
4879 {
4880 // Compare the last iterator in the window (index N-1).
4881 // When it reaches end, the window is exhausted.
4882 return lhs._iters[N - 1] == rhs._iters[N - 1];
4883 }
4884
4885 friend constexpr bool operator!=(const adjacent_transform_iterator& lhs, const adjacent_transform_iterator& rhs)
4886 {
4887 return !(lhs == rhs);
4888 }
4889
4890 private:
4891
4892 static constexpr base_iterator advance_copy(base_iterator it, base_iterator last, size_t n)
4893 {
4894 for (size_t i = 0; i < n && it != last; ++i)
4895 {
4896 ++it;
4897 }
4898 return it;
4899 }
4900
4901 template <size_t... Is>
4902 constexpr void increment(etl::index_sequence<Is...>)
4903 {
4904 ((void)((_iters[Is] != _end) ? (void)++_iters[Is] : (void)0), ...);
4905 }
4906
4907 template <size_t... Is>
4908 constexpr value_type deref(etl::index_sequence<Is...>) const
4909 {
4910 return etl::invoke(_f, *_iters[Is]...);
4911 }
4912
4913 Fun _f;
4914 base_iterator _iters[N];
4915 base_iterator _end;
4916 };
4917
4918 //*************************************************************************
4926 //*************************************************************************
4927 template <class Range, class Fun, size_t N>
4928 class adjacent_transform_view : public etl::ranges::view_interface< adjacent_transform_view<Range, Fun, N>>
4929 {
4930 static_assert(N > 0, "adjacent window size must be > 0");
4931
4932 public:
4933
4934 using iterator = adjacent_transform_iterator<Range, Fun, N>;
4935 using const_iterator = adjacent_transform_iterator<Range, Fun, N>;
4936
4937 constexpr adjacent_transform_view(Fun f, Range&& r)
4938 : _f{f}
4939 , _r{etl::move(r)}
4940 {
4941 }
4942
4943 adjacent_transform_view(const adjacent_transform_view& other) = default;
4944
4945 constexpr Range& base() const&
4946 {
4947 return _r;
4948 }
4949
4950 constexpr const_iterator begin() const
4951 {
4952 return const_iterator(_f, ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), etl::make_index_sequence<N>{});
4953 }
4954
4955 constexpr const_iterator end() const
4956 {
4957 // The end iterator has all N internal iterators at the end position.
4958 return const_iterator(_f, ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), etl::make_index_sequence<N>{});
4959 }
4960
4961 constexpr size_t size() const
4962 {
4963 auto total = static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
4964 return (total >= N) ? (total - N + 1) : 0;
4965 }
4966
4967 private:
4968
4969 Fun _f;
4970 mutable Range _r;
4971 };
4972
4973 template <class Fun, class Range, size_t N>
4974 adjacent_transform_view(Fun, Range&&, etl::integral_constant<size_t, N>) -> adjacent_transform_view<views::all_t<Range>, Fun, N>;
4975
4976 template <size_t N, typename Fun>
4977 struct adjacent_transform_range_adapter_closure : public range_adapter_closure< adjacent_transform_range_adapter_closure<N, Fun>>
4978 {
4979 template <typename Range>
4980 using target_view_type = adjacent_transform_view<Range, Fun, N>;
4981
4982 adjacent_transform_range_adapter_closure(Fun f)
4983 : _f{f}
4984 {
4985 }
4986
4987 template <typename Range>
4988 constexpr auto operator()(Range&& r)
4989 {
4990 return adjacent_transform_view<views::all_t<Range>, Fun, N>(_f, views::all(etl::forward<Range>(r)));
4991 }
4992
4993 Fun _f;
4994 };
4995
4996 namespace views
4997 {
4998 namespace private_views
4999 {
5000 template <size_t N>
5001 struct adjacent_transform_fn
5002 {
5003 template <class Range, typename Fun>
5004 constexpr auto operator()(Range&& r, Fun&& f) const
5005 {
5006 return adjacent_transform_view<views::all_t<Range>, etl::decay_t<Fun>, N>(etl::forward<Fun>(f), views::all(etl::forward<Range>(r)));
5007 }
5008
5009 template <typename Fun>
5010 constexpr auto operator()(Fun&& f) const
5011 {
5012 return ranges::adjacent_transform_range_adapter_closure< N, etl::decay_t<Fun>>(etl::forward<Fun>(f));
5013 }
5014 };
5015 } // namespace private_views
5016
5017 template <size_t N>
5018 inline constexpr private_views::adjacent_transform_fn<N> adjacent_transform{};
5019
5021 inline constexpr private_views::adjacent_transform_fn<2> pairwise_transform{};
5022 } // namespace views
5023
5024 //*************************************************************************
5026 //*************************************************************************
5027 template <class Range>
5028 class chunk_iterator
5029 {
5030 public:
5031
5032 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
5033
5034 using inner_iterator = typename trait::iterator;
5035 using const_inner_iterator = typename trait::const_iterator;
5036 using difference_type = typename trait::difference_type;
5037
5038 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5039
5040 using value_type = etl::ranges::subrange<const_inner_iterator>;
5041 using pointer = value_type*;
5042 using reference = value_type;
5043
5044 chunk_iterator(const_inner_iterator it, const_inner_iterator it_end, difference_type chunk_size)
5045 : _it(it)
5046 , _it_end(it_end)
5047 , _chunk_size(chunk_size)
5048 {
5049 }
5050
5051 chunk_iterator(const chunk_iterator& other) = default;
5052
5053 chunk_iterator& operator=(const chunk_iterator& other) = default;
5054
5055 chunk_iterator& operator++()
5056 {
5057 difference_type remaining = etl::distance(_it, _it_end);
5058 difference_type step = (_chunk_size < remaining) ? _chunk_size : remaining;
5059 etl::advance(_it, step);
5060 return *this;
5061 }
5062
5063 chunk_iterator operator++(int)
5064 {
5065 chunk_iterator tmp{*this};
5066 ++(*this);
5067 return tmp;
5068 }
5069
5070 value_type operator*() const
5071 {
5072 difference_type remaining = etl::distance(_it, _it_end);
5073 difference_type step = (_chunk_size < remaining) ? _chunk_size : remaining;
5074 const_inner_iterator chunk_end = _it;
5075 etl::advance(chunk_end, step);
5076 return value_type(_it, chunk_end);
5077 }
5078
5079 constexpr bool operator==(const chunk_iterator& other) const
5080 {
5081 return _it == other._it;
5082 }
5083
5084 constexpr bool operator!=(const chunk_iterator& other) const
5085 {
5086 return !(*this == other);
5087 }
5088
5089 private:
5090
5091 const_inner_iterator _it;
5092 const_inner_iterator _it_end;
5093 difference_type _chunk_size;
5094 };
5095
5096 //*************************************************************************
5100 //*************************************************************************
5101 template <class Range>
5102 class chunk_view : public etl::ranges::view_interface<chunk_view<Range>>
5103 {
5104 public:
5105
5106 using iterator = chunk_iterator<Range>;
5107 using const_iterator = chunk_iterator<Range>;
5108 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
5109
5110 constexpr chunk_view(Range&& r, difference_type chunk_size)
5111 : _r{etl::move(r)}
5112 , _chunk_size{chunk_size}
5113 {
5114 }
5115
5116 chunk_view(const chunk_view& other) = default;
5117
5118 constexpr Range base() const&
5119 {
5120 return _r;
5121 }
5122
5123 constexpr iterator begin() const
5124 {
5125 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _chunk_size);
5126 }
5127
5128 constexpr iterator end() const
5129 {
5130 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _chunk_size);
5131 }
5132
5133 private:
5134
5135 Range _r;
5136 difference_type _chunk_size;
5137 };
5138
5139 template <class Range>
5140 chunk_view(Range&&, typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type) -> chunk_view<views::all_t<Range>>;
5141
5142 struct chunk_range_adapter_closure : public range_adapter_closure<chunk_range_adapter_closure>
5143 {
5144 template <typename Range>
5145 using target_view_type = chunk_view<Range>;
5146
5147 template <class DifferenceType>
5148 constexpr chunk_range_adapter_closure(DifferenceType chunk_size)
5149 : _chunk_size{static_cast<size_t>(chunk_size)}
5150 {
5151 }
5152
5153 template <typename Range>
5154 constexpr auto operator()(Range&& r) const
5155 {
5156 return chunk_view(views::all(etl::forward<Range>(r)), static_cast< typename chunk_view<views::all_t<Range>>::difference_type>(_chunk_size));
5157 }
5158
5159 const size_t _chunk_size;
5160 };
5161
5162 namespace views
5163 {
5164 namespace private_views
5165 {
5166 struct chunk
5167 {
5168 template <class Range>
5169 constexpr auto operator()(Range&& r, ranges::range_difference_t<Range> chunk_size) const
5170 {
5171 return chunk_view(views::all(etl::forward<Range>(r)), chunk_size);
5172 }
5173
5174 template <class DifferenceType>
5175 constexpr auto operator()(DifferenceType chunk_size) const
5176 {
5177 return ranges::chunk_range_adapter_closure(chunk_size);
5178 }
5179 };
5180 } // namespace private_views
5181
5182 inline constexpr private_views::chunk chunk;
5183 } // namespace views
5184
5185 //*************************************************************************
5188 //*************************************************************************
5189 template <class Range>
5190 class slide_iterator
5191 {
5192 public:
5193
5194 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
5195
5196 using inner_iterator = typename trait::iterator;
5197 using const_inner_iterator = typename trait::const_iterator;
5198 using difference_type = typename trait::difference_type;
5199
5200 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5201
5202 using value_type = etl::ranges::subrange<const_inner_iterator>;
5203 using pointer = value_type*;
5204 using reference = value_type;
5205
5206 slide_iterator(const_inner_iterator it, const_inner_iterator it_end, difference_type window_size)
5207 : _it(it)
5208 , _it_end(it_end)
5209 , _window_size(window_size)
5210 {
5211 }
5212
5213 slide_iterator(const slide_iterator& other) = default;
5214
5215 slide_iterator& operator=(const slide_iterator& other) = default;
5216
5217 slide_iterator& operator++()
5218 {
5219 ++_it;
5220 return *this;
5221 }
5222
5223 slide_iterator operator++(int)
5224 {
5225 slide_iterator tmp{*this};
5226 ++(*this);
5227 return tmp;
5228 }
5229
5230 value_type operator*() const
5231 {
5232 const_inner_iterator window_end = _it;
5233 etl::advance(window_end, _window_size);
5234 return value_type(_it, window_end);
5235 }
5236
5237 constexpr bool operator==(const slide_iterator& other) const
5238 {
5239 return _it == other._it;
5240 }
5241
5242 constexpr bool operator!=(const slide_iterator& other) const
5243 {
5244 return !(*this == other);
5245 }
5246
5247 private:
5248
5249 const_inner_iterator _it;
5250 const_inner_iterator _it_end;
5251 difference_type _window_size;
5252 };
5253
5254 //*************************************************************************
5260 //*************************************************************************
5261 template <class Range>
5262 class slide_view : public etl::ranges::view_interface<slide_view<Range>>
5263 {
5264 public:
5265
5266 using iterator = slide_iterator<Range>;
5267 using const_iterator = slide_iterator<Range>;
5268 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
5269
5270 constexpr slide_view(Range&& r, difference_type window_size)
5271 : _r{etl::move(r)}
5272 , _window_size{window_size}
5273 {
5274 }
5275
5276 slide_view(const slide_view& other) = default;
5277
5278 constexpr Range base() const&
5279 {
5280 return _r;
5281 }
5282
5283 constexpr iterator begin() const
5284 {
5285 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _window_size);
5286 }
5287
5288 constexpr iterator end() const
5289 {
5290 auto total = static_cast<difference_type>(etl::distance(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r)));
5291 if (total < _window_size)
5292 {
5293 // Empty view: begin == end
5294 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _window_size);
5295 }
5296 auto end_it = ETL_OR_STD::begin(_r);
5297 etl::advance(end_it, total - _window_size + 1);
5298 return iterator(end_it, ETL_OR_STD::end(_r), _window_size);
5299 }
5300
5301 constexpr size_t size() const
5302 {
5303 auto total = static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
5304 return (total >= static_cast<size_t>(_window_size)) ? (total - static_cast<size_t>(_window_size) + 1) : 0;
5305 }
5306
5307 private:
5308
5309 Range _r;
5310 difference_type _window_size;
5311 };
5312
5313 template <class Range>
5314 slide_view(Range&&, typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type) -> slide_view<views::all_t<Range>>;
5315
5316 struct slide_range_adapter_closure : public range_adapter_closure<slide_range_adapter_closure>
5317 {
5318 template <typename Range>
5319 using target_view_type = slide_view<Range>;
5320
5321 template <class DifferenceType>
5322 constexpr slide_range_adapter_closure(DifferenceType window_size)
5323 : _window_size{static_cast<size_t>(window_size)}
5324 {
5325 }
5326
5327 template <typename Range>
5328 constexpr auto operator()(Range&& r) const
5329 {
5330 return slide_view(views::all(etl::forward<Range>(r)), static_cast< typename slide_view<views::all_t<Range>>::difference_type>(_window_size));
5331 }
5332
5333 const size_t _window_size;
5334 };
5335
5336 namespace views
5337 {
5338 namespace private_views
5339 {
5340 struct slide
5341 {
5342 template <class Range>
5343 constexpr auto operator()(Range&& r, ranges::range_difference_t<Range> window_size) const
5344 {
5345 return slide_view(views::all(etl::forward<Range>(r)), window_size);
5346 }
5347
5348 template <class DifferenceType>
5349 constexpr auto operator()(DifferenceType window_size) const
5350 {
5351 return ranges::slide_range_adapter_closure(window_size);
5352 }
5353 };
5354 } // namespace private_views
5355
5356 inline constexpr private_views::slide slide;
5357 } // namespace views
5358
5359 //*************************************************************************
5364 //*************************************************************************
5365 template <class Range, class Pred>
5366 class chunk_by_iterator
5367 {
5368 public:
5369
5370 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
5371
5372 using inner_iterator = typename trait::iterator;
5373 using const_inner_iterator = typename trait::const_iterator;
5374 using difference_type = typename trait::difference_type;
5375
5376 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5377
5378 using value_type = etl::ranges::subrange<const_inner_iterator>;
5379 using pointer = value_type*;
5380 using reference = value_type;
5381
5382 chunk_by_iterator(const_inner_iterator it, const_inner_iterator it_end, const Pred& pred)
5383 : _it(it)
5384 , _it_end(it_end)
5385 , _pred(pred)
5386 {
5387 _chunk_end = find_next_chunk_end();
5388 }
5389
5390 chunk_by_iterator(const chunk_by_iterator& other) = default;
5391
5392 chunk_by_iterator& operator=(const chunk_by_iterator& other) = default;
5393
5394 chunk_by_iterator& operator++()
5395 {
5396 _it = _chunk_end;
5397 _chunk_end = find_next_chunk_end();
5398 return *this;
5399 }
5400
5401 chunk_by_iterator operator++(int)
5402 {
5403 chunk_by_iterator tmp{*this};
5404 ++(*this);
5405 return tmp;
5406 }
5407
5408 value_type operator*() const
5409 {
5410 return value_type(_it, _chunk_end);
5411 }
5412
5413 constexpr bool operator==(const chunk_by_iterator& other) const
5414 {
5415 return _it == other._it;
5416 }
5417
5418 constexpr bool operator!=(const chunk_by_iterator& other) const
5419 {
5420 return !(*this == other);
5421 }
5422
5423 private:
5424
5425 const_inner_iterator find_next_chunk_end() const
5426 {
5427 if (_it == _it_end)
5428 {
5429 return _it_end;
5430 }
5431
5432 const_inner_iterator it_prev = _it;
5433 const_inner_iterator it_curr = _it;
5434 ++it_curr;
5435
5436 while (it_curr != _it_end)
5437 {
5438 if (!_pred(*it_prev, *it_curr))
5439 {
5440 return it_curr;
5441 }
5442 it_prev = it_curr;
5443 ++it_curr;
5444 }
5445
5446 return _it_end;
5447 }
5448
5449 const_inner_iterator _it;
5450 const_inner_iterator _it_end;
5451 const_inner_iterator _chunk_end;
5452 Pred _pred;
5453 };
5454
5455 //*************************************************************************
5460 //*************************************************************************
5461 template <class Range, class Pred>
5462 class chunk_by_view : public etl::ranges::view_interface<chunk_by_view<Range, Pred>>
5463 {
5464 public:
5465
5466 using iterator = chunk_by_iterator<Range, Pred>;
5467 using const_iterator = chunk_by_iterator<Range, Pred>;
5468
5469 chunk_by_view(Range&& r, const Pred& pred)
5470 : _r{etl::move(r)}
5471 , _pred{pred}
5472 {
5473 }
5474
5475 chunk_by_view(const chunk_by_view& other) = default;
5476
5477 constexpr Range base() const&
5478 {
5479 return _r;
5480 }
5481
5482 constexpr const Pred& pred() const
5483 {
5484 return _pred;
5485 }
5486
5487 constexpr const_iterator begin() const
5488 {
5489 return const_iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _pred);
5490 }
5491
5492 constexpr const_iterator end() const
5493 {
5494 return const_iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _pred);
5495 }
5496
5497 private:
5498
5499 Range _r;
5500 const Pred _pred;
5501 };
5502
5503 template <class Range, typename Pred>
5504 chunk_by_view(Range&&, Pred) -> chunk_by_view<views::all_t<Range>, Pred>;
5505
5506 template <typename Pred>
5507 struct chunk_by_range_adapter_closure : public range_adapter_closure<chunk_by_range_adapter_closure<Pred>>
5508 {
5509 template <typename Range>
5510 using target_view_type = chunk_by_view<Range, Pred>;
5511
5512 chunk_by_range_adapter_closure(const Pred& p)
5513 : _p{p}
5514 {
5515 }
5516
5517 template <typename Range>
5518 constexpr auto operator()(Range&& r) const
5519 {
5520 return chunk_by_view(views::all(etl::forward<Range>(r)), _p);
5521 }
5522
5523 const Pred _p;
5524 };
5525
5526 namespace views
5527 {
5528 namespace private_views
5529 {
5530 struct chunk_by
5531 {
5532 template <class Range, typename Pred>
5533 constexpr auto operator()(Range&& r, const Pred& p) const
5534 {
5535 return chunk_by_view(views::all(etl::forward<Range>(r)), p);
5536 }
5537
5538 template <typename Pred>
5539 constexpr auto operator()(const Pred& p) const
5540 {
5541 return ranges::chunk_by_range_adapter_closure<Pred>(p);
5542 }
5543 };
5544 } // namespace private_views
5545
5546 inline constexpr private_views::chunk_by chunk_by;
5547 } // namespace views
5548
5549 //*************************************************************************
5552 //*************************************************************************
5553 template <class Range>
5554 class stride_iterator
5555 {
5556 public:
5557
5558 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
5559
5560 using inner_iterator = typename trait::iterator;
5561 using const_inner_iterator = typename trait::const_iterator;
5562 using difference_type = typename trait::difference_type;
5563
5564 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5565
5566 using value_type = typename trait::value_type;
5567 using pointer = typename trait::pointer;
5568 using reference = typename trait::reference;
5569
5570 constexpr stride_iterator(const_inner_iterator it, const_inner_iterator it_end, difference_type stride_n)
5571 : _it(it)
5572 , _it_end(it_end)
5573 , _stride_n(stride_n)
5574 {
5575 }
5576
5577 stride_iterator(const stride_iterator& other) = default;
5578
5579 stride_iterator& operator=(const stride_iterator& other) = default;
5580
5581 constexpr stride_iterator& operator++()
5582 {
5583 difference_type remaining = etl::distance(_it, _it_end);
5584 difference_type step = (_stride_n < remaining) ? _stride_n : remaining;
5585 etl::advance(_it, step);
5586 return *this;
5587 }
5588
5589 constexpr stride_iterator operator++(int)
5590 {
5591 stride_iterator tmp{*this};
5592 ++(*this);
5593 return tmp;
5594 }
5595
5596 constexpr auto operator*() const
5597 {
5598 return *_it;
5599 }
5600
5601 constexpr auto operator->() const
5602 {
5603 return &(*_it);
5604 }
5605
5606 constexpr bool operator==(const stride_iterator& other) const
5607 {
5608 return _it == other._it;
5609 }
5610
5611 constexpr bool operator!=(const stride_iterator& other) const
5612 {
5613 return !(*this == other);
5614 }
5615
5616 private:
5617
5618 mutable const_inner_iterator _it;
5619 const_inner_iterator _it_end;
5620 difference_type _stride_n;
5621 };
5622
5623 //*************************************************************************
5626 //*************************************************************************
5627 template <class Range>
5628 class stride_view : public etl::ranges::view_interface<stride_view<Range>>
5629 {
5630 public:
5631
5632 using iterator = stride_iterator<Range>;
5633 using const_iterator = stride_iterator<Range>;
5634 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
5635
5636 constexpr stride_view(Range&& r, difference_type stride_n)
5637 : _r{etl::move(r)}
5638 , _stride_n{stride_n}
5639 {
5640 }
5641
5642 stride_view(const stride_view& other) = default;
5643
5644 constexpr Range base() const&
5645 {
5646 return _r;
5647 }
5648
5649 constexpr iterator begin() const
5650 {
5651 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _stride_n);
5652 }
5653
5654 constexpr iterator end() const
5655 {
5656 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _stride_n);
5657 }
5658
5659 private:
5660
5661 Range _r;
5662 difference_type _stride_n;
5663 };
5664
5665 template <class Range>
5666 stride_view(Range&&, typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type) -> stride_view<views::all_t<Range>>;
5667
5668 struct stride_range_adapter_closure : public range_adapter_closure<stride_range_adapter_closure>
5669 {
5670 template <typename Range>
5671 using target_view_type = stride_view<Range>;
5672
5673 template <class DifferenceType>
5674 constexpr stride_range_adapter_closure(DifferenceType stride_n)
5675 : _stride_n{static_cast<size_t>(stride_n)}
5676 {
5677 }
5678
5679 template <typename Range>
5680 constexpr auto operator()(Range&& r) const
5681 {
5682 return stride_view(views::all(etl::forward<Range>(r)), static_cast< typename stride_view<views::all_t<Range>>::difference_type>(_stride_n));
5683 }
5684
5685 const size_t _stride_n;
5686 };
5687
5688 namespace views
5689 {
5690 namespace private_views
5691 {
5692 struct stride
5693 {
5694 template <class Range>
5695 constexpr auto operator()(Range&& r, ranges::range_difference_t<Range> stride_n) const
5696 {
5697 return stride_view(views::all(etl::forward<Range>(r)), stride_n);
5698 }
5699
5700 template <class DifferenceType>
5701 constexpr auto operator()(DifferenceType stride_n) const
5702 {
5703 return ranges::stride_range_adapter_closure(stride_n);
5704 }
5705 };
5706 } // namespace private_views
5707
5708 inline constexpr private_views::stride stride;
5709 } // namespace views
5710
5711 //*************************************************************************
5717 //*************************************************************************
5718 template <class... Ranges>
5719 class cartesian_product_iterator
5720 {
5721 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
5722
5723 public:
5724
5725 using iterators_type = etl::tuple< typename etl::ranges::private_ranges::iterator_trait< Ranges>::const_iterator...>;
5726 using value_type = etl::tuple<typename etl::ranges::private_ranges::iterator_trait< Ranges>::value_type...>;
5727 using difference_type = ptrdiff_t;
5728 using pointer = const value_type*;
5729 using reference = value_type;
5730
5731 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5732
5733 constexpr cartesian_product_iterator(iterators_type current, iterators_type begins, iterators_type ends, bool is_end = false)
5734 : _current(current)
5735 , _begins(begins)
5736 , _ends(ends)
5737 , _is_end(is_end)
5738 {
5739 }
5740
5741 constexpr cartesian_product_iterator(const cartesian_product_iterator& other) = default;
5742
5743 constexpr cartesian_product_iterator& operator=(const cartesian_product_iterator& other) = default;
5744
5745 constexpr cartesian_product_iterator& operator++()
5746 {
5747 increment();
5748 return *this;
5749 }
5750
5751 constexpr cartesian_product_iterator operator++(int)
5752 {
5753 cartesian_product_iterator tmp = *this;
5754 ++(*this);
5755 return tmp;
5756 }
5757
5758 constexpr value_type operator*() const
5759 {
5760 return deref(etl::make_index_sequence<sizeof...(Ranges)>{});
5761 }
5762
5763 friend constexpr bool operator==(const cartesian_product_iterator& lhs, const cartesian_product_iterator& rhs)
5764 {
5765 return lhs._is_end == rhs._is_end && (lhs._is_end || lhs.all_equal(rhs, etl::make_index_sequence<sizeof...(Ranges)>{}));
5766 }
5767
5768 friend constexpr bool operator!=(const cartesian_product_iterator& lhs, const cartesian_product_iterator& rhs)
5769 {
5770 return !(lhs == rhs);
5771 }
5772
5773 private:
5774
5775 // Increment with carry: increment the last range, and carry over to the
5776 // previous range when a range wraps around
5777 constexpr void increment()
5778 {
5779 if (_is_end)
5780 return;
5781 increment_at<sizeof...(Ranges) - 1>();
5782 }
5783
5784 template <size_t I>
5785 constexpr etl::enable_if_t<(I > 0)> increment_at()
5786 {
5787 auto& it = etl::get<I>(_current);
5788 ++it;
5789 if (it == etl::get<I>(_ends))
5790 {
5791 it = etl::get<I>(_begins);
5792 increment_at<I - 1>();
5793 }
5794 }
5795
5796 template <size_t I>
5797 constexpr etl::enable_if_t<(I == 0)> increment_at()
5798 {
5799 auto& it = etl::get<0>(_current);
5800 ++it;
5801 if (it == etl::get<0>(_ends))
5802 {
5803 _is_end = true;
5804 }
5805 }
5806
5807 template <size_t... Is>
5808 constexpr value_type deref(etl::index_sequence<Is...>) const
5809 {
5810 return value_type(*etl::get<Is>(_current)...);
5811 }
5812
5813 template <size_t... Is>
5814 constexpr bool all_equal(const cartesian_product_iterator& other, etl::index_sequence<Is...>) const
5815 {
5816 return ((etl::get<Is>(_current) == etl::get<Is>(other._current)) && ...);
5817 }
5818
5819 iterators_type _current;
5820 iterators_type _begins;
5821 iterators_type _ends;
5822 bool _is_end;
5823 };
5824
5825 //*************************************************************************
5832 //*************************************************************************
5833 template <class... Ranges>
5834 class cartesian_product_view : public etl::ranges::view_interface<cartesian_product_view<Ranges...>>
5835 {
5836 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
5837
5838 public:
5839
5840 using iterator = cartesian_product_iterator<Ranges...>;
5841 using const_iterator = cartesian_product_iterator<Ranges...>;
5842
5843 constexpr cartesian_product_view(Ranges&&... r)
5844 : _r{etl::move(r)...}
5845 {
5846 }
5847
5848 cartesian_product_view(const cartesian_product_view& other) = default;
5849
5850 constexpr const_iterator begin() const
5851 {
5852 if (any_empty(etl::make_index_sequence<sizeof...(Ranges)>{}))
5853 {
5854 return end();
5855 }
5856 return make_begin(etl::make_index_sequence<sizeof...(Ranges)>{});
5857 }
5858
5859 constexpr const_iterator end() const
5860 {
5861 return make_end(etl::make_index_sequence<sizeof...(Ranges)>{});
5862 }
5863
5864 constexpr size_t size() const
5865 {
5866 return get_product_size(etl::make_index_sequence<sizeof...(Ranges)>{});
5867 }
5868
5869 private:
5870
5871 template <size_t... Is>
5872 constexpr const_iterator make_begin(etl::index_sequence<Is...>) const
5873 {
5874 return const_iterator(typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...),
5875 typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...),
5876 typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...), false);
5877 }
5878
5879 template <size_t... Is>
5880 constexpr const_iterator make_end(etl::index_sequence<Is...>) const
5881 {
5882 return const_iterator(typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...),
5883 typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...),
5884 typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...), true);
5885 }
5886
5887 template <size_t... Is>
5888 constexpr bool any_empty(etl::index_sequence<Is...>) const
5889 {
5890 return ((ETL_OR_STD::begin(etl::get<Is>(_r)) == ETL_OR_STD::end(etl::get<Is>(_r))) || ...);
5891 }
5892
5893 template <size_t... Is>
5894 constexpr size_t get_product_size(etl::index_sequence<Is...>) const
5895 {
5896 size_t sizes[] = {static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(etl::get<Is>(_r)), ETL_OR_STD::cend(etl::get<Is>(_r))))...};
5897 size_t product = 1;
5898 for (size_t i = 0; i < sizeof...(Ranges); ++i)
5899 {
5900 product *= sizes[i];
5901 }
5902 return product;
5903 }
5904
5905 mutable etl::tuple<Ranges...> _r;
5906 };
5907
5908 template <class... Ranges>
5909 cartesian_product_view(Ranges&&...) -> cartesian_product_view<views::all_t<Ranges>...>;
5910
5911 namespace views
5912 {
5913 namespace private_views
5914 {
5915 struct cartesian_product
5916 {
5917 template <class... Ranges>
5918 constexpr auto operator()(Ranges&&... r) const
5919 {
5920 return cartesian_product_view(views::all(etl::forward<Ranges>(r))...);
5921 }
5922 };
5923 } // namespace private_views
5924
5925 inline constexpr private_views::cartesian_product cartesian_product;
5926 } // namespace views
5927
5928 //*************************************************************************
5933 //*************************************************************************
5934 template <class Range>
5935 class to_input_iterator
5936 {
5937 public:
5938
5939 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
5940
5941 using iterator = typename trait::iterator;
5942 using const_iterator = typename trait::const_iterator;
5943 using value_type = typename trait::value_type;
5944 using difference_type = typename trait::difference_type;
5945 using pointer = typename trait::pointer;
5946 using reference = typename trait::reference;
5947
5948 using iterator_category = ETL_OR_STD::input_iterator_tag;
5949
5950 to_input_iterator() = default;
5951
5952 to_input_iterator(const_iterator it)
5953 : _it(it)
5954 {
5955 }
5956
5957 to_input_iterator(const to_input_iterator& other) = default;
5958
5959 to_input_iterator& operator=(const to_input_iterator& other) = default;
5960
5961 to_input_iterator& operator++()
5962 {
5963 ++_it;
5964 return *this;
5965 }
5966
5967 to_input_iterator operator++(int)
5968 {
5969 to_input_iterator tmp = *this;
5970 ++(*this);
5971 return tmp;
5972 }
5973
5974 reference operator*() const
5975 {
5976 return *_it;
5977 }
5978
5979 pointer operator->() const
5980 {
5981 return &(*_it);
5982 }
5983
5984 bool operator==(const to_input_iterator& other) const
5985 {
5986 return _it == other._it;
5987 }
5988
5989 bool operator!=(const to_input_iterator& other) const
5990 {
5991 return !(*this == other);
5992 }
5993
5994 private:
5995
5996 mutable const_iterator _it;
5997 };
5998
5999 //*************************************************************************
6005 //*************************************************************************
6006 template <class Range>
6007 class to_input_view : public etl::ranges::view_interface<to_input_view<Range>>
6008 {
6009 public:
6010
6011 using iterator = to_input_iterator<Range>;
6012 using const_iterator = iterator;
6013
6014 to_input_view(const to_input_view& other) = default;
6015
6016 to_input_view(Range&& r)
6017 : _r{etl::move(r)}
6018 {
6019 }
6020
6021 constexpr Range& base() const
6022 {
6023 return _r;
6024 }
6025
6026 constexpr iterator begin() const
6027 {
6028 return iterator(ETL_OR_STD::begin(_r));
6029 }
6030
6031 constexpr iterator end() const
6032 {
6033 return iterator(ETL_OR_STD::end(_r));
6034 }
6035
6036 constexpr size_t size() const
6037 {
6038 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
6039 }
6040
6041 private:
6042
6043 mutable Range _r;
6044 };
6045
6046 template <class Range>
6047 to_input_view(Range&&) -> to_input_view<views::all_t<Range>>;
6048
6049 struct to_input_range_adapter_closure : public range_adapter_closure<to_input_range_adapter_closure>
6050 {
6051 template <typename Range>
6052 using target_view_type = to_input_view<Range>;
6053
6054 to_input_range_adapter_closure() = default;
6055
6056 template <typename Range>
6057 constexpr auto operator()(Range&& r)
6058 {
6059 return to_input_view(views::all(etl::forward<Range>(r)));
6060 }
6061 };
6062
6063 namespace views
6064 {
6065 namespace private_views
6066 {
6067 struct to_input
6068 {
6069 template <class Range>
6070 constexpr auto operator()(Range&& r) const
6071 {
6072 return to_input_view(views::all(etl::forward<Range>(r)));
6073 }
6074
6075 constexpr auto operator()() const
6076 {
6077 return ranges::to_input_range_adapter_closure();
6078 }
6079 };
6080 } // namespace private_views
6081
6082 inline constexpr private_views::to_input to_input;
6083 } // namespace views
6084
6085 //*************************************************************************
6092 //*************************************************************************
6093 template <class R>
6094 struct elements_of
6095 {
6096 R range;
6097 };
6098
6099 template <class R>
6100 elements_of(R&&) -> elements_of<R>;
6101
6102 namespace private_ranges
6103 {
6104 template <class C>
6105 struct to_range_adapter_closure : public range_adapter_closure<to_range_adapter_closure<C>>
6106 {
6107 template <class Range = void>
6108 using target_view_type = C;
6109
6110 to_range_adapter_closure() = default;
6111
6112 template <class Range>
6113 C operator()(const Range& r) const
6114 {
6115 using result_type = C;
6116
6117 result_type result;
6118
6119 for (auto i : r)
6120 {
6121 result.push_back(i);
6122 }
6123
6124 return result;
6125 }
6126
6127 template <class Range>
6128 C operator()(Range&& r)
6129 {
6130 using result_type = C;
6131
6132 result_type result;
6133
6134 for (auto&& i : r)
6135 {
6136 result.emplace_back(etl::move(i));
6137 }
6138
6139 return result;
6140 }
6141 };
6142 } // namespace private_ranges
6143
6144 template <class C>
6145 private_ranges::to_range_adapter_closure<C> to()
6146 {
6147 return private_ranges::to_range_adapter_closure<C>();
6148 }
6149
6150 } // namespace ranges
6151
6152 namespace views = ranges::views;
6153} // namespace etl
6154
6155template < class Range, typename RangeAdaptorClosure, typename = etl::enable_if_t<etl::is_invocable_v<RangeAdaptorClosure, Range>>>
6156
6157auto operator|(Range&& r, RangeAdaptorClosure rac)
6158{
6159 return rac(etl::forward<Range>(r));
6160}
6161
6162#endif
6163
6164#endif
ETL_CONSTEXPR14 bool operator!=(const etl::bitset< Active_Bits, TElement > &lhs, const etl::bitset< Active_Bits, TElement > &rhs) ETL_NOEXCEPT
Definition bitset_new.h:2529
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_CONSTEXPR14 void iota(TIterator first, TIterator last, T value)
Definition numeric.h:58
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1081
ETL_CONSTEXPR TContainer::pointer data(TContainer &container)
Definition iterator.h:1228
ETL_CONSTEXPR14 etl::circular_iterator< TIterator > operator-(etl::circular_iterator< TIterator > &lhs, typename etl::iterator_traits< TIterator >::difference_type offset)
Definition circular_iterator.h:675
etl::byte operator|(etl::byte lhs, etl::byte rhs)
Or.
Definition byte.h:250
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits.h:80
ETL_CONSTEXPR TContainer::const_iterator cbegin(const TContainer &container)
Definition iterator.h:987
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1192
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition iterator.h:967
ETL_CONSTEXPR14 enable_if<!etl::is_specialization< TRep2, etl::chrono::duration >::value, etl::chrono::duration< typenameetl::common_type< TRep1, TRep2 >::type, TPeriod1 > >::type operator*(const etl::chrono::duration< TRep1, TPeriod1 > &lhs, const TRep2 &rhs) ETL_NOEXCEPT
Operator *.
Definition duration.h:541
ETL_CONSTEXPR14 etl::circular_iterator< TIterator > operator+(etl::circular_iterator< TIterator > &lhs, typename etl::iterator_traits< TIterator >::difference_type offset)
Definition circular_iterator.h:662
T & get(array< T, Size > &a)
Definition array.h:1161
ETL_CONSTEXPR TContainer::const_iterator cend(const TContainer &container)
Definition iterator.h:1017
etl::add_const< T >::type & as_const(T &t)
as_const
Definition utility.h:526
ETL_CONSTEXPR TContainer::iterator end(TContainer &container)
Definition iterator.h:997