Embedded Template Library 1.0
Loading...
Searching...
No Matches
circular_buffer.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2020 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_CIRCULAR_BUFFER_INCLUDED
32#define ETL_CIRCULAR_BUFFER_INCLUDED
33
34#include "platform.h"
35#include "error_handler.h"
36#include "exception.h"
37#include "initializer_list.h"
38#include "iterator.h"
39#include "memory.h"
40#include "memory_model.h"
41#include "static_assert.h"
42#include "type_traits.h"
43#include "vector.h"
44
45namespace etl
46{
47 //***************************************************************************
49 //***************************************************************************
50 class circular_buffer_exception : public etl::exception
51 {
52 public:
53
54 circular_buffer_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
55 : exception(reason_, file_name_, line_number_)
56 {
57 }
58 };
59
60 //***************************************************************************
62 //***************************************************************************
63 class circular_buffer_empty : public etl::circular_buffer_exception
64 {
65 public:
66
67 circular_buffer_empty(string_type file_name_, numeric_type line_number_)
68 : etl::circular_buffer_exception(ETL_ERROR_TEXT("circular_buffer:empty", ETL_CIRCULAR_BUFFER_FILE_ID"A"), file_name_, line_number_)
69 {
70 }
71 };
72
73 //***************************************************************************
75 //***************************************************************************
76 class circular_buffer_incompatible_type : public circular_buffer_exception
77 {
78 public:
79
80 circular_buffer_incompatible_type(string_type file_name_, numeric_type line_number_)
81 : circular_buffer_exception(ETL_ERROR_TEXT("circular_buffer:type", ETL_CIRCULAR_BUFFER_FILE_ID"B"), file_name_, line_number_)
82 {
83 }
84 };
85
86 //***************************************************************************
88 //***************************************************************************
89 class circular_buffer_base
90 {
91 public:
92
94 typedef size_t size_type;
95
96 //*************************************************************************
97 size_type size() const
98 {
99 return (in >= out) ? in - out : buffer_size - (out - in);
100 }
101
102 //*************************************************************************
103 bool empty() const
104 {
105 return in == out;
106 }
107
108 //*************************************************************************
109 bool full() const
110 {
111 size_t i = in;
112
113 ++i;
114 if (i == buffer_size) ETL_UNLIKELY
115 {
116 i = 0U;
117 }
118
119 return i == out;
120 }
121
122 //*************************************************************************
123 size_type available() const
124 {
125 return max_size() - size();
126 }
127
128 //*************************************************************************
129 size_type max_size() const
130 {
131 return buffer_size - 1U;
132 }
133
134 //*************************************************************************
135 size_type capacity() const
136 {
137 return buffer_size - 1U;
138 }
139
140 protected:
141
142 //*************************************************************************
143 circular_buffer_base(size_type buffer_size_)
144 : buffer_size(buffer_size_)
145 , in(0U)
146 , out(0U)
147 {
148 }
149
150 //*************************************************************************
151 void increment_in()
152 {
153 ++in;
154 if (in == buffer_size) ETL_UNLIKELY
155 {
156 in = 0U;
157 }
158 }
159
160 //*************************************************************************
161 void increment_out()
162 {
163 ++out;
164 if (out == buffer_size) ETL_UNLIKELY
165 {
166 out = 0U;
167 }
168 }
169
170 size_type buffer_size;
174 };
175
176 //***************************************************************************
178 //***************************************************************************
179 template <typename T>
180 class icircular_buffer : public circular_buffer_base
181 {
182 public:
183
184 typedef T value_type;
185 typedef T& reference;
186 typedef const T& const_reference;
187#if ETL_USING_CPP11
188 typedef T&& rvalue_reference;
189#endif
190 typedef T* pointer;
191 typedef const T* const_pointer;
192
193 typedef typename etl::iterator_traits<pointer>::difference_type difference_type;
194
195 //*************************************************************************
197 //*************************************************************************
198 class iterator : public etl::iterator<ETL_OR_STD::random_access_iterator_tag, T>
199 {
200 public:
201
202 friend class icircular_buffer;
203
204 //*************************************************************************
206 //*************************************************************************
208 : picb(ETL_NULLPTR)
209 , current(0U)
210 {
211 }
212
213 //*************************************************************************
215 //*************************************************************************
216 iterator(const iterator& other)
217 : picb(other.picb)
218 , current(other.current)
219 {
220 }
221
222 //*************************************************************************
224 //*************************************************************************
226 {
227 picb = other.picb;
228 current = other.current;
229
230 return *this;
231 }
232
233 //*************************************************************************
235 //*************************************************************************
236 reference operator*() const
237 {
238 return picb->pbuffer[current];
239 }
240
241 //*************************************************************************
243 //*************************************************************************
244 pointer operator->() const
245 {
246 return &picb->pbuffer[current];
247 }
248
249 //*************************************************************************
251 //*************************************************************************
252 reference operator[](size_t index)
253 {
254 return picb->pbuffer[(current + index) % picb->buffer_size];
255 }
256
257 //*************************************************************************
259 //*************************************************************************
260 const_reference operator[](size_t index) const
261 {
262 return picb->pbuffer[(current + index) % picb->buffer_size];
263 }
264
265 //*************************************************************************
267 //*************************************************************************
269 {
270 ++current;
271
272 // Did we reach the end of the buffer?
273 if (current == picb->buffer_size)
274 {
275 current = 0U;
276 }
277
278 return (*this);
279 }
280
281 //*************************************************************************
283 //*************************************************************************
285 {
286 iterator original(*this);
287
288 ++(*this);
289
290 return (original);
291 }
292
293 //*************************************************************************
295 //*************************************************************************
297 {
298 // Are we at the end of the buffer?
299 if (current == 0U)
300 {
301 current = picb->buffer_size - 1;
302 }
303 else
304 {
305 --current;
306 }
307
308 return (*this);
309 }
310
311 //*************************************************************************
313 //*************************************************************************
315 {
316 iterator original(*this);
317
318 --(*this);
319
320 return (original);
321 }
322
323 //*************************************************************************
325 //*************************************************************************
327 {
328 current += size_type(static_cast<int>(picb->buffer_size) + n);
329 current %= picb->buffer_size;
330
331 return (*this);
332 }
333
334 //*************************************************************************
336 //*************************************************************************
338 {
339 return (this->operator+=(-n));
340 }
341
342 //*************************************************************************
344 //*************************************************************************
345 friend iterator operator+(const iterator& lhs, int n)
346 {
347 iterator temp = lhs;
348
349 temp += n;
350
351 return temp;
352 }
353
354 //*************************************************************************
356 //*************************************************************************
357 friend iterator operator+(int n, const iterator& rhs)
358 {
359 iterator temp = rhs;
360
361 temp += n;
362
363 return temp;
364 }
365
366 //*************************************************************************
368 //*************************************************************************
369 friend iterator operator-(const iterator& lhs, int n)
370 {
371 iterator temp = lhs;
372
373 temp -= n;
374
375 return temp;
376 }
377
378 //*************************************************************************
380 //*************************************************************************
381 friend bool operator==(const iterator& lhs, const iterator& rhs)
382 {
383 return (lhs.current == rhs.current);
384 }
385
386 //*************************************************************************
388 //*************************************************************************
389 friend bool operator!=(const iterator& lhs, const iterator& rhs)
390 {
391 return !(lhs == rhs);
392 }
393
394 //***************************************************
395 friend bool operator<(const iterator& lhs, const iterator& rhs)
396 {
397 const difference_type lhs_index = lhs.get_index();
398 const difference_type rhs_index = rhs.get_index();
399 const difference_type reference_index = lhs.container().begin().get_index();
400 const difference_type buffer_size = static_cast<difference_type>(lhs.container().max_size() + 1UL);
401
402 const difference_type lhs_distance = (lhs_index < reference_index) ? buffer_size + lhs_index - reference_index : lhs_index - reference_index;
403 const difference_type rhs_distance = (rhs_index < reference_index) ? buffer_size + rhs_index - reference_index : rhs_index - reference_index;
404
405 return lhs_distance < rhs_distance;
406 }
407
408 //***************************************************
409 friend bool operator<=(const iterator& lhs, const iterator& rhs)
410 {
411 return !(lhs > rhs);
412 }
413
414 //***************************************************
415 friend bool operator>(const iterator& lhs, const iterator& rhs)
416 {
417 return (rhs < lhs);
418 }
419
420 //***************************************************
421 friend bool operator>=(const iterator& lhs, const iterator& rhs)
422 {
423 return !(lhs < rhs);
424 }
425
426 //***************************************************
427 difference_type get_index() const
428 {
429 return static_cast<difference_type>(current);
430 }
431
432 //***************************************************
433 const icircular_buffer& container() const
434 {
435 return *picb;
436 }
437
438 //***************************************************
439 pointer get_buffer() const
440 {
441 return picb->pbuffer;
442 }
443
444 protected:
445
446 //***************************************************
447 difference_type distance(difference_type firstIndex, difference_type index) const
448 {
449 if (index < firstIndex)
450 {
451 return picb->buffer_size + current - firstIndex;
452 }
453 else
454 {
455 return index - firstIndex;
456 }
457 }
458
459 //*************************************************************************
461 //*************************************************************************
462 iterator(const icircular_buffer<T>* picb_, size_type current_)
463 : picb(picb_)
464 , current(current_)
465 {
466 }
467
468 private:
469
470 const icircular_buffer<T>* picb;
471 size_type current;
472 };
473
474 //*************************************************************************
476 //*************************************************************************
477 class const_iterator : public etl::iterator<ETL_OR_STD::random_access_iterator_tag, const T>
478 {
479 public:
480
481 friend class icircular_buffer;
482
483 //*************************************************************************
485 //*************************************************************************
487 : picb(ETL_NULLPTR)
488 , current(0U)
489 {
490 }
491
492 //*************************************************************************
494 //*************************************************************************
496 : picb(other.picb)
497 , current(other.current)
498 {
499 }
500
501 //*************************************************************************
503 //*************************************************************************
505 : picb(other.picb)
506 , current(other.current)
507 {
508 }
509
510 //*************************************************************************
512 //*************************************************************************
514 {
515 picb = other.picb;
516 current = other.current;
517
518 return *this;
519 }
520
521 //*************************************************************************
523 //*************************************************************************
525 {
526 picb = other.picb;
527 current = other.current;
528
529 return *this;
530 }
531
532 //*************************************************************************
534 //*************************************************************************
535 const_reference operator*() const
536 {
537 return picb->pbuffer[current];
538 }
539
540 //*************************************************************************
542 //*************************************************************************
543 const_pointer operator->() const
544 {
545 return &(picb->pbuffer[current]);
546 }
547
548 //*************************************************************************
550 //*************************************************************************
551 const_reference operator[](size_t index) const
552 {
553 return picb->pbuffer[(current + index) % picb->buffer_size];
554 }
555
556 //*************************************************************************
558 //*************************************************************************
560 {
561 ++current;
562
563 // Did we reach the end of the buffer?
564 if (current == picb->buffer_size)
565 {
566 current = 0U;
567 }
568
569 return (*this);
570 }
571
572 //*************************************************************************
574 //*************************************************************************
576 {
577 const_iterator original(*this);
578
579 ++(*this);
580
581 return (original);
582 }
583
584 //*************************************************************************
586 //*************************************************************************
588 {
589 // Are we at the end of the buffer?
590 if (current == 0U)
591 {
592 current = picb->buffer_size - 1;
593 }
594 else
595 {
596 --current;
597 }
598
599 return (*this);
600 }
601
602 //*************************************************************************
604 //*************************************************************************
606 {
607 const_iterator original(*this);
608
609 --(*this);
610
611 return (original);
612 }
613
614 //*************************************************************************
616 //*************************************************************************
618 {
619 current += size_type(static_cast<int>(picb->buffer_size) + n);
620 current %= picb->buffer_size;
621
622 return (*this);
623 }
624
625 //*************************************************************************
627 //*************************************************************************
629 {
630 return (this->operator+=(-n));
631 }
632
633 //*************************************************************************
635 //*************************************************************************
636 friend const_iterator operator+(const const_iterator& lhs, int n)
637 {
638 const_iterator temp = lhs;
639
640 temp += n;
641
642 return temp;
643 }
644
645 //*************************************************************************
647 //*************************************************************************
648 friend const_iterator operator-(const const_iterator& lhs, int n)
649 {
650 const_iterator temp = lhs;
651
652 temp -= n;
653
654 return temp;
655 }
656
657 //*************************************************************************
659 //*************************************************************************
660 friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
661 {
662 return (lhs.current == rhs.current);
663 }
664
665 //*************************************************************************
667 //*************************************************************************
668 friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
669 {
670 return !(lhs == rhs);
671 }
672
673 //***************************************************
674 friend bool operator<(const const_iterator& lhs, const const_iterator& rhs)
675 {
676 const difference_type lhs_index = lhs.get_index();
677 const difference_type rhs_index = rhs.get_index();
678 const difference_type reference_index = lhs.container().begin().get_index();
679 const difference_type buffer_size = static_cast<difference_type>(lhs.container().max_size() + 1UL);
680
681 const difference_type lhs_distance = (lhs_index < reference_index) ? buffer_size + lhs_index - reference_index : lhs_index - reference_index;
682 const difference_type rhs_distance = (rhs_index < reference_index) ? buffer_size + rhs_index - reference_index : rhs_index - reference_index;
683
684 return lhs_distance < rhs_distance;
685 }
686
687 //***************************************************
688 friend bool operator<=(const const_iterator& lhs, const const_iterator& rhs)
689 {
690 return !(lhs > rhs);
691 }
692
693 //***************************************************
694 friend bool operator>(const const_iterator& lhs, const const_iterator& rhs)
695 {
696 return (rhs < lhs);
697 }
698
699 //***************************************************
700 friend bool operator>=(const const_iterator& lhs, const const_iterator& rhs)
701 {
702 return !(lhs < rhs);
703 }
704
705 //***************************************************
706 difference_type get_index() const
707 {
708 return static_cast<difference_type>(current);
709 }
710
711 //***************************************************
712 const icircular_buffer& container() const
713 {
714 return *picb;
715 }
716
717 //***************************************************
718 pointer get_buffer() const
719 {
720 return picb->pbuffer;
721 }
722
723 protected:
724
725 //*************************************************************************
727 //*************************************************************************
728 const_iterator(const icircular_buffer<T>* picb_, size_type current_)
729 : picb(picb_)
730 , current(current_)
731 {
732 }
733
734 private:
735
736 const icircular_buffer<T>* picb;
737 size_type current;
738 };
739
740 friend class iterator;
741 friend class const_iterator;
742
744 typedef etl::reverse_iterator<const_iterator> const_reverse_iterator;
745
746 //*************************************************************************
748 //*************************************************************************
750 {
751 return iterator(this, out);
752 }
753
754 //*************************************************************************
756 //*************************************************************************
758 {
759 return const_iterator(this, out);
760 }
761
762 //*************************************************************************
764 //*************************************************************************
766 {
767 return const_iterator(this, out);
768 }
769
770 //*************************************************************************
772 //*************************************************************************
774 {
775 return iterator(this, in);
776 }
777
778 //*************************************************************************
780 //*************************************************************************
782 {
783 return const_iterator(this, in);
784 }
785
786 //*************************************************************************
788 //*************************************************************************
790 {
791 return const_iterator(this, in);
792 }
793
794 //*************************************************************************
796 //*************************************************************************
797 reverse_iterator rbegin()
798 {
799 return reverse_iterator(end());
800 }
801
802 //*************************************************************************
804 //*************************************************************************
805 const_reverse_iterator rbegin() const
806 {
807 return const_reverse_iterator(end());
808 }
809
810 //*************************************************************************
812 //*************************************************************************
813 const_reverse_iterator crbegin() const
814 {
815 return const_reverse_iterator(end());
816 }
817
818 //*************************************************************************
820 //*************************************************************************
821 reverse_iterator rend()
822 {
823 return reverse_iterator(begin());
824 }
825
826 //*************************************************************************
828 //*************************************************************************
829 const_reverse_iterator rend() const
830 {
831 return const_reverse_iterator(begin());
832 }
833
834 //*************************************************************************
836 //*************************************************************************
837 const_reverse_iterator crend() const
838 {
839 return const_reverse_iterator(begin());
840 }
841
842 //*************************************************************************
845 //*************************************************************************
846 reference front()
847 {
848 ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
849
850 return pbuffer[out];
851 }
852
853 //*************************************************************************
856 //*************************************************************************
857 const_reference front() const
858 {
859 ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
860
861 return pbuffer[out];
862 }
863
864 //*************************************************************************
867 //*************************************************************************
868 reference back()
869 {
870 ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
871
872 return pbuffer[in == 0U ? buffer_size - 1 : in - 1U];
873 }
874
875 //*************************************************************************
878 //*************************************************************************
879 const_reference back() const
880 {
881 ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
882
883 return pbuffer[in == 0U ? buffer_size - 1 : in - 1U];
884 }
885
886 //*************************************************************************
888 //*************************************************************************
889 reference operator[](size_t index)
890 {
891 return pbuffer[(out + index) % buffer_size];
892 }
893
894 //*************************************************************************
897 //*************************************************************************
898 const_reference operator[](size_t index) const
899 {
900 return pbuffer[(out + index) % buffer_size];
901 }
902
903 //*************************************************************************
907 //*************************************************************************
908 void push(const_reference item)
909 {
910 ::new (&pbuffer[in]) T(item);
911 increment_in();
912
913 // Did we catch up with the 'out' index?
914 if (in == out)
915 {
916 // Forget about the oldest one.
917 pbuffer[out].~T();
918 this->increment_out();
919 }
920 else
921 {
922 ETL_INCREMENT_DEBUG_COUNT;
923 }
924 }
925
926#if ETL_USING_CPP11
927 //*************************************************************************
931 //*************************************************************************
932 void push(rvalue_reference item)
933 {
934 ::new (&pbuffer[in]) T(etl::move(item));
935 increment_in();
936
937 // Did we catch up with the 'out' index?
938 if (in == out)
939 {
940 // Forget about the oldest item.
941 pbuffer[out].~T();
942 increment_out();
943 }
944 else
945 {
946 ETL_INCREMENT_DEBUG_COUNT;
947 }
948 }
949#endif
950
951 //*************************************************************************
953 //*************************************************************************
954 template <typename TIterator>
955 void push(TIterator first, const TIterator& last)
956 {
957 while (first != last)
958 {
959 push(*first);
960 ++first;
961 }
962 }
963
964 //*************************************************************************
966 //*************************************************************************
967 void pop()
968 {
969 ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
970 pbuffer[out].~T();
971 increment_out();
972 ETL_DECREMENT_DEBUG_COUNT;
973 }
974
975 //*************************************************************************
977 //*************************************************************************
979 {
980 while (n-- != 0U)
981 {
982 pop();
983 }
984 }
985
986 //*************************************************************************
988 //*************************************************************************
989 void clear()
990 {
991 if ETL_IF_CONSTEXPR (etl::is_trivially_destructible<T>::value)
992 {
993 in = 0U;
994 out = 0U;
995 ETL_RESET_DEBUG_COUNT;
996 }
997 else
998 {
999 while (!empty())
1000 {
1001 pop();
1002 }
1003 }
1004 }
1005
1006 //*************************************************************************
1008 //*************************************************************************
1009 void fill(const T& value)
1010 {
1011 etl::fill(begin(), end(), value);
1012 }
1013
1014#ifdef ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE
1015 //*************************************************************************
1017 //*************************************************************************
1018 virtual void repair() = 0;
1019#endif
1020
1021 //*************************************************************************
1023 //*************************************************************************
1024 friend difference_type operator-(const iterator& lhs, const iterator& rhs)
1025 {
1026 return distance(rhs, lhs);
1027 }
1028
1029 //*************************************************************************
1031 //*************************************************************************
1032 friend difference_type operator-(const const_iterator& lhs, const const_iterator& rhs)
1033 {
1034 return distance(rhs, lhs);
1035 }
1036
1037 protected:
1038
1039 //*************************************************************************
1041 //*************************************************************************
1042 icircular_buffer(pointer pbuffer_, size_type max_length)
1043 : circular_buffer_base(max_length + 1U)
1044 , pbuffer(pbuffer_)
1045 {
1046 }
1047
1048 //*************************************************************************
1050 //*************************************************************************
1051 template <typename TIterator1, typename TIterator2>
1052 static difference_type distance(const TIterator1& range_begin, const TIterator2& range_end)
1053 {
1054 difference_type distance1 = distance(range_begin);
1055 difference_type distance2 = distance(range_end);
1056
1057 return distance2 - distance1;
1058 }
1059
1060 //*************************************************************************
1063 //*************************************************************************
1064 template <typename TIterator>
1065 static difference_type distance(const TIterator& other)
1066 {
1067 const difference_type index = other.get_index();
1068 const difference_type reference_index = static_cast<difference_type>(other.container().out);
1069 const difference_type buffer_size = static_cast<difference_type>(other.container().buffer_size);
1070
1071 if (index < reference_index)
1072 {
1073 return buffer_size + index - reference_index;
1074 }
1075 else
1076 {
1077 return index - reference_index;
1078 }
1079 }
1080
1081 //*************************************************************************
1083 //*************************************************************************
1084 void repair_buffer(T* pbuffer_)
1085 {
1086 pbuffer = pbuffer_;
1087 }
1088
1089 pointer pbuffer;
1090
1091 private:
1092
1093 //*************************************************************************
1095 //*************************************************************************
1096#if defined(ETL_POLYMORPHIC_CIRCULAR_BUFFER) || defined(ETL_POLYMORPHIC_CONTAINERS)
1097
1098 public:
1099
1100 virtual ~icircular_buffer() {}
1101#else
1102
1103 protected:
1104
1106#endif
1107 };
1108
1109 //***************************************************************************
1112 //***************************************************************************
1113 template <typename T, size_t MAX_SIZE_>
1115 {
1116 public:
1117
1118 ETL_STATIC_ASSERT((MAX_SIZE_ > 0U), "Zero capacity etl::circular_buffer is not valid");
1119
1120 static ETL_CONSTANT typename icircular_buffer<T>::size_type MAX_SIZE = typename icircular_buffer<T>::size_type(MAX_SIZE_);
1121
1122 //*************************************************************************
1124 //*************************************************************************
1126 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1127 {
1128 }
1129
1130 //*************************************************************************
1133 //*************************************************************************
1134 template <typename TIterator>
1135 circular_buffer(TIterator first, const TIterator& last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
1136 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1137 {
1138 while (first != last)
1139 {
1140 this->push(*first);
1141 ++first;
1142 }
1143 }
1144
1145#if ETL_HAS_INITIALIZER_LIST
1146 //*************************************************************************
1148 //*************************************************************************
1149 circular_buffer(std::initializer_list<T> init)
1150 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1151 {
1152 this->push(init.begin(), init.end());
1153 }
1154#endif
1155
1156 //*************************************************************************
1158 //*************************************************************************
1160 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1161 {
1162 if (this != &other)
1163 {
1164 this->push(other.begin(), other.end());
1165 }
1166 }
1167
1168 //*************************************************************************
1170 //*************************************************************************
1172 {
1173 if (this != &other)
1174 {
1175 this->clear();
1176 this->push(other.begin(), other.end());
1177 }
1178
1179 return *this;
1180 }
1181
1182#if ETL_USING_CPP11
1183 //*************************************************************************
1185 //*************************************************************************
1187 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1188 {
1189 if (this != &other)
1190 {
1191 typename etl::icircular_buffer<T>::iterator itr = other.begin();
1192 while (itr != other.end())
1193 {
1194 this->push(etl::move(*itr));
1195 ++itr;
1196 }
1197 }
1198 }
1199
1200 //*************************************************************************
1202 //*************************************************************************
1204 {
1205 if (this != &other)
1206 {
1207 this->clear();
1208
1209 for (typename etl::icircular_buffer<T>::const_iterator itr = other.begin(); itr != other.end(); ++itr)
1210 {
1211 this->push(etl::move(*itr));
1212 }
1213 }
1214
1215 return *this;
1216 }
1217
1218#endif
1219
1220 //*************************************************************************
1222 //*************************************************************************
1224 {
1225 this->clear();
1226 }
1227
1228 //*************************************************************************
1230 //*************************************************************************
1231#ifdef ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE
1232 virtual void repair() ETL_OVERRIDE
1233#else
1234 void repair()
1235#endif
1236 {
1237 ETL_ASSERT(etl::is_trivially_copyable<T>::value, ETL_ERROR(etl::circular_buffer_incompatible_type));
1238
1240 }
1241
1242 private:
1243
1246 };
1247
1248 template <typename T, size_t MAX_SIZE_>
1249 ETL_CONSTANT typename icircular_buffer<T>::size_type circular_buffer<T, MAX_SIZE_>::MAX_SIZE;
1250
1251 //***************************************************************************
1254 //***************************************************************************
1255 template <typename T>
1257 {
1258 public:
1259
1260 //*************************************************************************
1262 //*************************************************************************
1263 circular_buffer_ext(void* buffer, size_t max_size)
1264 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1265 {
1266 }
1267
1268 //*************************************************************************
1271 //*************************************************************************
1272 circular_buffer_ext(size_t max_size)
1273 : icircular_buffer<T>(ETL_NULLPTR, max_size)
1274 {
1275 }
1276
1277 //*************************************************************************
1280 //*************************************************************************
1281 template <typename TIterator>
1282 circular_buffer_ext(TIterator first, const TIterator& last, void* buffer, size_t max_size,
1283 typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
1284 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1285 {
1286 while (first != last)
1287 {
1288 this->push(*first);
1289 ++first;
1290 }
1291 }
1292
1293#if ETL_HAS_INITIALIZER_LIST
1294 //*************************************************************************
1296 //*************************************************************************
1297 circular_buffer_ext(std::initializer_list<T> init, void* buffer, size_t max_size)
1298 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1299 {
1300 this->push(init.begin(), init.end());
1301 }
1302#endif
1303
1304 //*************************************************************************
1306 //*************************************************************************
1307 circular_buffer_ext(const circular_buffer_ext& other, void* buffer, size_t max_size)
1308 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1309 {
1310 if (this != &other)
1311 {
1312 this->push(other.begin(), other.end());
1313 }
1314 }
1315
1316 //*************************************************************************
1318 //*************************************************************************
1320
1321 //*************************************************************************
1323 //*************************************************************************
1325 {
1326 if (this != &other)
1327 {
1328 this->clear();
1329 this->push(other.begin(), other.end());
1330 }
1331
1332 return *this;
1333 }
1334
1335#if ETL_USING_CPP11
1336 //*************************************************************************
1338 //*************************************************************************
1339 circular_buffer_ext(circular_buffer_ext&& other, void* buffer, size_t max_size)
1340 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1341 {
1342 if (this != &other)
1343 {
1344 typename etl::icircular_buffer<T>::iterator itr = other.begin();
1345 while (itr != other.end())
1346 {
1347 this->push(etl::move(*itr));
1348 ++itr;
1349 }
1350 }
1351 }
1352
1353 //*************************************************************************
1355 //*************************************************************************
1357 {
1358 if (this != &other)
1359 {
1360 this->clear();
1361
1362 for (typename etl::icircular_buffer<T>::iterator itr = other.begin(); itr != other.end(); ++itr)
1363 {
1364 this->push(etl::move(*itr));
1365 }
1366 }
1367
1368 return *this;
1369 }
1370#endif
1371
1372 //*************************************************************************
1374 //*************************************************************************
1375 void swap(circular_buffer_ext& other) ETL_NOEXCEPT
1376 {
1377 using ETL_OR_STD::swap; // Allow ADL
1378
1379 swap(this->in, other.in);
1380 swap(this->out, other.out);
1381 swap(this->pbuffer, other.pbuffer);
1382 swap(this->buffer_size, other.buffer_size);
1383
1384#if defined(ETL_DEBUG_COUNT)
1385 this->etl_debug_count.swap(other.etl_debug_count);
1386#endif
1387 }
1388
1389#if ETL_USING_CPP11
1390 //*************************************************************************
1392 //*************************************************************************
1393 void swap(circular_buffer_ext&& other) ETL_NOEXCEPT
1394 {
1395 using ETL_OR_STD::swap; // Allow ADL
1396
1397 swap(this->in, other.in);
1398 swap(this->out, other.out);
1399 swap(this->pbuffer, other.pbuffer);
1400 swap(this->buffer_size, other.buffer_size);
1401
1402 #if defined(ETL_DEBUG_COUNT)
1403 this->etl_debug_count.swap(other.etl_debug_count);
1404 #endif
1405 }
1406#endif
1407
1408 //*************************************************************************
1410 //*************************************************************************
1411 void set_buffer(void* buffer)
1412 {
1413 this->pbuffer = reinterpret_cast<T*>(buffer);
1414 }
1415
1416 //*************************************************************************
1418 //*************************************************************************
1419 bool is_valid() const
1420 {
1421 return this->pbuffer != ETL_NULLPTR;
1422 }
1423
1424 //*************************************************************************
1426 //*************************************************************************
1428 {
1429 this->clear();
1430 }
1431
1432 //*************************************************************************
1434 //*************************************************************************
1435#ifdef ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE
1436 virtual void repair() ETL_OVERRIDE
1437#else
1438 void repair()
1439#endif
1440 {
1441 }
1442 };
1443
1444 //*************************************************************************
1446 //*************************************************************************
1447#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
1448 template <typename T, typename... Ts>
1449 circular_buffer(T, Ts...) -> circular_buffer<etl::enable_if_t<(etl::is_same_v<T, Ts> && ...), T>, 1U + sizeof...(Ts)>;
1450#endif
1451
1452 //*************************************************************************
1454 //*************************************************************************
1455 template <typename T>
1457 {
1458 lhs.swap(rhs);
1459 }
1460
1461#if ETL_USING_CPP11
1462 //*************************************************************************
1464 //*************************************************************************
1465 template <typename T>
1467 {
1468 lhs.swap(rhs);
1469 }
1470#endif
1471
1472 //*************************************************************************
1474 //*************************************************************************
1475 template <typename T>
1477 {
1478 return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
1479 }
1480
1481 //*************************************************************************
1483 //*************************************************************************
1484 template <typename T>
1486 {
1487 return !(lhs == rhs);
1488 }
1489} // namespace etl
1490
1491#endif
size_t size_type
The type used for determining the size of queue.
Definition circular_buffer.h:94
size_type out
Index to the next read.
Definition circular_buffer.h:172
ETL_DECLARE_DEBUG_COUNT
Internal debugging.
Definition circular_buffer.h:173
size_type in
Index to the next write.
Definition circular_buffer.h:171
Empty exception for the circular_buffer.
Definition circular_buffer.h:64
Exception for the circular_buffer.
Definition circular_buffer.h:51
Definition circular_buffer.h:1257
void swap(circular_buffer_ext &other) ETL_NOEXCEPT
Swap with another circular buffer.
Definition circular_buffer.h:1375
circular_buffer_ext & operator=(const circular_buffer_ext &other)
Assignment operator.
Definition circular_buffer.h:1324
circular_buffer_ext(size_t max_size)
Definition circular_buffer.h:1272
void set_buffer(void *buffer)
set_buffer
Definition circular_buffer.h:1411
circular_buffer_ext(const circular_buffer_ext &other) ETL_DELETE
Copy Constructor (Deleted).
bool is_valid() const
set_buffer
Definition circular_buffer.h:1419
circular_buffer_ext(void *buffer, size_t max_size)
Constructor.
Definition circular_buffer.h:1263
circular_buffer_ext(const circular_buffer_ext &other, void *buffer, size_t max_size)
Construct a copy.
Definition circular_buffer.h:1307
~circular_buffer_ext()
Destructor.
Definition circular_buffer.h:1427
circular_buffer_ext(TIterator first, const TIterator &last, void *buffer, size_t max_size, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition circular_buffer.h:1282
void repair()
Fix the internal pointers after a low level memory copy.
Definition circular_buffer.h:1438
Incompatible type exception.
Definition circular_buffer.h:77
Definition circular_buffer.h:1115
circular_buffer(TIterator first, const TIterator &last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition circular_buffer.h:1135
circular_buffer & operator=(const circular_buffer &other)
Assignment operator.
Definition circular_buffer.h:1171
circular_buffer(const circular_buffer &other)
Copy Constructor.
Definition circular_buffer.h:1159
~circular_buffer()
Destructor.
Definition circular_buffer.h:1223
void repair()
Fix the internal pointers after a low level memory copy.
Definition circular_buffer.h:1234
circular_buffer()
Constructor.
Definition circular_buffer.h:1125
Iterator iterating through the circular buffer.
Definition circular_buffer.h:478
const_iterator & operator-=(int n)
Subtract offset.
Definition circular_buffer.h:628
const_iterator()
Constructor.
Definition circular_buffer.h:486
const_iterator(const icircular_buffer< T > *picb_, size_type current_)
Protected constructor. Only icircular_buffer can create one.
Definition circular_buffer.h:728
const_iterator(const typename icircular_buffer::iterator &other)
Copy Constructor from iterator.
Definition circular_buffer.h:495
const_reference operator[](size_t index) const
[] operator
Definition circular_buffer.h:551
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs)
Inequality operator.
Definition circular_buffer.h:668
const_iterator operator++(int)
Post increment.
Definition circular_buffer.h:575
const_iterator & operator+=(int n)
Add offset.
Definition circular_buffer.h:617
const_iterator & operator--()
Pre-decrement.
Definition circular_buffer.h:587
const_iterator operator--(int)
Post increment.
Definition circular_buffer.h:605
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs)
Equality operator.
Definition circular_buffer.h:660
const_iterator(const const_iterator &other)
Copy Constructor from const iterator.
Definition circular_buffer.h:504
const_iterator & operator++()
Pre-increment.
Definition circular_buffer.h:559
const_reference operator*() const
Definition circular_buffer.h:535
friend const_iterator operator-(const const_iterator &lhs, int n)
Subtract offset.
Definition circular_buffer.h:648
const_pointer operator->() const
-> operator
Definition circular_buffer.h:543
friend const_iterator operator+(const const_iterator &lhs, int n)
Add offset.
Definition circular_buffer.h:636
const_iterator & operator=(const typename icircular_buffer::iterator &other)
Assignment operator.
Definition circular_buffer.h:513
const_iterator & operator=(const const_iterator &other)
Assignment operator.
Definition circular_buffer.h:524
Iterator iterating through the circular buffer.
Definition circular_buffer.h:199
iterator(const icircular_buffer< T > *picb_, size_type current_)
Protected constructor. Only icircular_buffer can create one.
Definition circular_buffer.h:462
iterator & operator+=(int n)
Add offset.
Definition circular_buffer.h:326
friend bool operator==(const iterator &lhs, const iterator &rhs)
Equality operator.
Definition circular_buffer.h:381
iterator & operator--()
Pre-decrement.
Definition circular_buffer.h:296
const_reference operator[](size_t index) const
[] operator
Definition circular_buffer.h:260
friend iterator operator-(const iterator &lhs, int n)
Subtract offset.
Definition circular_buffer.h:369
pointer operator->() const
-> operator
Definition circular_buffer.h:244
iterator & operator-=(int n)
Subtract offset.
Definition circular_buffer.h:337
friend iterator operator+(const iterator &lhs, int n)
Add offset.
Definition circular_buffer.h:345
reference operator*() const
Definition circular_buffer.h:236
iterator & operator=(const iterator &other)
Assignment operator.
Definition circular_buffer.h:225
iterator operator--(int)
Post increment.
Definition circular_buffer.h:314
iterator operator++(int)
Post increment.
Definition circular_buffer.h:284
iterator()
Constructor.
Definition circular_buffer.h:207
reference operator[](size_t index)
[] operator
Definition circular_buffer.h:252
friend bool operator!=(const iterator &lhs, const iterator &rhs)
Inequality operator.
Definition circular_buffer.h:389
friend iterator operator+(int n, const iterator &rhs)
Add offset.
Definition circular_buffer.h:357
iterator & operator++()
Pre-increment.
Definition circular_buffer.h:268
iterator(const iterator &other)
Copy Constructor.
Definition circular_buffer.h:216
Definition circular_buffer.h:181
static difference_type distance(const TIterator1 &range_begin, const TIterator2 &range_end)
Measures the distance between two iterators.
Definition circular_buffer.h:1052
const_reference operator[](size_t index) const
Definition circular_buffer.h:898
void fill(const T &value)
Fills the buffer.
Definition circular_buffer.h:1009
const_reverse_iterator rend() const
Gets a const reverse iterator to the end of the buffer.
Definition circular_buffer.h:829
void pop()
pop
Definition circular_buffer.h:967
reverse_iterator rend()
Gets a reverse iterator to the end of the buffer.
Definition circular_buffer.h:821
const_reverse_iterator rbegin() const
Gets a const reverse iterator to the start of the buffer.
Definition circular_buffer.h:805
void push(TIterator first, const TIterator &last)
Push a buffer from an iterator range.
Definition circular_buffer.h:955
friend difference_type operator-(const iterator &lhs, const iterator &rhs)
Definition circular_buffer.h:1024
const_iterator end() const
Gets a const iterator to the end of the buffer.
Definition circular_buffer.h:781
const_reference back() const
Definition circular_buffer.h:879
iterator end()
Gets an iterator to the end of the buffer.
Definition circular_buffer.h:773
iterator begin()
Gets an iterator to the start of the buffer.
Definition circular_buffer.h:749
const_iterator begin() const
Gets a const iterator to the start of the buffer.
Definition circular_buffer.h:757
const_iterator cbegin() const
Gets a const iterator to the start of the buffer.
Definition circular_buffer.h:765
const_reverse_iterator crend() const
Gets a const reverse iterator to the end of the buffer.
Definition circular_buffer.h:837
reference front()
Definition circular_buffer.h:846
friend difference_type operator-(const const_iterator &lhs, const const_iterator &rhs)
Definition circular_buffer.h:1032
void clear()
Clears the buffer.
Definition circular_buffer.h:989
void repair_buffer(T *pbuffer_)
Fix the internal pointers after a low level memory copy.
Definition circular_buffer.h:1084
reference back()
Definition circular_buffer.h:868
icircular_buffer(pointer pbuffer_, size_type max_length)
Protected constructor.
Definition circular_buffer.h:1042
reverse_iterator rbegin()
Gets a reverse iterator to the start of the buffer.
Definition circular_buffer.h:797
void pop(size_type n)
pop(n)
Definition circular_buffer.h:978
reference operator[](size_t index)
Get a reference to the item.
Definition circular_buffer.h:889
void push(const_reference item)
Definition circular_buffer.h:908
const_iterator cend() const
Gets a const iterator to the end of the buffer.
Definition circular_buffer.h:789
const_reverse_iterator crbegin() const
Gets a const reverse iterator to the start of the buffer.
Definition circular_buffer.h:813
static difference_type distance(const TIterator &other)
Definition circular_buffer.h:1065
~icircular_buffer()
Destructor.
Definition circular_buffer.h:1105
const_reference front() const
Definition circular_buffer.h:857
Definition iterator.h:252
Definition memory.h:2728
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR14 void swap(etl::typed_storage_ext< T > &lhs, etl::typed_storage_ext< T > &rhs) ETL_NOEXCEPT
Swap two etl::typed_storage_ext.
Definition alignment.h:856
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1081
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1093
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1106
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1120
iterator
Definition iterator.h:424