Embedded Template Library  1.0
circular_buffer.h
Go to the documentation of this file.
1 
3 /******************************************************************************
4 The MIT License(MIT)
5 
6 Embedded Template Library.
7 https://github.com/ETLCPP/etl
8 https://www.etlcpp.com
9 
10 Copyright(c) 2020 jwellbelove
11 
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files(the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions :
18 
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21 
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
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 
44 #undef ETL_FILE
45 #define ETL_FILE "56"
46 
47 namespace etl
48 {
49  //***************************************************************************
51  //***************************************************************************
53  {
54  public:
55 
56  circular_buffer_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
57  : exception(reason_, file_name_, line_number_)
58  {
59  }
60  };
61 
62  //***************************************************************************
64  //***************************************************************************
66  {
67  public:
68 
69  circular_buffer_empty(string_type file_name_, numeric_type line_number_)
70  : etl::circular_buffer_exception(ETL_ERROR_TEXT("circular_buffer:empty", ETL_FILE"A"), file_name_, line_number_)
71  {
72  }
73  };
74 
75  //***************************************************************************
77  //***************************************************************************
79  {
80  public:
81 
83  typedef size_t size_type;
84 
85  //*************************************************************************
86  size_type size() const
87  {
88  return (in >= out) ? in - out : BUFFER_SIZE - (out - in);
89  }
90 
91  //*************************************************************************
92  bool empty() const
93  {
94  return in == out;
95  }
96 
97  //*************************************************************************
98  bool full() const
99  {
100  return (in + 1U) % BUFFER_SIZE == out;
101  }
102 
103  //*************************************************************************
104  size_type available() const
105  {
106  return max_size() - size();
107  }
108 
109  //*************************************************************************
110  size_type max_size() const
111  {
112  return BUFFER_SIZE - 1U;
113  }
114 
115  //*************************************************************************
116  size_type capacity() const
117  {
118  return BUFFER_SIZE - 1U;
119  }
120 
121  protected:
122 
123  //*************************************************************************
124  circular_buffer_base(size_type BUFFER_SIZE_)
125  : BUFFER_SIZE(BUFFER_SIZE_)
126  , in(0U)
127  , out(0U)
128  {
129  }
130 
131  const size_type BUFFER_SIZE;
135  };
136 
137  //***************************************************************************
139  //***************************************************************************
140  template <typename T>
142  {
143  public:
144 
145  typedef T value_type;
146  typedef T& reference;
147  typedef const T& const_reference;
148 #if ETL_CPP11_SUPPORTED
149  typedef T&& rvalue_reference;
150 #endif
151  typedef T* pointer;
152  typedef const T* const_pointer;
153 
154  typedef typename etl::iterator_traits<pointer>::difference_type difference_type;
155 
156  //*************************************************************************
158  //*************************************************************************
159  class iterator : public etl::iterator<ETL_OR_STD::random_access_iterator_tag, T>
160  {
161  public:
162 
163  friend class icircular_buffer;
164 
165  //*************************************************************************
167  //*************************************************************************
169  : picb(ETL_NULLPTR)
170  , current(0U)
171  {
172  }
173 
174  //*************************************************************************
176  //*************************************************************************
177  iterator(const iterator& other)
178  : picb(other.picb)
179  , current(other.current)
180  {
181  }
182 
183  //*************************************************************************
185  //*************************************************************************
186  iterator& operator =(const iterator& other)
187  {
188  picb = other.picb;
189  current = other.current;
190 
191  return *this;
192  }
193 
194  //*************************************************************************
196  //*************************************************************************
197  reference operator *()
198  {
199  return picb->pbuffer[current];
200  }
201 
202  //*************************************************************************
204  //*************************************************************************
205  const_reference operator *() const
206  {
207  return picb->pbuffer[current];
208  }
209 
210  //*************************************************************************
212  //*************************************************************************
213  pointer operator ->()
214  {
215  return picb->pbuffer[current];
216  }
217 
218  //*************************************************************************
220  //*************************************************************************
221  const_pointer operator ->() const
222  {
223  return picb->pbuffer[current];
224  }
225 
226  //*************************************************************************
228  //*************************************************************************
230  {
231  ++current;
232 
233  // Did we reach the end of the buffer?
234  if (current == picb->BUFFER_SIZE)
235  {
236  current = 0U;
237  }
238 
239  return (*this);
240  }
241 
242  //*************************************************************************
244  //*************************************************************************
246  {
247  iterator original(*this);
248 
249  ++(*this);
250 
251  return (original);
252  }
253 
254  //*************************************************************************
256  //*************************************************************************
258  {
259  // Are we at the end of the buffer?
260  if (current == 0U)
261  {
262  current = picb->BUFFER_SIZE - 1;
263  }
264  else
265  {
266  --current;
267  }
268 
269  return (*this);
270  }
271 
272  //*************************************************************************
274  //*************************************************************************
276  {
277  iterator original(*this);
278 
279  --(*this);
280 
281  return (original);
282  }
283 
284  //*************************************************************************
286  //*************************************************************************
288  {
289  n = picb->BUFFER_SIZE + n;
290 
291  current += n;
292  current %= picb->BUFFER_SIZE;
293 
294  return (*this);
295  }
296 
297  //*************************************************************************
299  //*************************************************************************
301  {
302  return (this->operator+=(-n));
303  }
304 
305  //*************************************************************************
307  //*************************************************************************
308  friend iterator operator +(const iterator& lhs, int n)
309  {
310  iterator temp = lhs;
311 
312  temp += n;
313 
314  return temp;
315  }
316 
317  //*************************************************************************
319  //*************************************************************************
320  friend iterator operator -(const iterator& lhs, int n)
321  {
322  iterator temp = lhs;
323 
324  temp -= n;
325 
326  return temp;
327  }
328 
329  //*************************************************************************
331  //*************************************************************************
332  friend bool operator == (const iterator& lhs, const iterator& rhs)
333  {
334  return (lhs.current == rhs.current);
335  }
336 
337  //*************************************************************************
339  //*************************************************************************
340  friend bool operator != (const iterator& lhs, const iterator& rhs)
341  {
342  return !(lhs == rhs);
343  }
344 
345  //***************************************************
346  friend bool operator < (const iterator& lhs, const iterator& rhs)
347  {
348  const difference_type lhs_index = lhs.get_index();
349  const difference_type rhs_index = rhs.get_index();
350  const difference_type reference_index = lhs.container().begin().get_index();
351  const size_t buffer_size = lhs.container().max_size() + 1;
352 
353  const difference_type lhs_distance = (lhs_index < reference_index) ? buffer_size + lhs_index - reference_index : lhs_index - reference_index;
354  const difference_type rhs_distance = (rhs_index < reference_index) ? buffer_size + rhs_index - reference_index : rhs_index - reference_index;
355 
356  return lhs_distance < rhs_distance;
357  }
358 
359  //***************************************************
360  friend bool operator <= (const iterator& lhs, const iterator& rhs)
361  {
362  return !(lhs > rhs);
363  }
364 
365  //***************************************************
366  friend bool operator > (const iterator& lhs, const iterator& rhs)
367  {
368  return (rhs < lhs);
369  }
370 
371  //***************************************************
372  friend bool operator >= (const iterator& lhs, const iterator& rhs)
373  {
374  return !(lhs < rhs);
375  }
376 
377  //***************************************************
378  difference_type get_index() const
379  {
380  return current;
381  }
382 
383  //***************************************************
384  const icircular_buffer& container() const
385  {
386  return *picb;
387  }
388 
389  //***************************************************
390  pointer get_buffer() const
391  {
392  return pbuffer;
393  }
394 
395  protected:
396 
397  //***************************************************
398  difference_type distance(difference_type firstIndex, difference_type index) const
399  {
400  if (index < firstIndex)
401  {
402  return picb->BUFFER_SIZE + current - firstIndex;
403  }
404  else
405  {
406  return index - firstIndex;
407  }
408  }
409 
410  //*************************************************************************
412  //*************************************************************************
413  iterator(const icircular_buffer<T>* picb_, size_type current_)
414  : picb(picb_)
415  , current(current_)
416  {
417  }
418 
419  private:
420 
421  const icircular_buffer<T>* picb;
422  size_type current;
423  };
424 
425  //*************************************************************************
427  //*************************************************************************
428  class const_iterator : public etl::iterator<ETL_OR_STD::random_access_iterator_tag, const T>
429  {
430  public:
431 
432  friend class icircular_buffer;
433 
434  //*************************************************************************
436  //*************************************************************************
438  : picb(ETL_NULLPTR)
439  , current(0U)
440  {
441  }
442 
443  //*************************************************************************
445  //*************************************************************************
447  : picb(other.picb)
448  , current(other.current)
449  {
450  }
451 
452  //*************************************************************************
454  //*************************************************************************
456  : picb(other.picb)
457  , current(other.current)
458  {
459  }
460 
461  //*************************************************************************
463  //*************************************************************************
465  {
466  picb = other.picb;
467  current = other.current;
468 
469  return *this;
470  }
471 
472  //*************************************************************************
474  //*************************************************************************
476  {
477  picb = other.picb;
478  current = other.current;
479 
480  return *this;
481  }
482 
483  //*************************************************************************
485  //*************************************************************************
486  const_reference operator *() const
487  {
488  return picb->pbuffer[current];
489  }
490 
491  //*************************************************************************
493  //*************************************************************************
494  const_pointer operator ->() const
495  {
496  return picb->pbuffer[current];
497  }
498 
499  //*************************************************************************
501  //*************************************************************************
503  {
504  ++current;
505 
506  // Did we reach the end of the buffer?
507  if (current == picb->BUFFER_SIZE)
508  {
509  current = 0U;
510  }
511 
512  return (*this);
513  }
514 
515  //*************************************************************************
517  //*************************************************************************
519  {
520  const_iterator original(*this);
521 
522  ++(*this);
523 
524  return (original);
525  }
526 
527  //*************************************************************************
529  //*************************************************************************
531  {
532  // Are we at the end of the buffer?
533  if (current == 0U)
534  {
535  current = picb->BUFFER_SIZE - 1;
536  }
537  else
538  {
539  --current;
540  }
541 
542  return (*this);
543  }
544 
545  //*************************************************************************
547  //*************************************************************************
549  {
550  const_iterator original(*this);
551 
552  --(*this);
553 
554  return (original);
555  }
556 
557  //*************************************************************************
559  //*************************************************************************
561  {
562  n = picb->BUFFER_SIZE + n;
563 
564  current += n;
565  current %= picb->BUFFER_SIZE;
566 
567  return (*this);
568  }
569 
570  //*************************************************************************
572  //*************************************************************************
574  {
575  return (this->operator+=(-n));
576  }
577 
578  //*************************************************************************
580  //*************************************************************************
581  friend const_iterator operator +(const const_iterator& lhs, int n)
582  {
583  const_iterator temp = lhs;
584 
585  temp += n;
586 
587  return temp;
588  }
589 
590  //*************************************************************************
592  //*************************************************************************
593  friend const_iterator operator -(const const_iterator& lhs, int n)
594  {
595  const_iterator temp = lhs;
596 
597  temp -= n;
598 
599  return temp;
600  }
601 
602  //*************************************************************************
604  //*************************************************************************
605  friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
606  {
607  return (lhs.current == rhs.current);
608  }
609 
610  //*************************************************************************
612  //*************************************************************************
613  friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
614  {
615  return !(lhs == rhs);
616  }
617 
618  //***************************************************
619  friend bool operator < (const const_iterator& lhs, const const_iterator& rhs)
620  {
621  const difference_type lhs_index = lhs.get_index();
622  const difference_type rhs_index = rhs.get_index();
623  const difference_type reference_index = lhs.container().begin().get_index();
624  const size_t buffer_size = lhs.container().max_size() + 1;
625 
626  const difference_type lhs_distance = (lhs_index < reference_index) ? buffer_size + lhs_index - reference_index : lhs_index - reference_index;
627  const difference_type rhs_distance = (rhs_index < reference_index) ? buffer_size + rhs_index - reference_index : rhs_index - reference_index;
628 
629  return lhs_distance < rhs_distance;
630  }
631 
632  //***************************************************
633  friend bool operator <= (const const_iterator& lhs, const const_iterator& rhs)
634  {
635  return !(lhs > rhs);
636  }
637 
638  //***************************************************
639  friend bool operator > (const const_iterator& lhs, const const_iterator& rhs)
640  {
641  return (rhs < lhs);
642  }
643 
644  //***************************************************
645  friend bool operator >= (const const_iterator& lhs, const const_iterator& rhs)
646  {
647  return !(lhs < rhs);
648  }
649 
650  //***************************************************
651  difference_type get_index() const
652  {
653  return current;
654  }
655 
656  //***************************************************
657  const icircular_buffer& container() const
658  {
659  return *picb;
660  }
661 
662  //***************************************************
663  pointer get_buffer() const
664  {
665  return pbuffer;
666  }
667 
668  protected:
669 
670  //*************************************************************************
672  //*************************************************************************
674  : picb(picb_)
675  , current(current_)
676  {
677  }
678 
679  private:
680 
681  const icircular_buffer<T>* picb;
682  size_type current;
683  };
684 
685  friend class iterator;
686  friend class const_iterator;
687 
689  typedef etl::reverse_iterator<const_iterator> const_reverse_iterator;
690 
691  //*************************************************************************
693  //*************************************************************************
695  {
696  return iterator(this, out);
697  }
698 
699  //*************************************************************************
701  //*************************************************************************
703  {
704  return const_iterator(this, out);
705  }
706 
707  //*************************************************************************
709  //*************************************************************************
711  {
712  return const_iterator(this, out);
713  }
714 
715  //*************************************************************************
717  //*************************************************************************
719  {
720  return iterator(this, in);
721  }
722 
723  //*************************************************************************
725  //*************************************************************************
727  {
728  return const_iterator(this, in);
729  }
730 
731  //*************************************************************************
733  //*************************************************************************
735  {
736  return const_iterator(this, in);
737  }
738 
739  //*************************************************************************
741  //*************************************************************************
743  {
744  return reverse_iterator(end());
745  }
746 
747  //*************************************************************************
749  //*************************************************************************
751  {
752  return const_reverse_iterator(end());
753  }
754 
755  //*************************************************************************
757  //*************************************************************************
759  {
760  return const_reverse_iterator(end());
761  }
762 
763  //*************************************************************************
765  //*************************************************************************
767  {
768  return reverse_iterator(begin());
769  }
770 
771  //*************************************************************************
773  //*************************************************************************
775  {
776  return const_reverse_iterator(begin());
777  }
778 
779  //*************************************************************************
781  //*************************************************************************
783  {
784  return const_reverse_iterator(begin());
785  }
786 
787  //*************************************************************************
790  //*************************************************************************
791  reference front()
792  {
793  ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
794 
795  return pbuffer[out];
796  }
797 
798  //*************************************************************************
801  //*************************************************************************
802  const_reference front() const
803  {
804  ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
805 
806  return pbuffer[out];
807  }
808 
809  //*************************************************************************
812  //*************************************************************************
813  reference back()
814  {
815  ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
816 
817  return pbuffer[in == 0U ? BUFFER_SIZE - 1 : in - 1U];
818  }
819 
820  //*************************************************************************
823  //*************************************************************************
824  const_reference back() const
825  {
826  ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
827 
828  return pbuffer[in == 0U ? BUFFER_SIZE - 1 : in - 1U];
829  }
830 
831  //*************************************************************************
833  //*************************************************************************
834  reference operator [](int index)
835  {
836  return pbuffer[(out + index) % BUFFER_SIZE];
837  }
838 
839  //*************************************************************************
842  //*************************************************************************
843  const_reference operator [](int index) const
844  {
845  return pbuffer[(out + index) % BUFFER_SIZE];
846  }
847 
848  //*************************************************************************
852  //*************************************************************************
853  void push(const_reference item)
854  {
855  ::new (&pbuffer[in]) T(item);
856  in = (in + 1U) % BUFFER_SIZE;
857 
858  // Did we catch up with the 'out' index?
859  if (in == out)
860  {
861  // Forget about the oldest one.
862  pbuffer[out].~T();
863  out = (out + 1U) % BUFFER_SIZE;
864  }
865  else
866  {
867  ETL_INCREMENT_DEBUG_COUNT;
868  }
869  }
870 
871 #if ETL_CPP11_SUPPORTED
872  //*************************************************************************
876  //*************************************************************************
877  void push(rvalue_reference item)
878  {
879  ::new (&pbuffer[in]) T(etl::move(item));
880  in = (in + 1U) % BUFFER_SIZE;
881 
882  // Did we catch up with the 'out' index?
883  if (in == out)
884  {
885  // Forget about the oldest item.
886  pbuffer[out].~T();
887  out = (out + 1U) % BUFFER_SIZE;
888  }
889  else
890  {
891  ETL_INCREMENT_DEBUG_COUNT;
892  }
893  }
894 #endif
895 
896  //*************************************************************************
898  //*************************************************************************
899  template <typename TIterator>
900  void push(TIterator first, const TIterator& last)
901  {
902  while (first != last)
903  {
904  push(*first++);
905  }
906  }
907 
908  //*************************************************************************
910  //*************************************************************************
911  void pop()
912  {
913  ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
914  pbuffer[out].~T();
915  out = (out + 1U) % BUFFER_SIZE;
916  ETL_DECREMENT_DEBUG_COUNT
917  }
918 
919  //*************************************************************************
921  //*************************************************************************
922  void pop(size_type n)
923  {
924  while (n-- != 0U)
925  {
926  pop();
927  }
928  }
929 
930  //*************************************************************************
932  //*************************************************************************
933  void clear()
934  {
935  if ETL_IF_CONSTEXPR(etl::is_trivially_destructible<T>::value)
936  {
937  in = 0U;
938  out = 0U;
939  ETL_RESET_DEBUG_COUNT
940  }
941  else
942  {
943  while (!empty())
944  {
945  pop();
946  }
947  }
948  }
949 
950  //*************************************************************************
952  //*************************************************************************
953  friend difference_type operator -(const iterator& lhs, const iterator& rhs)
954  {
955  return distance(rhs, lhs);
956  }
957 
958  //*************************************************************************
960  //*************************************************************************
961  friend difference_type operator -(const const_iterator& lhs, const const_iterator& rhs)
962  {
963  return distance(rhs, lhs);
964  }
965 
966  //*************************************************************************
968  //*************************************************************************
969  friend difference_type operator -(const reverse_iterator& lhs, const reverse_iterator& rhs)
970  {
971  return distance(lhs.base(), rhs.base());
972  }
973 
974  //*************************************************************************
976  //*************************************************************************
977  friend difference_type operator -(const const_reverse_iterator& lhs, const const_reverse_iterator& rhs)
978  {
979  return distance(lhs.base(), rhs.base());
980  }
981 
982  protected:
983 
984  //*************************************************************************
986  //*************************************************************************
987  icircular_buffer<T>(pointer pbuffer_, size_type max_length)
988  : circular_buffer_base(max_length + 1U)
989  , pbuffer(pbuffer_)
990  {
991  }
992 
993  //*************************************************************************
995  //*************************************************************************
996  template <typename TIterator1, typename TIterator2>
997  static difference_type distance(const TIterator1& range_begin, const TIterator2& range_end)
998  {
999  difference_type distance1 = distance(range_begin);
1000  difference_type distance2 = distance(range_end);
1001 
1002  return distance2 - distance1;
1003  }
1004 
1005  //*************************************************************************
1007  //*************************************************************************
1008  template <typename TIterator>
1009  static difference_type distance(const TIterator& other)
1010  {
1011  const difference_type index = other.get_index();
1012  const difference_type reference_index = other.container().out;
1013  const size_t buffer_size = other.container().BUFFER_SIZE;
1014 
1015  if (index < reference_index)
1016  {
1017  return buffer_size + index - reference_index;
1018  }
1019  else
1020  {
1021  return index - reference_index;
1022  }
1023  }
1024 
1025  pointer pbuffer;
1026 
1027  private:
1028 
1029  //*************************************************************************
1031  //*************************************************************************
1032 #if defined(ETL_POLYMORPHIC_CIRCULAR_BUFFER) || defined(ETL_POLYMORPHIC_CONTAINERS)
1033  public:
1034  virtual ~icircular_buffer()
1035  {
1036  }
1037 #else
1038  protected:
1040  {
1041  }
1042 #endif
1043  };
1044 
1045  //***************************************************************************
1048  //***************************************************************************
1049  template <typename T, size_t MAX_SIZE_>
1051  {
1052  public:
1053 
1054  ETL_STATIC_ASSERT((MAX_SIZE_ > 0U), "Zero capacity etl::circular_buffer is not valid");
1055 
1056  static ETL_CONSTANT typename icircular_buffer<T>::size_type MAX_SIZE = typename icircular_buffer<T>::size_type(MAX_SIZE_);
1057 
1058  //*************************************************************************
1060  //*************************************************************************
1062  : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1063  {
1064  }
1065 
1066  //*************************************************************************
1069  //*************************************************************************
1070  template <typename TIterator>
1071  circular_buffer(TIterator first, const TIterator& last)
1072  : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1073  {
1074  while (first != last)
1075  {
1076  this->push(*first++);
1077  }
1078  }
1079 
1080 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
1081  //*************************************************************************
1083  //*************************************************************************
1084  circular_buffer(std::initializer_list<T> init)
1085  : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1086  {
1087  this->push(init.begin(), init.end());
1088  }
1089 #endif
1090 
1091  //*************************************************************************
1093  //*************************************************************************
1095  : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1096  {
1097  if (this != &other)
1098  {
1099  this->push(other.begin(), other.end());
1100  }
1101  }
1102 
1103  //*************************************************************************
1105  //*************************************************************************
1107  {
1108  if (this != &other)
1109  {
1110  this->push(other.begin(), other.end());
1111  }
1112 
1113  return *this;
1114  }
1115 
1116 #if ETL_CPP11_SUPPORTED
1117  //*************************************************************************
1119  //*************************************************************************
1121  : icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
1122  {
1123  if (this != &other)
1124  {
1125  typename etl::icircular_buffer<T>::iterator itr = other.begin();
1126  while (itr != other.end())
1127  {
1128  this->push(etl::move(*itr));
1129  ++itr;
1130  }
1131  }
1132  }
1133 
1134  //*************************************************************************
1136  //*************************************************************************
1138  {
1139  if (this != &other)
1140  {
1141  for (typename etl::icircular_buffer<T>::const_iterator itr = other.begin(); itr != other.end(); ++itr)
1142  {
1143  this->push(etl::move(*itr));
1144  }
1145  }
1146 
1147  return *this;
1148  }
1149 
1150 #endif
1151 
1152  //*************************************************************************
1154  //*************************************************************************
1156  {
1157  this->clear();
1158  }
1159 
1160  private:
1161 
1164  };
1165 
1166  //***************************************************************************
1169  //***************************************************************************
1170  template <typename T>
1172  {
1173  public:
1174 
1175  //*************************************************************************
1177  //*************************************************************************
1178  circular_buffer_ext(void* buffer, size_t max_size)
1179  : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1180  {
1181  }
1182 
1183  //*************************************************************************
1186  //*************************************************************************
1187  template <typename TIterator>
1188  circular_buffer_ext(TIterator first, const TIterator& last, void* buffer, size_t max_size)
1189  : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1190  {
1191  while (first != last)
1192  {
1193  this->push(*first++);
1194  }
1195  }
1196 
1197 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
1198  //*************************************************************************
1200  //*************************************************************************
1201  circular_buffer_ext(std::initializer_list<T> init, void* buffer, size_t max_size)
1202  : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1203  {
1204  this->push(init.begin(), init.end());
1205  }
1206 #endif
1207 
1208  //*************************************************************************
1210  //*************************************************************************
1211  circular_buffer_ext(const circular_buffer_ext& other, void* buffer, size_t max_size)
1212  : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1213  {
1214  if (this != &other)
1215  {
1216  this->push(other.begin(), other.end());
1217  }
1218  }
1219 
1220  //*************************************************************************
1222  //*************************************************************************
1224  {
1225  if (this != &other)
1226  {
1227  this->push(other.begin(), other.end());
1228  }
1229 
1230  return *this;
1231  }
1232 
1233 #if ETL_CPP11_SUPPORTED
1234  //*************************************************************************
1236  //*************************************************************************
1237  circular_buffer_ext(circular_buffer_ext&& other, void* buffer, size_t max_size)
1238  : icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
1239  {
1240  if (this != &other)
1241  {
1242  typename etl::icircular_buffer<T>::iterator itr = other.begin();
1243  while (itr != other.end())
1244  {
1245  this->push(etl::move(*itr));
1246  ++itr;
1247  }
1248  }
1249  }
1250 
1251  //*************************************************************************
1253  //*************************************************************************
1255  {
1256  if (this != &other)
1257  {
1258  for (typename etl::icircular_buffer<T>::iterator itr = other.begin(); itr != other.end(); ++itr)
1259  {
1260  this->push(etl::move(*itr));
1261  }
1262  }
1263 
1264  return *this;
1265  }
1266 #endif
1267 
1268  //*************************************************************************
1270  //*************************************************************************
1272  {
1273  using ETL_OR_STD::swap; // Allow ADL
1274 
1275  swap(this->in, other.in);
1276  swap(this->out, other.out);
1277  swap(this->pbuffer, other.pbuffer);
1278  }
1279 
1280  //*************************************************************************
1282  //*************************************************************************
1284  {
1285  this->clear();
1286  }
1287  };
1288 
1289  //*************************************************************************
1291  //*************************************************************************
1292 #if ETL_CPP17_SUPPORTED
1293  template <typename T, typename... Ts>
1294  circular_buffer(T, Ts...)
1295  ->circular_buffer<etl::enable_if_t<(etl::is_same_v<T, Ts> && ...), T>, 1U + sizeof...(Ts)>;
1296 #endif
1297 
1298  //*************************************************************************
1300  //*************************************************************************
1301  template <typename T>
1303  {
1304  lhs.swap(rhs);
1305  }
1306 
1307  //*************************************************************************
1309  //*************************************************************************
1310  template <typename T>
1312  {
1313  return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
1314  }
1315 
1316  //*************************************************************************
1318  //*************************************************************************
1319  template <typename T>
1321  {
1322  return !(lhs == rhs);
1323  }
1324 }
1325 
1326 #undef ETL_FILE
1327 
1328 #endif
Definition: circular_buffer.h:79
size_t size_type
The type used for determining the size of queue.
Definition: circular_buffer.h:83
size_type out
Index to the next read.
Definition: circular_buffer.h:133
ETL_DECLARE_DEBUG_COUNT
Internal debugging.
Definition: circular_buffer.h:134
size_type in
Index to the next write.
Definition: circular_buffer.h:132
Empty exception for the circular_buffer.
Definition: circular_buffer.h:66
Exception for the circular_buffer.
Definition: circular_buffer.h:53
Definition: circular_buffer.h:1172
circular_buffer_ext(TIterator first, const TIterator &last, void *buffer, size_t max_size)
Definition: circular_buffer.h:1188
circular_buffer_ext & operator=(const circular_buffer_ext &other)
Assignment operator.
Definition: circular_buffer.h:1223
circular_buffer_ext(void *buffer, size_t max_size)
Constructor.
Definition: circular_buffer.h:1178
circular_buffer_ext(const circular_buffer_ext &other, void *buffer, size_t max_size)
Copy Constructor.
Definition: circular_buffer.h:1211
void swap(circular_buffer_ext &other)
Swap with another circular buffer.
Definition: circular_buffer.h:1271
~circular_buffer_ext()
Destructor.
Definition: circular_buffer.h:1283
Definition: circular_buffer.h:1051
circular_buffer(const circular_buffer &other)
Copy Constructor.
Definition: circular_buffer.h:1094
circular_buffer & operator=(const circular_buffer &other)
Assignment operator.
Definition: circular_buffer.h:1106
~circular_buffer()
Destructor.
Definition: circular_buffer.h:1155
circular_buffer(TIterator first, const TIterator &last)
Definition: circular_buffer.h:1071
circular_buffer()
Constructor.
Definition: circular_buffer.h:1061
Iterator iterating through the circular buffer.
Definition: circular_buffer.h:429
const_iterator()
Constructor.
Definition: circular_buffer.h:437
const_iterator(const icircular_buffer< T > *picb_, size_type current_)
Protected constructor. Only icircular_buffer can create one.
Definition: circular_buffer.h:673
const_iterator(const typename icircular_buffer::iterator &other)
Copy Constructor from iterator.
Definition: circular_buffer.h:446
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs)
Inequality operator.
Definition: circular_buffer.h:613
const_iterator & operator--()
Pre-decrement.
Definition: circular_buffer.h:530
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs)
Equality operator.
Definition: circular_buffer.h:605
const_iterator & operator=(const typename icircular_buffer::iterator &other)
Assignment operator.
Definition: circular_buffer.h:464
const_iterator(const const_iterator &other)
Copy Constructor from const iterator.
Definition: circular_buffer.h:455
const_iterator & operator+=(int n)
Add offset.
Definition: circular_buffer.h:560
const_reference operator*() const
Definition: circular_buffer.h:486
const_iterator & operator-=(int n)
Subtract offset.
Definition: circular_buffer.h:573
friend const_iterator operator-(const const_iterator &lhs, int n)
Subtract offset.
Definition: circular_buffer.h:593
const_iterator & operator++()
Pre-increment.
Definition: circular_buffer.h:502
const_pointer operator->() const
-> operator
Definition: circular_buffer.h:494
friend const_iterator operator+(const const_iterator &lhs, int n)
Add offset.
Definition: circular_buffer.h:581
Iterator iterating through the circular buffer.
Definition: circular_buffer.h:160
iterator & operator++()
Pre-increment.
Definition: circular_buffer.h:229
iterator(const icircular_buffer< T > *picb_, size_type current_)
Protected constructor. Only icircular_buffer can create one.
Definition: circular_buffer.h:413
friend bool operator==(const iterator &lhs, const iterator &rhs)
Equality operator.
Definition: circular_buffer.h:332
friend iterator operator-(const iterator &lhs, int n)
Subtract offset.
Definition: circular_buffer.h:320
friend iterator operator+(const iterator &lhs, int n)
Add offset.
Definition: circular_buffer.h:308
iterator & operator+=(int n)
Add offset.
Definition: circular_buffer.h:287
iterator()
Constructor.
Definition: circular_buffer.h:168
friend bool operator!=(const iterator &lhs, const iterator &rhs)
Inequality operator.
Definition: circular_buffer.h:340
iterator & operator=(const iterator &other)
Assignment operator.
Definition: circular_buffer.h:186
reference operator*()
Definition: circular_buffer.h:197
iterator & operator--()
Pre-decrement.
Definition: circular_buffer.h:257
pointer operator->()
-> operator
Definition: circular_buffer.h:213
iterator & operator-=(int n)
Subtract offset.
Definition: circular_buffer.h:300
iterator(const iterator &other)
Copy Constructor.
Definition: circular_buffer.h:177
Definition: circular_buffer.h:142
static difference_type distance(const TIterator1 &range_begin, const TIterator2 &range_end)
Measures the distance between two iterators.
Definition: circular_buffer.h:997
const_reverse_iterator rend() const
Gets a const reverse iterator to the end of the buffer.
Definition: circular_buffer.h:774
void pop()
pop
Definition: circular_buffer.h:911
reverse_iterator rend()
Gets a reverse iterator to the end of the buffer.
Definition: circular_buffer.h:766
reference operator[](int index)
Get a reference to the item.
Definition: circular_buffer.h:834
const_reverse_iterator rbegin() const
Gets a const reverse iterator to the start of the buffer.
Definition: circular_buffer.h:750
void push(TIterator first, const TIterator &last)
Push a buffer from an iterator range.
Definition: circular_buffer.h:900
friend difference_type operator-(const iterator &lhs, const iterator &rhs)
Definition: circular_buffer.h:953
const_iterator end() const
Gets a const iterator to the end of the buffer.
Definition: circular_buffer.h:726
const_reference back() const
Definition: circular_buffer.h:824
iterator end()
Gets an iterator to the end of the buffer.
Definition: circular_buffer.h:718
iterator begin()
Gets an iterator to the start of the buffer.
Definition: circular_buffer.h:694
const_iterator begin() const
Gets a const iterator to the start of the buffer.
Definition: circular_buffer.h:702
const_iterator cbegin() const
Gets a const iterator to the start of the buffer.
Definition: circular_buffer.h:710
const_reverse_iterator crend() const
Gets a const reverse iterator to the end of the buffer.
Definition: circular_buffer.h:782
reference front()
Definition: circular_buffer.h:791
void clear()
Clears the buffer.
Definition: circular_buffer.h:933
reference back()
Definition: circular_buffer.h:813
reverse_iterator rbegin()
Gets a reverse iterator to the start of the buffer.
Definition: circular_buffer.h:742
void pop(size_type n)
pop(n)
Definition: circular_buffer.h:922
void push(const_reference item)
Definition: circular_buffer.h:853
const_iterator cend() const
Gets a const iterator to the end of the buffer.
Definition: circular_buffer.h:734
const_reverse_iterator crbegin() const
Gets a const reverse iterator to the start of the buffer.
Definition: circular_buffer.h:758
static difference_type distance(const TIterator &other)
Measures the distance from the _begin iterator to the specified iterator.
Definition: circular_buffer.h:1009
~icircular_buffer()
Destructor.
Definition: circular_buffer.h:1039
const_reference front() const
Definition: circular_buffer.h:802
Definition: iterator.h:251
#define ETL_ASSERT(b, e)
Definition: error_handler.h:290
exception(string_type reason_, string_type file_, numeric_type line_)
Constructor.
Definition: exception.h:67
Definition: exception.h:47
is_trivially_destructible
Definition: type_traits_generator.h:1171
Definition: absolute.h:37
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:633
void swap(etl::circular_buffer_ext< T > &lhs, etl::circular_buffer_ext< T > &rhs)
Template deduction guides.
Definition: circular_buffer.h:1302
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:645
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:594
void swap(etl::array< T, SIZE > &lhs, etl::array< T, SIZE > &rhs)
Template deduction guides.
Definition: array.h:570
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:582
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:606
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:621
iterator
Definition: iterator.h:422