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 "vector.h"
36#include "exception.h"
37#include "error_handler.h"
38#include "memory.h"
39#include "memory_model.h"
40#include "type_traits.h"
41#include "iterator.h"
42#include "static_assert.h"
43#include "initializer_list.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(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 size_t buffer_size = 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 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(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 size_t buffer_size = 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 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 //*************************************************************************
1062 //*************************************************************************
1063 template <typename TIterator>
1064 static difference_type distance(const TIterator& other)
1065 {
1066 const difference_type index = other.get_index();
1067 const difference_type reference_index = static_cast<difference_type>(other.container().out);
1068 const size_t buffer_size = other.container().buffer_size;
1069
1070 if (index < reference_index)
1071 {
1072 return buffer_size + index - reference_index;
1073 }
1074 else
1075 {
1076 return index - reference_index;
1077 }
1078 }
1079
1080 //*************************************************************************
1082 //*************************************************************************
1083 void repair_buffer(T* pbuffer_)
1084 {
1085 pbuffer = pbuffer_;
1086 }
1087
1088 pointer pbuffer;
1089
1090 private:
1091
1092 //*************************************************************************
1094 //*************************************************************************
1095#if defined(ETL_POLYMORPHIC_CIRCULAR_BUFFER) || defined(ETL_POLYMORPHIC_CONTAINERS)
1096 public:
1097 virtual ~icircular_buffer()
1098 {
1099 }
1100#else
1101 protected:
1103 {
1104 }
1105#endif
1106 };
1107
1108 //***************************************************************************
1111 //***************************************************************************
1112 template <typename T, size_t MAX_SIZE_>
1114 {
1115 public:
1116
1117 ETL_STATIC_ASSERT((MAX_SIZE_ > 0U), "Zero capacity etl::circular_buffer is not valid");
1118
1119 static ETL_CONSTANT typename icircular_buffer<T>::size_type MAX_SIZE = typename icircular_buffer<T>::size_type(MAX_SIZE_);
1120
1121 //*************************************************************************
1123 //*************************************************************************
1125 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1126 {
1127 }
1128
1129 //*************************************************************************
1132 //*************************************************************************
1133 template <typename TIterator>
1134 circular_buffer(TIterator first, const TIterator& last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
1135 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1136 {
1137 while (first != last)
1138 {
1139 this->push(*first);
1140 ++first;
1141 }
1142 }
1143
1144#if ETL_HAS_INITIALIZER_LIST
1145 //*************************************************************************
1147 //*************************************************************************
1148 circular_buffer(std::initializer_list<T> init)
1149 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1150 {
1151 this->push(init.begin(), init.end());
1152 }
1153#endif
1154
1155 //*************************************************************************
1157 //*************************************************************************
1159 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1160 {
1161 if (this != &other)
1162 {
1163 this->push(other.begin(), other.end());
1164 }
1165 }
1166
1167 //*************************************************************************
1169 //*************************************************************************
1171 {
1172 if (this != &other)
1173 {
1174 this->clear();
1175 this->push(other.begin(), other.end());
1176 }
1177
1178 return *this;
1179 }
1180
1181#if ETL_USING_CPP11
1182 //*************************************************************************
1184 //*************************************************************************
1186 : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1187 {
1188 if (this != &other)
1189 {
1190 typename etl::icircular_buffer<T>::iterator itr = other.begin();
1191 while (itr != other.end())
1192 {
1193 this->push(etl::move(*itr));
1194 ++itr;
1195 }
1196 }
1197 }
1198
1199 //*************************************************************************
1201 //*************************************************************************
1203 {
1204 if (this != &other)
1205 {
1206 this->clear();
1207
1208 for (typename etl::icircular_buffer<T>::const_iterator itr = other.begin(); itr != other.end(); ++itr)
1209 {
1210 this->push(etl::move(*itr));
1211 }
1212 }
1213
1214 return *this;
1215 }
1216
1217#endif
1218
1219 //*************************************************************************
1221 //*************************************************************************
1223 {
1224 this->clear();
1225 }
1226
1227 //*************************************************************************
1229 //*************************************************************************
1230#ifdef ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE
1231 virtual void repair() ETL_OVERRIDE
1232#else
1233 void repair()
1234#endif
1235 {
1236 ETL_ASSERT(etl::is_trivially_copyable<T>::value, ETL_ERROR(etl::circular_buffer_incompatible_type));
1237
1239 }
1240
1241 private:
1242
1245 };
1246
1247 template <typename T, size_t MAX_SIZE_>
1248 ETL_CONSTANT typename icircular_buffer<T>::size_type circular_buffer<T, MAX_SIZE_>::MAX_SIZE;
1249
1250 //***************************************************************************
1253 //***************************************************************************
1254 template <typename T>
1256 {
1257 public:
1258
1259 //*************************************************************************
1261 //*************************************************************************
1262 circular_buffer_ext(void* buffer, size_t max_size)
1263 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1264 {
1265 }
1266
1267 //*************************************************************************
1270 //*************************************************************************
1271 circular_buffer_ext(size_t max_size)
1272 : icircular_buffer<T>(ETL_NULLPTR, max_size)
1273 {
1274 }
1275
1276 //*************************************************************************
1279 //*************************************************************************
1280 template <typename TIterator>
1281 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)
1282 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1283 {
1284 while (first != last)
1285 {
1286 this->push(*first);
1287 ++first;
1288 }
1289 }
1290
1291#if ETL_HAS_INITIALIZER_LIST
1292 //*************************************************************************
1294 //*************************************************************************
1295 circular_buffer_ext(std::initializer_list<T> init, void* buffer, size_t max_size)
1296 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1297 {
1298 this->push(init.begin(), init.end());
1299 }
1300#endif
1301
1302 //*************************************************************************
1304 //*************************************************************************
1305 circular_buffer_ext(const circular_buffer_ext& other, void* buffer, size_t max_size)
1306 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1307 {
1308 if (this != &other)
1309 {
1310 this->push(other.begin(), other.end());
1311 }
1312 }
1313
1314 //*************************************************************************
1316 //*************************************************************************
1318
1319 //*************************************************************************
1321 //*************************************************************************
1323 {
1324
1325 if (this != &other)
1326 {
1327 this->clear();
1328 this->push(other.begin(), other.end());
1329 }
1330
1331 return *this;
1332 }
1333
1334#if ETL_USING_CPP11
1335 //*************************************************************************
1337 //*************************************************************************
1338 circular_buffer_ext(circular_buffer_ext&& other, void* buffer, size_t max_size)
1339 : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1340 {
1341 if (this != &other)
1342 {
1343 typename etl::icircular_buffer<T>::iterator itr = other.begin();
1344 while (itr != other.end())
1345 {
1346 this->push(etl::move(*itr));
1347 ++itr;
1348 }
1349 }
1350 }
1351
1352 //*************************************************************************
1354 //*************************************************************************
1356 {
1357 if (this != &other)
1358 {
1359 this->clear();
1360
1361 for (typename etl::icircular_buffer<T>::iterator itr = other.begin(); itr != other.end(); ++itr)
1362 {
1363 this->push(etl::move(*itr));
1364 }
1365 }
1366
1367 return *this;
1368 }
1369#endif
1370
1371 //*************************************************************************
1373 //*************************************************************************
1374 void swap(circular_buffer_ext& other) ETL_NOEXCEPT
1375 {
1376 using ETL_OR_STD::swap; // Allow ADL
1377
1378 swap(this->in, other.in);
1379 swap(this->out, other.out);
1380 swap(this->pbuffer, other.pbuffer);
1381 swap(this->buffer_size, other.buffer_size);
1382
1383#if defined(ETL_DEBUG_COUNT)
1384 this->etl_debug_count.swap(other.etl_debug_count);
1385#endif
1386 }
1387
1388#if ETL_USING_CPP11
1389 //*************************************************************************
1391 //*************************************************************************
1392 void swap(circular_buffer_ext&& other) ETL_NOEXCEPT
1393 {
1394 using ETL_OR_STD::swap; // Allow ADL
1395
1396 swap(this->in, other.in);
1397 swap(this->out, other.out);
1398 swap(this->pbuffer, other.pbuffer);
1399 swap(this->buffer_size, other.buffer_size);
1400
1401#if defined(ETL_DEBUG_COUNT)
1402 this->etl_debug_count.swap(other.etl_debug_count);
1403#endif
1404 }
1405#endif
1406
1407 //*************************************************************************
1409 //*************************************************************************
1410 void set_buffer(void* buffer)
1411 {
1412 this->pbuffer = reinterpret_cast<T*>(buffer);
1413 }
1414
1415 //*************************************************************************
1417 //*************************************************************************
1418 bool is_valid() const
1419 {
1420 return this->pbuffer != ETL_NULLPTR;
1421 }
1422
1423 //*************************************************************************
1425 //*************************************************************************
1427 {
1428 this->clear();
1429 }
1430
1431 //*************************************************************************
1433 //*************************************************************************
1434#ifdef ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE
1435 virtual void repair() ETL_OVERRIDE
1436#else
1437 void repair()
1438#endif
1439 {
1440 }
1441 };
1442
1443 //*************************************************************************
1445 //*************************************************************************
1446#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
1447 template <typename T, typename... Ts>
1448 circular_buffer(T, Ts...)
1449 ->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}
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:1256
void swap(circular_buffer_ext &other) ETL_NOEXCEPT
Swap with another circular buffer.
Definition circular_buffer.h:1374
circular_buffer_ext & operator=(const circular_buffer_ext &other)
Assignment operator.
Definition circular_buffer.h:1322
circular_buffer_ext(size_t max_size)
Definition circular_buffer.h:1271
void set_buffer(void *buffer)
set_buffer
Definition circular_buffer.h:1410
circular_buffer_ext(const circular_buffer_ext &other) ETL_DELETE
Copy Constructor (Deleted).
bool is_valid() const
set_buffer
Definition circular_buffer.h:1418
circular_buffer_ext(void *buffer, size_t max_size)
Constructor.
Definition circular_buffer.h:1262
circular_buffer_ext(const circular_buffer_ext &other, void *buffer, size_t max_size)
Construct a copy.
Definition circular_buffer.h:1305
~circular_buffer_ext()
Destructor.
Definition circular_buffer.h:1426
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:1281
void repair()
Fix the internal pointers after a low level memory copy.
Definition circular_buffer.h:1437
Incompatible type exception.
Definition circular_buffer.h:77
Definition circular_buffer.h:1114
circular_buffer(TIterator first, const TIterator &last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition circular_buffer.h:1134
circular_buffer & operator=(const circular_buffer &other)
Assignment operator.
Definition circular_buffer.h:1170
circular_buffer(const circular_buffer &other)
Copy Constructor.
Definition circular_buffer.h:1158
~circular_buffer()
Destructor.
Definition circular_buffer.h:1222
void repair()
Fix the internal pointers after a low level memory copy.
Definition circular_buffer.h:1233
circular_buffer()
Constructor.
Definition circular_buffer.h:1124
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 n)
Add offset.
Definition circular_buffer.h:617
const_iterator & operator--()
Pre-decrement.
Definition circular_buffer.h:587
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
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
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()
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
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
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
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:1083
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)
Measures the distance from the _begin iterator to the specified iterator.
Definition circular_buffer.h:1064
~icircular_buffer()
Destructor.
Definition circular_buffer.h:1102
const_reference front() const
Definition circular_buffer.h:857
Definition iterator.h:228
Definition memory.h:2183
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition exception.h:69
Definition exception.h:47
enable_if
Definition type_traits_generator.h:1254
bitset_ext
Definition absolute.h:39
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:838
size_t max_size() const
Returns the maximum number of items in the variant_pool.
Definition variant_pool_generator.h:395
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1151
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1139
iterator
Definition iterator.h:399