Embedded Template Library  1.0
list.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) 2014 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_LIST_INCLUDED
32 #define ETL_LIST_INCLUDED
33 
34 #include <stddef.h>
35 
36 #include "platform.h"
37 #include "algorithm.h"
38 #include "iterator.h"
39 #include "functional.h"
40 #include "container.h"
41 #include "pool.h"
42 #include "exception.h"
43 #include "error_handler.h"
44 #include "debug_count.h"
45 #include "nullptr.h"
46 #include "type_traits.h"
47 #include "algorithm.h"
48 #include "memory.h"
49 #include "iterator.h"
50 #include "static_assert.h"
51 #include "placement_new.h"
52 
53 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
54  #include <initializer_list>
55 #endif
56 
57 #include "private/minmax_push.h"
58 
59 #undef ETL_FILE
60 #define ETL_FILE "7"
61 
62 //*****************************************************************************
66 //*****************************************************************************
67 
68 namespace etl
69 {
70  //***************************************************************************
73  //***************************************************************************
74  class list_exception : public exception
75  {
76  public:
77 
78  list_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
79  : exception(reason_, file_name_, line_number_)
80  {
81  }
82  };
83 
84  //***************************************************************************
87  //***************************************************************************
88  class list_full : public list_exception
89  {
90  public:
91 
92  list_full(string_type file_name_, numeric_type line_number_)
93  : list_exception(ETL_ERROR_TEXT("list:full", ETL_FILE"A"), file_name_, line_number_)
94  {
95  }
96  };
97 
98  //***************************************************************************
101  //***************************************************************************
102  class list_empty : public list_exception
103  {
104  public:
105 
106  list_empty(string_type file_name_, numeric_type line_number_)
107  : list_exception(ETL_ERROR_TEXT("list:empty", ETL_FILE"B"), file_name_, line_number_)
108  {
109  }
110  };
111 
112  //***************************************************************************
115  //***************************************************************************
117  {
118  public:
119 
120  list_iterator(string_type file_name_, numeric_type line_number_)
121  : list_exception(ETL_ERROR_TEXT("list:iterator", ETL_FILE"C"), file_name_, line_number_)
122  {
123  }
124  };
125 
126  //***************************************************************************
129  //***************************************************************************
131  {
132  public:
133 
134  list_unsorted(string_type file_name_, numeric_type line_number_)
135  : list_exception(ETL_ERROR_TEXT("list:unsorted", ETL_FILE"D"), file_name_, line_number_)
136  {
137  }
138  };
139 
140  //***************************************************************************
143  //***************************************************************************
145  {
146  public:
147 
148  list_no_pool(string_type file_name_, numeric_type line_number_)
149  : list_exception(ETL_ERROR_TEXT("list:no pool", ETL_FILE"E"), file_name_, line_number_)
150  {
151  }
152  };
153 
154  //***************************************************************************
157  //***************************************************************************
158  class list_base
159  {
160  public:
161 
162  typedef size_t size_type;
163 
164  //*************************************************************************
166  //*************************************************************************
167  struct node_t
168  {
169  //***********************************************************************
171  //***********************************************************************
173  : previous(ETL_NULLPTR),
174  next(ETL_NULLPTR)
175  {
176  }
177 
178  //***********************************************************************
180  //***********************************************************************
181  inline void reverse()
182  {
183  using ETL_OR_STD::swap; // Allow ADL
184 
185  swap(previous, next);
186  }
187 
188  node_t* previous;
189  node_t* next;
190  };
191 
192  //*************************************************************************
194  //*************************************************************************
195  bool has_shared_pool() const
196  {
197  return pool_is_shared;
198  }
199 
200  //*************************************************************************
202  //*************************************************************************
203  void reverse()
204  {
205  if (is_trivial_list())
206  {
207  return;
208  }
209 
210  node_t* p_node = terminal_node.next;
211 
212  while (p_node != &terminal_node)
213  {
214  node_t* p_temp = p_node->previous;
215  p_node->previous = p_node->next;
216  p_node->next = p_temp;
217  p_node = p_node->previous;
218  }
219 
220  // Terminal node.
221  node_t* p_temp = p_node->previous;
222  p_node->previous = p_node->next;
223  p_node->next = p_temp;
224  }
225 
226  //*************************************************************************
228  //*************************************************************************
230  {
231  return MAX_SIZE;
232  }
233 
234  //*************************************************************************
236  //*************************************************************************
238  {
239  return MAX_SIZE;
240  }
241 
242  //*************************************************************************
244  //*************************************************************************
245  size_type size() const
246  {
247  if (has_shared_pool())
248  {
249  // We have to count what we actually own.
250  size_type count = 0U;
251 
252  node_t* p_node = terminal_node.next;
253 
254  while (p_node != &terminal_node)
255  {
256  ++count;
257  p_node = p_node->next;
258  }
259 
260  return count;
261  }
262  else
263  {
264  return p_node_pool->size();
265  }
266  }
267 
268  //*************************************************************************
270  //*************************************************************************
271  bool empty() const
272  {
273  return (terminal_node.next == &terminal_node);
274  }
275 
276  //*************************************************************************
278  //*************************************************************************
279  bool full() const
280  {
281  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
282  return p_node_pool->full();
283  }
284 
285  //*************************************************************************
288  //*************************************************************************
290  {
291  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
292  return p_node_pool->available();
293  }
294 
295  protected:
296 
297  //*************************************************************************
299  //*************************************************************************
300  bool is_trivial_list() const
301  {
302  return (size() < 2);
303  }
304 
305  //*************************************************************************
307  //*************************************************************************
309  {
310  return *terminal_node.next;
311  }
312 
313  //*************************************************************************
315  //*************************************************************************
316  const node_t& get_head() const
317  {
318  return *terminal_node.next;
319  }
320 
321  //*************************************************************************
323  //*************************************************************************
325  {
326  return *terminal_node.previous;
327  }
328 
329  //*************************************************************************
331  //*************************************************************************
332  const node_t& get_tail() const
333  {
334  return *terminal_node.previous;
335  }
336 
337  //*************************************************************************
339  //*************************************************************************
340  void insert_node(node_t& position, node_t& node)
341  {
342  // Connect to the list.
343  join(*position.previous, node);
344  join(node, position);
345  }
346 
347  //*************************************************************************
349  //*************************************************************************
350  void join(node_t& left, node_t& right)
351  {
352  left.next = &right;
353  right.previous = &left;
354  }
355 
356  //*************************************************************************
358  //*************************************************************************
359  explicit list_base(bool pool_is_shared_)
360  : p_node_pool(ETL_NULLPTR),
361  MAX_SIZE(0),
362  pool_is_shared(pool_is_shared_)
363  {
365  }
366 
367  //*************************************************************************
369  //*************************************************************************
370  list_base(etl::ipool& node_pool_, size_type max_size_, bool pool_is_shared_)
371  : p_node_pool(&node_pool_),
372  MAX_SIZE(max_size_),
373  pool_is_shared(pool_is_shared_)
374  {
376  }
377 
378  //*************************************************************************
380  //*************************************************************************
381  void set_node_pool(etl::ipool& node_pool_)
382  {
383  p_node_pool = &node_pool_;
385  }
386 
387  //*************************************************************************
389  //*************************************************************************
391  {
392  return p_node_pool;
393  }
394 
395  //*************************************************************************
397  //*************************************************************************
399  {
400  }
401 
406  ETL_DECLARE_DEBUG_COUNT
407  };
408 
409  //***************************************************************************
412  //***************************************************************************
413  template <typename T>
414  class ilist : public etl::list_base
415  {
416  public:
417 
418  typedef T value_type;
419  typedef T* pointer;
420  typedef const T* const_pointer;
421  typedef T& reference;
422  typedef const T& const_reference;
423 #if ETL_CPP11_SUPPORTED
424  typedef T&& rvalue_reference;
425 #endif
426  typedef size_t size_type;
427 
428  protected:
429 
430  typedef typename etl::parameter_type<T>::type parameter_t;
431 
432  //*************************************************************************
434  //*************************************************************************
435  struct data_node_t : public node_t
436  {
437  explicit data_node_t(const T& value_)
438  : value(value_)
439  {
440  }
441 
442  T value;
443  };
444 
445  private:
446 
447  //*************************************************************************
449  //*************************************************************************
450  static data_node_t* data_cast(node_t* p_node)
451  {
452  return reinterpret_cast<data_node_t*>(p_node);
453  }
454 
455  //*************************************************************************
457  //*************************************************************************
458  static data_node_t& data_cast(node_t& node)
459  {
460  return reinterpret_cast<data_node_t&>(node);
461  }
462 
463  //*************************************************************************
465  //*************************************************************************
466  static const data_node_t* data_cast(const node_t* p_node)
467  {
468  return reinterpret_cast<const data_node_t*>(p_node);
469  }
470 
471  //*************************************************************************
473  //*************************************************************************
474  static const data_node_t& data_cast(const node_t& node)
475  {
476  return reinterpret_cast<const data_node_t&>(node);
477  }
478 
479  public:
480 
481  //*************************************************************************
483  //*************************************************************************
484  class iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, T>
485  {
486  public:
487 
488  friend class ilist;
489  friend class const_iterator;
490 
491  iterator()
492  : p_node(ETL_NULLPTR)
493  {
494  }
495 
496  iterator(node_t& node)
497  : p_node(&node)
498  {
499  }
500 
501  iterator(const iterator& other)
502  : p_node(other.p_node)
503  {
504  }
505 
506  iterator& operator ++()
507  {
508  p_node = p_node->next;
509  return *this;
510  }
511 
512  iterator operator ++(int)
513  {
514  iterator temp(*this);
515  p_node = p_node->next;
516  return temp;
517  }
518 
519  iterator& operator --()
520  {
521  p_node = p_node->previous;
522  return *this;
523  }
524 
525  iterator operator --(int)
526  {
527  iterator temp(*this);
528  p_node = p_node->previous;
529  return temp;
530  }
531 
532  iterator& operator =(const iterator& other)
533  {
534  p_node = other.p_node;
535  return *this;
536  }
537 
538  reference operator *()
539  {
540  return ilist::data_cast(p_node)->value;
541  }
542 
543  const_reference operator *() const
544  {
545  return ilist::data_cast(p_node)->value;
546  }
547 
548  pointer operator &()
549  {
550  return &(ilist::data_cast(p_node)->value);
551  }
552 
553  const_pointer operator &() const
554  {
555  return &(ilist::data_cast(p_node)->value);
556  }
557 
558  pointer operator ->()
559  {
560  return &(ilist::data_cast(p_node)->value);
561  }
562 
563  const_pointer operator ->() const
564  {
565  return &(ilist::data_cast(p_node)->value);
566  }
567 
568  friend bool operator == (const iterator& lhs, const iterator& rhs)
569  {
570  return lhs.p_node == rhs.p_node;
571  }
572 
573  friend bool operator != (const iterator& lhs, const iterator& rhs)
574  {
575  return !(lhs == rhs);
576  }
577 
578  private:
579 
580  node_t* p_node;
581  };
582 
583  //*************************************************************************
585  //*************************************************************************
586  class const_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, const T>
587  {
588  public:
589 
590  friend class ilist;
591 
593  : p_node(ETL_NULLPTR)
594  {
595  }
596 
597  const_iterator(node_t& node)
598  : p_node(&node)
599  {
600  }
601 
602  const_iterator(const node_t& node)
603  : p_node(&node)
604  {
605  }
606 
607  const_iterator(const typename ilist::iterator& other)
608  : p_node(other.p_node)
609  {
610  }
611 
612  const_iterator(const const_iterator& other)
613  : p_node(other.p_node)
614  {
615  }
616 
617  const_iterator& operator ++()
618  {
619  p_node = p_node->next;
620  return *this;
621  }
622 
623  const_iterator operator ++(int)
624  {
625  const_iterator temp(*this);
626  p_node = p_node->next;
627  return temp;
628  }
629 
630  const_iterator& operator --()
631  {
632  p_node = p_node->previous;
633  return *this;
634  }
635 
636  const_iterator operator --(int)
637  {
638  const_iterator temp(*this);
639  p_node = p_node->previous;
640  return temp;
641  }
642 
643  const_iterator& operator =(const const_iterator& other)
644  {
645  p_node = other.p_node;
646  return *this;
647  }
648 
649  const_reference operator *() const
650  {
651  return ilist::data_cast(p_node)->value;
652  }
653 
654  const_pointer operator &() const
655  {
656  return &(ilist::data_cast(p_node)->value);
657  }
658 
659  const_pointer operator ->() const
660  {
661  return &(ilist::data_cast(p_node)->value);
662  }
663 
664  friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
665  {
666  return lhs.p_node == rhs.p_node;
667  }
668 
669  friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
670  {
671  return !(lhs == rhs);
672  }
673 
674  private:
675 
676  const node_t* p_node;
677  };
678 
679  typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
680 
681  typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
682  typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
683 
684  //*************************************************************************
686  //*************************************************************************
688  {
689  return iterator(get_head());
690  }
691 
692  //*************************************************************************
694  //*************************************************************************
696  {
697  return const_iterator(get_head());
698  }
699 
700  //*************************************************************************
702  //*************************************************************************
704  {
705  return iterator(terminal_node);
706  }
707 
708  //*************************************************************************
710  //*************************************************************************
712  {
713  return const_iterator(static_cast<const data_node_t&>(terminal_node));
714  }
715 
716  //*************************************************************************
718  //*************************************************************************
720  {
721  return const_iterator(get_head());
722  }
723 
724  //*************************************************************************
726  //*************************************************************************
728  {
729  return const_iterator(static_cast<const data_node_t&>(terminal_node));
730  }
731 
732  //*************************************************************************
734  //*************************************************************************
735  reverse_iterator rbegin()
736  {
737  return reverse_iterator(terminal_node);
738  }
739 
740  //*************************************************************************
742  //*************************************************************************
743  const_reverse_iterator rbegin() const
744  {
745  return const_reverse_iterator(static_cast<const data_node_t&>(terminal_node));
746  }
747 
748  //*************************************************************************
750  //*************************************************************************
751  reverse_iterator rend()
752  {
753  return reverse_iterator(get_head());
754  }
755 
756  //*************************************************************************
758  //*************************************************************************
759  const_reverse_iterator rend() const
760  {
761  return const_reverse_iterator(get_head());
762  }
763 
764  //*************************************************************************
766  //*************************************************************************
767  const_reverse_iterator crbegin() const
768  {
769  return const_reverse_iterator(static_cast<const data_node_t&>(terminal_node));
770  }
771 
772  //*************************************************************************
774  //*************************************************************************
775  const_reverse_iterator crend() const
776  {
777  return const_reverse_iterator(get_head());
778  }
779 
780  //*************************************************************************
782  //*************************************************************************
783  reference front()
784  {
785  return data_cast(get_head()).value;
786  }
787 
788  //*************************************************************************
790  //*************************************************************************
791  const_reference front() const
792  {
793  return data_cast(get_head()).value;
794  }
795 
796  //*************************************************************************
798  //*************************************************************************
799  reference back()
800  {
801  return data_cast(get_tail()).value;
802  }
803 
804  //*************************************************************************
806  //*************************************************************************
807  const_reference back() const
808  {
809  return data_cast(get_tail()).value;
810  }
811 
812  //*************************************************************************
816  //*************************************************************************
817  template <typename TIterator>
818  void assign(TIterator first, TIterator last)
819  {
820 #if defined(ETL_DEBUG)
821  difference_type d = etl::distance(first, last);
822  ETL_ASSERT(d >= 0, ETL_ERROR(list_iterator));
823  ETL_ASSERT(size_t(d) <= MAX_SIZE, ETL_ERROR(list_full));
824 #endif
825  initialise();
826 
827  // Add all of the elements.
828  while (first != last)
829  {
830  data_node_t& node = allocate_data_node(*first);
831  join(get_tail(), node);
832  join(node, terminal_node);
833  ++first;
834  }
835  }
836 
837  //*************************************************************************
839  //*************************************************************************
840  void assign(size_t n, const T& value)
841  {
842 #if defined(ETL_DEBUG)
843  ETL_ASSERT(n <= available(), ETL_ERROR(list_full));
844 #endif
845 
846  initialise();
847 
848  // Add all of the elements.
849  while (n-- > 0)
850  {
851  data_node_t& node = allocate_data_node(value);
852  join(*terminal_node.previous, node);
853  join(node, terminal_node);
854  }
855  }
856 
857  //*************************************************************************
859  //*************************************************************************
860  void push_front(const T& value)
861  {
862 #if defined(ETL_CHECK_PUSH_POP)
863  ETL_ASSERT(!full(), ETL_ERROR(list_full));
864 #endif
865  insert_node(get_head(), allocate_data_node(value));
866  }
867 
868 #if ETL_CPP11_SUPPORTED
869  //*************************************************************************
871  //*************************************************************************
872  void push_front(rvalue_reference value)
873  {
874 #if defined(ETL_CHECK_PUSH_POP)
875  ETL_ASSERT(!full(), ETL_ERROR(list_full));
876 #endif
877  insert_node(get_head(), allocate_data_node(etl::move(value)));
878  }
879 #endif
880 
881 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT
882  //*************************************************************************
884  //*************************************************************************
885  template <typename ... Args>
886  void emplace_front(Args && ... args)
887  {
888 #if defined(ETL_CHECK_PUSH_POP)
889  ETL_ASSERT(!full(), ETL_ERROR(list_full));
890 #endif
891  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
892 
893  data_node_t* p_data_node = create_data_node();
894  ::new (&(p_data_node->value)) T(etl::forward<Args>(args)...);
895  ETL_INCREMENT_DEBUG_COUNT
896  insert_node(get_head(), *p_data_node);
897  }
898 #else
899  //*************************************************************************
901  //*************************************************************************
902  template <typename T1>
903  void emplace_front(const T1& value1)
904  {
905 #if defined(ETL_CHECK_PUSH_POP)
906  ETL_ASSERT(!full(), ETL_ERROR(list_full));
907 #endif
908  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
909 
910  data_node_t* p_data_node = create_data_node();
911  ::new (&(p_data_node->value)) T(value1);
912  ETL_INCREMENT_DEBUG_COUNT
913  insert_node(get_head(), *p_data_node);
914  }
915 
916  //*************************************************************************
918  //*************************************************************************
919  template <typename T1, typename T2>
920  void emplace_front(const T1& value1, const T2& value2)
921  {
922 #if defined(ETL_CHECK_PUSH_POP)
923  ETL_ASSERT(!full(), ETL_ERROR(list_full));
924 #endif
925  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
926 
927  data_node_t* p_data_node = create_data_node();
928  ::new (&(p_data_node->value)) T(value1, value2);
929  ETL_INCREMENT_DEBUG_COUNT
930  insert_node(get_head(), *p_data_node);
931  }
932 
933  //*************************************************************************
935  //*************************************************************************
936  template <typename T1, typename T2, typename T3>
937  void emplace_front(const T1& value1, const T2& value2, const T3& value3)
938  {
939 #if defined(ETL_CHECK_PUSH_POP)
940  ETL_ASSERT(!full(), ETL_ERROR(list_full));
941 #endif
942  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
943 
944  data_node_t* p_data_node = create_data_node();
945  ::new (&(p_data_node->value)) T(value1, value2, value3);
946  ETL_INCREMENT_DEBUG_COUNT
947  insert_node(get_head(), *p_data_node);
948  }
949 
950  //*************************************************************************
952  //*************************************************************************
953  template <typename T1, typename T2, typename T3, typename T4>
954  void emplace_front(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
955  {
956 #if defined(ETL_CHECK_PUSH_POP)
957  ETL_ASSERT(!full(), ETL_ERROR(list_full));
958 #endif
959  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
960 
961  data_node_t* p_data_node = create_data_node();
962  ::new (&(p_data_node->value)) T(value1, value2, value3, value4);
963  ETL_INCREMENT_DEBUG_COUNT
964  insert_node(get_head(), *p_data_node);
965  }
966 #endif
967 
968  //*************************************************************************
970  //*************************************************************************
971  void pop_front()
972  {
973 #if defined(ETL_CHECK_PUSH_POP)
974  ETL_ASSERT(!empty(), ETL_ERROR(list_empty));
975 #endif
976  node_t& node = get_head();
977  remove_node(node);
978  }
979 
980  //*************************************************************************
982  //*************************************************************************
983  void push_back(const T& value)
984  {
985 #if defined(ETL_CHECK_PUSH_POP)
986  ETL_ASSERT(!full(), ETL_ERROR(list_full));
987 #endif
988  insert_node(terminal_node, allocate_data_node(value));
989  }
990 
991 #if ETL_CPP11_SUPPORTED
992  //*************************************************************************
994  //*************************************************************************
995  void push_back(rvalue_reference value)
996  {
997 #if defined(ETL_CHECK_PUSH_POP)
998  ETL_ASSERT(!full(), ETL_ERROR(list_full));
999 #endif
1000  insert_node(terminal_node, allocate_data_node(etl::move(value)));
1001  }
1002 #endif
1003 
1004  //*************************************************************************
1006  //*************************************************************************
1007 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT
1008  template <typename ... Args>
1009  void emplace_back(Args && ... args)
1010  {
1011 #if defined(ETL_CHECK_PUSH_POP)
1012  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1013 #endif
1014  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1015 
1016  data_node_t* p_data_node = create_data_node();
1017  ::new (&(p_data_node->value)) T(etl::forward<Args>(args)...);
1018  ETL_INCREMENT_DEBUG_COUNT
1019  insert_node(terminal_node, *p_data_node);
1020  }
1021 #else
1022  template <typename T1>
1023  void emplace_back(const T1& value1)
1024  {
1025 #if defined(ETL_CHECK_PUSH_POP)
1026  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1027 #endif
1028  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1029 
1030  data_node_t* p_data_node = create_data_node();
1031  ::new (&(p_data_node->value)) T(value1);
1032  ETL_INCREMENT_DEBUG_COUNT
1033  insert_node(terminal_node, *p_data_node);
1034  }
1035 
1036  template <typename T1, typename T2>
1037  void emplace_back(const T1& value1, const T2& value2)
1038  {
1039 #if defined(ETL_CHECK_PUSH_POP)
1040  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1041 #endif
1042  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1043 
1044  data_node_t* p_data_node = create_data_node();
1045  ::new (&(p_data_node->value)) T(value1, value2);
1046  ETL_INCREMENT_DEBUG_COUNT
1047  insert_node(terminal_node, *p_data_node);
1048  }
1049 
1050  template <typename T1, typename T2, typename T3>
1051  void emplace_back(const T1& value1, const T2& value2, const T3& value3)
1052  {
1053 #if defined(ETL_CHECK_PUSH_POP)
1054  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1055 #endif
1056  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1057 
1058  data_node_t* p_data_node = create_data_node();
1059  ::new (&(p_data_node->value)) T(value1, value2, value3);
1060  ETL_INCREMENT_DEBUG_COUNT
1061  insert_node(terminal_node, *p_data_node);
1062  }
1063 
1064  template <typename T1, typename T2, typename T3, typename T4>
1065  void emplace_back(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
1066  {
1067 #if defined(ETL_CHECK_PUSH_POP)
1068  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1069 #endif
1070  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1071 
1072  data_node_t* p_data_node = create_data_node();
1073  ::new (&(p_data_node->value)) T(value1, value2, value3, value4);
1074  ETL_INCREMENT_DEBUG_COUNT
1075  insert_node(terminal_node, *p_data_node);
1076  }
1077 #endif
1078 
1079  //*************************************************************************
1081  //*************************************************************************
1082  void pop_back()
1083  {
1084 #if defined(ETL_CHECK_PUSH_POP)
1085  ETL_ASSERT(!empty(), ETL_ERROR(list_empty));
1086 #endif
1087  node_t& node = get_tail();
1088  remove_node(node);
1089  }
1090 
1091  //*************************************************************************
1093  //*************************************************************************
1094  iterator insert(iterator position, const_reference value)
1095  {
1096  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1097 
1098  data_node_t& data_node = allocate_data_node(value);
1099  insert_node(*position.p_node, data_node);
1100 
1101  return iterator(data_node);
1102  }
1103 
1104 #if ETL_CPP11_SUPPORTED
1105  //*************************************************************************
1107  //*************************************************************************
1108  iterator insert(iterator position, rvalue_reference value)
1109  {
1110  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1111 
1112  data_node_t& data_node = allocate_data_node(etl::move(value));
1113  insert_node(*position.p_node, data_node);
1114 
1115  return iterator(data_node);
1116  }
1117 #endif
1118 
1119  //*************************************************************************
1121  //*************************************************************************
1122 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT
1123  template <typename ... Args>
1124  iterator emplace(iterator position, Args && ... args)
1125  {
1126  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1127  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1128 
1129  data_node_t* p_data_node = create_data_node();
1130  ::new (&(p_data_node->value)) T(etl::forward<Args>(args)...);
1131  ETL_INCREMENT_DEBUG_COUNT
1132  insert_node(*position.p_node, *p_data_node);
1133 
1134  return iterator(*p_data_node);
1135  }
1136 #else
1137  template <typename T1>
1138  iterator emplace(iterator position, const T1& value1)
1139  {
1140  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1141  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1142 
1143  data_node_t* p_data_node = create_data_node();
1144  ::new (&(p_data_node->value)) T(value1);
1145  ETL_INCREMENT_DEBUG_COUNT
1146  insert_node(*position.p_node, *p_data_node);
1147 
1148  return iterator(*p_data_node);
1149  }
1150 
1151  template <typename T1, typename T2>
1152  iterator emplace(iterator position, const T1& value1, const T2& value2)
1153  {
1154  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1155  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1156 
1157  data_node_t* p_data_node = create_data_node();
1158  ::new (&(p_data_node->value)) T(value1, value2);
1159  ETL_INCREMENT_DEBUG_COUNT
1160  insert_node(*position.p_node, *p_data_node);
1161 
1162  return iterator(*p_data_node);
1163  }
1164 
1165  template <typename T1, typename T2, typename T3>
1166  iterator emplace(iterator position, const T1& value1, const T2& value2, const T3& value3)
1167  {
1168  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1169  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1170 
1171  data_node_t* p_data_node = create_data_node();
1172  ::new (&(p_data_node->value)) T(value1, value2, value3);
1173  ETL_INCREMENT_DEBUG_COUNT
1174  insert_node(*position.p_node, *p_data_node);
1175 
1176  return iterator(*p_data_node);
1177  }
1178 
1179  template <typename T1, typename T2, typename T3, typename T4>
1180  iterator emplace(iterator position, const T1& value1, const T2& value2, const T3& value3, const T4& value4)
1181  {
1182  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1183  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1184 
1185  data_node_t* p_data_node = create_data_node();
1186  ::new (&(p_data_node->value)) T(value1, value2, value3, value4);
1187  ETL_INCREMENT_DEBUG_COUNT
1188  insert_node(*position.p_node, *p_data_node);
1189 
1190  return iterator(*p_data_node);
1191  }
1192 #endif
1193 
1194  //*************************************************************************
1196  //*************************************************************************
1197  void insert(iterator position, size_t n, const_reference value)
1198  {
1199  for (size_t i = 0; i < n; ++i)
1200  {
1201  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1202 
1203  // Set up the next free node and insert.
1204  insert_node(*position.p_node, allocate_data_node(value));
1205  }
1206  }
1207 
1208  //*************************************************************************
1210  //*************************************************************************
1211  template <typename TIterator>
1212  void insert(iterator position, TIterator first, TIterator last)
1213  {
1214  while (first != last)
1215  {
1216  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1217 
1218  // Set up the next free node and insert.
1219  insert_node(*position.p_node, allocate_data_node(*first++));
1220  }
1221  }
1222 
1223  //*************************************************************************
1225  //*************************************************************************
1227  {
1228  ++position;
1229  remove_node(*position.p_node->previous);
1230  return position;
1231  }
1232 
1233  //*************************************************************************
1235  //*************************************************************************
1237  {
1238  node_t* p_first = first.p_node;
1239  node_t* p_last = last.p_node;
1240  node_t* p_next;
1241 
1242  // Join the ends.
1243  join(*(p_first->previous), *p_last);
1244 
1245  // Erase the ones in between.
1246  while (p_first != p_last)
1247  {
1248  p_next = p_first->next; // Remember the next node.
1249  destroy_data_node(static_cast<data_node_t&>(*p_first)); // Destroy the current node.
1250  p_first = p_next; // Move to the next node.
1251  }
1252 
1253  return last;
1254  }
1255 
1256  //*************************************************************************
1258  //*************************************************************************
1259  void resize(size_t n)
1260  {
1261  resize(n, T());
1262  }
1263 
1264  //*************************************************************************
1266  //*************************************************************************
1267  void resize(size_t n, const_reference value)
1268  {
1269  ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(list_full));
1270 
1271  // Zero?
1272  if (n == 0U)
1273  {
1274  clear();
1275  }
1276  // Smaller?
1277  else if (n < size())
1278  {
1279  iterator i_start = end();
1280  etl::advance(i_start, -difference_type(size() - n));
1281  erase(i_start, end());
1282  }
1283  // Larger?
1284  else if (n > size())
1285  {
1286  insert(end(), n - size(), value);
1287  }
1288  }
1289 
1290  //*************************************************************************
1292  //*************************************************************************
1293  void clear()
1294  {
1295  initialise();
1296  }
1297 
1298  //*************************************************************************
1299  // Removes the values specified.
1300  //*************************************************************************
1301  void remove(const_reference value)
1302  {
1303  iterator iValue = begin();
1304 
1305  while (iValue != end())
1306  {
1307  if (value == *iValue)
1308  {
1309  iValue = erase(iValue);
1310  }
1311  else
1312  {
1313  ++iValue;
1314  }
1315  }
1316  }
1317 
1318  //*************************************************************************
1320  //*************************************************************************
1321  template <typename TPredicate>
1322  void remove_if(TPredicate predicate)
1323  {
1324  iterator iValue = begin();
1325 
1326  while (iValue != end())
1327  {
1328  if (predicate(*iValue))
1329  {
1330  iValue = erase(iValue);
1331  }
1332  else
1333  {
1334  ++iValue;
1335  }
1336  }
1337  }
1338 
1339  //*************************************************************************
1342  //*************************************************************************
1343  void unique()
1344  {
1346  }
1347 
1348  //*************************************************************************
1351  //*************************************************************************
1352  template <typename TIsEqual>
1353  void unique(TIsEqual isEqual)
1354  {
1355  if (empty())
1356  {
1357  return;
1358  }
1359 
1360  iterator i_item = begin();
1361  ++i_item;
1362  iterator i_previous = begin();
1363 
1364  while (i_item != end())
1365  {
1366  if (isEqual(*i_previous, *i_item))
1367  {
1368  i_item = erase(i_item);
1369  }
1370  else
1371  {
1372  i_previous = i_item;
1373  ++i_item;
1374  }
1375  }
1376  }
1377 
1378  //*************************************************************************
1380  //*************************************************************************
1381  void splice(iterator to, ilist& other)
1382  {
1383  if (&other != this)
1384  {
1385  insert(to, other.begin(), other.end());
1386  other.erase(other.begin(), other.end());
1387  }
1388  }
1389 
1390 #if ETL_CPP11_SUPPORTED
1391  //*************************************************************************
1393  //*************************************************************************
1394  void splice(iterator to, ilist&& other)
1395  {
1396  if (&other != this)
1397  {
1398  typename ilist<T>::iterator itr = other.begin();
1399  while (itr != other.end())
1400  {
1401  to = insert(to, etl::move(*itr++));
1402  }
1403 
1404  other.erase(other.begin(), other.end());
1405  }
1406  }
1407 #endif
1408 
1409  //*************************************************************************
1411  //*************************************************************************
1412  void splice(iterator to, ilist& other, iterator from)
1413  {
1414  if (&other == this)
1415  {
1416  // Internal move.
1417  move(to, from);
1418  }
1419  else
1420  {
1421  // From another list.
1422  insert(to, *from);
1423  other.erase(from);
1424  }
1425  }
1426 
1427 #if ETL_CPP11_SUPPORTED
1428  //*************************************************************************
1430  //*************************************************************************
1431  void splice(iterator to, ilist&& other, iterator from)
1432  {
1433  if (&other == this)
1434  {
1435  // Internal move.
1436  move(to, from);
1437  }
1438  else
1439  {
1440  // From another list.
1441  insert(to, etl::move(*from));
1442  other.erase(from);
1443  }
1444  }
1445 #endif
1446 
1447  //*************************************************************************
1449  //*************************************************************************
1450  void splice(iterator to, ilist& other, iterator first, iterator last)
1451  {
1452  if (&other == this)
1453  {
1454  // Internal move.
1455  move(to, first, last);
1456  }
1457  else
1458  {
1459  // From another list.
1460  insert(to, first, last);
1461  other.erase(first, last);
1462  }
1463  }
1464 
1465 #if ETL_CPP11_SUPPORTED
1466  //*************************************************************************
1468  //*************************************************************************
1469  void splice(iterator to, ilist&& other, iterator first, iterator last)
1470  {
1471  if (&other == this)
1472  {
1473  // Internal move.
1474  move(to, first, last);
1475  }
1476  else
1477  {
1478  // From another list.
1479  ilist::iterator itr = first;
1480  while (itr != last)
1481  {
1482  to = insert(to, etl::move(*itr++));
1483  ++to;
1484  }
1485 
1486  other.erase(first, last);
1487  }
1488  }
1489 #endif
1490 
1491  //*************************************************************************
1493  //*************************************************************************
1494  void merge(ilist& other)
1495  {
1496  merge(other, etl::less<value_type>());
1497  }
1498 
1499  //*************************************************************************
1501  //*************************************************************************
1502  template <typename TCompare>
1503  void merge(ilist& other, TCompare compare)
1504  {
1505  if ((this != &other) && !other.empty())
1506  {
1507 #if defined(ETL_DEBUG)
1508  ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(list_unsorted));
1510 #endif
1511 
1512  ilist::iterator other_begin = other.begin();
1513  ilist::iterator other_end = other.end();
1514 
1515  ilist::iterator this_begin = begin();
1516  ilist::iterator this_end = end();
1517 
1518  while ((this_begin != this_end) && (other_begin != other_end))
1519  {
1520  // Find the place to insert.
1521  while ((this_begin != this_end) && !(compare(*other_begin, *this_begin)))
1522  {
1523  ++this_begin;
1524  }
1525 
1526  // Insert.
1527  if (this_begin != this_end)
1528  {
1529  while ((other_begin != other_end) && (compare(*other_begin, *this_begin)))
1530  {
1531  insert(this_begin, *other_begin);
1532  ++other_begin;
1533  }
1534  }
1535  }
1536 
1537  // Any left over?
1538  if ((this_begin == this_end) && (other_begin != other_end))
1539  {
1540  insert(this_end, other_begin, other_end);
1541  }
1542 
1543  other.clear();
1544  }
1545  }
1546 
1547 #if ETL_CPP11_SUPPORTED
1548  //*************************************************************************
1550  //*************************************************************************
1551  void merge(ilist&& other)
1552  {
1553  merge(etl::move(other), etl::less<value_type>());
1554  }
1555 
1556  //*************************************************************************
1558  //*************************************************************************
1559  template <typename TCompare>
1560  void merge(ilist&& other, TCompare compare)
1561  {
1562  if (!other.empty())
1563  {
1564 #if defined(ETL_DEBUG)
1565  ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(list_unsorted));
1566  ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(list_unsorted));
1567 #endif
1568 
1569  ilist::iterator other_begin = other.begin();
1570  ilist::iterator other_end = other.end();
1571 
1572  ilist::iterator this_begin = begin();
1573  ilist::iterator this_end = end();
1574 
1575  while ((this_begin != this_end) && (other_begin != other_end))
1576  {
1577  // Find the place to insert.
1578  while ((this_begin != this_end) && !(compare(*other_begin, *this_begin)))
1579  {
1580  ++this_begin;
1581  }
1582 
1583  // Insert.
1584  if (this_begin != this_end)
1585  {
1586  while ((other_begin != other_end) && (compare(*other_begin, *this_begin)))
1587  {
1588  insert(this_begin, etl::move(*other_begin));
1589  ++other_begin;
1590  }
1591  }
1592  }
1593 
1594  // Any left over?
1595  if ((this_begin == this_end) && (other_begin != other_end))
1596  {
1597  while (other_begin != other_end)
1598  {
1599  insert(this_end, etl::move(*other_begin++));
1600  }
1601  }
1602 
1603  other.clear();
1604  }
1605  }
1606 #endif
1607 
1608  //*************************************************************************
1611  //*************************************************************************
1612  void sort()
1613  {
1614  sort(etl::less<T>());
1615  }
1616 
1617  //*************************************************************************
1641  //*************************************************************************
1642  template <typename TCompare>
1643  void sort(TCompare compare)
1644  {
1645  iterator i_left;
1646  iterator i_right;
1647  iterator i_node;
1648  iterator i_head;
1649  iterator i_tail;
1650  int list_size = 1;
1651  int number_of_merges;
1652  int left_size;
1653  int right_size;
1654 
1655  if (is_trivial_list())
1656  {
1657  return;
1658  }
1659 
1660  while (true)
1661  {
1662  i_left = begin();
1663  i_head = end();
1664  i_tail = end();
1665 
1666  number_of_merges = 0; // Count the number of merges we do in this pass.
1667 
1668  while (i_left != end())
1669  {
1670  ++number_of_merges; // There exists a merge to be done.
1671  i_right = i_left;
1672  left_size = 0;
1673 
1674  // Step 'list_size' places along from left
1675  for (int i = 0; i < list_size; ++i)
1676  {
1677  ++left_size;
1678  ++i_right;
1679 
1680  if (i_right == end())
1681  {
1682  break;
1683  }
1684  }
1685 
1686  // If right hasn't fallen off end, we have two lists to merge.
1687  right_size = list_size;
1688 
1689  // Now we have two lists. Merge them.
1690  while (left_size > 0 || (right_size > 0 && i_right != end()))
1691  {
1692  // Decide whether the next node of merge comes from left or right.
1693  if (left_size == 0)
1694  {
1695  // Left is empty. The node must come from right.
1696  i_node = i_right++;
1697  --right_size;
1698  }
1699  else if (right_size == 0 || i_right == end())
1700  {
1701  // Right is empty. The node must come from left.
1702  i_node = i_left++;
1703  --left_size;
1704  }
1705  else if (!compare(*i_right, *i_left))
1706  {
1707  // First node of left is lower or same. The node must come from left.
1708  i_node = i_left++;
1709  --left_size;
1710  }
1711  else
1712  {
1713  // First node of right is lower. The node must come from right.
1714  i_node = i_right;
1715  ++i_right;
1716  --right_size;
1717  }
1718 
1719  // Add the next node to the merged head.
1720  if (i_head == end())
1721  {
1722  join(*i_head.p_node, *i_node.p_node);
1723  i_head = i_node;
1724  i_tail = i_node;
1725  }
1726  else
1727  {
1728  join(*i_tail.p_node, *i_node.p_node);
1729  i_tail = i_node;
1730  }
1731 
1732  join(*i_tail.p_node, terminal_node);
1733  }
1734 
1735  // Now left has stepped `list_size' places along, and right has too.
1736  i_left = i_right;
1737  }
1738 
1739  // If we have done only one merge, we're finished.
1740  if (number_of_merges <= 1) // Allow for number_of_merges == 0, the empty head case
1741  {
1742  return;
1743  }
1744 
1745  // Otherwise repeat, merging lists twice the size
1746  list_size *= 2;
1747  }
1748  }
1749 
1750  //*************************************************************************
1752  //*************************************************************************
1753  ilist& operator = (const ilist& rhs)
1754  {
1755  if (&rhs != this)
1756  {
1757  assign(rhs.cbegin(), rhs.cend());
1758  }
1759 
1760  return *this;
1761  }
1762 
1763 #if ETL_CPP11_SUPPORTED
1764  //*************************************************************************
1766  //*************************************************************************
1767  ilist& operator = (ilist&& rhs)
1768  {
1769  if (&rhs != this)
1770  {
1771  this->initialise();
1772 
1773  iterator itr = rhs.begin();
1774  while (itr != rhs.end())
1775  {
1776  push_back(etl::move(*itr));
1777  ++itr;
1778  }
1779 
1780  rhs.initialise();
1781  }
1782 
1783  return *this;
1784  }
1785 #endif
1786 
1787  protected:
1788 
1789  //*************************************************************************
1791  //*************************************************************************
1792  ilist(bool pool_is_shared_)
1793  : list_base(pool_is_shared_)
1794  {
1795  }
1796 
1797  //*************************************************************************
1799  //*************************************************************************
1800  ilist(etl::ipool& node_pool, size_t max_size_, bool pool_is_shared_)
1801  : list_base(node_pool, max_size_, pool_is_shared_)
1802  {
1803  }
1804 
1805  //*************************************************************************
1807  //*************************************************************************
1808  void initialise()
1809  {
1810  if (this->p_node_pool != ETL_NULLPTR)
1811  {
1812  if (!empty())
1813  {
1815  {
1816  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1818  ETL_RESET_DEBUG_COUNT;
1819  }
1820  else
1821  {
1822  node_t* p_first = terminal_node.next;
1823  node_t* p_last = &terminal_node;
1824 
1825  while (p_first != p_last)
1826  {
1827  destroy_data_node(static_cast<data_node_t&>(*p_first)); // Destroy the current node.
1828  p_first = p_first->next; // Move to the next node.
1829  }
1830  }
1831  }
1832  }
1833 
1835  }
1836 
1837 #if ETL_CPP11_SUPPORTED
1838  //*************************************************************************
1840  //*************************************************************************
1841  void move_container(ilist&& rhs)
1842  {
1843  if (&rhs != this)
1844  {
1845  this->initialise();
1846 
1847  if (!rhs.empty())
1848  {
1849  // Are we using the same pool?
1850  if (this->get_node_pool() == rhs.get_node_pool())
1851  {
1852  node_t* p_rhs_node = &rhs.get_head();
1853 
1854  // Just link the nodes to the new forward_list.
1855  do
1856  {
1857  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1858 
1859  node_t* p_node = p_rhs_node;
1860  p_rhs_node = p_rhs_node->next;
1861  insert_node(terminal_node, *p_node);
1862 
1863  ETL_INCREMENT_DEBUG_COUNT;
1864 
1865  } while (p_rhs_node != &rhs.terminal_node);
1866 
1867  ETL_OBJECT_RESET_DEBUG_COUNT(rhs);
1868  rhs.join(rhs.terminal_node, rhs.terminal_node);
1869  }
1870  else
1871  {
1872  // Add all of the elements.
1873  etl::ilist<T>::iterator first = rhs.begin();
1874  etl::ilist<T>::iterator last = rhs.end();
1875 
1876  while (first != last)
1877  {
1878  ETL_ASSERT(!full(), ETL_ERROR(list_full));
1879 
1880  insert_node(terminal_node, this->allocate_data_node(etl::move(*first++)));
1881  }
1882 
1883  rhs.initialise();
1884  }
1885  }
1886  }
1887  }
1888 #endif
1889 
1890  private:
1891 
1892  //*************************************************************************
1895  //*************************************************************************
1896  void move(iterator to, iterator from)
1897  {
1898  if (from == to)
1899  {
1900  return; // Can't more to before yourself!
1901  }
1902 
1903  node_t& from_node = *from.p_node;
1904  node_t& to_node = *to.p_node;
1905 
1906  // Disconnect the node from the list.
1907  join(*from_node.previous, *from_node.next);
1908 
1909  // Attach it to the new position.
1910  join(*to_node.previous, from_node);
1911  join(from_node, to_node);
1912  }
1913 
1914  //*************************************************************************
1917  //*************************************************************************
1918  void move(iterator to, iterator first, iterator last)
1919  {
1920  if ((first == to) || (last == to))
1921  {
1922  return; // Can't more to before yourself!
1923  }
1924 
1925 #if defined(ETL_DEBUG)
1926  // Check that we are not doing an illegal move!
1927  for (const_iterator item = first; item != last; ++item)
1928  {
1929  ETL_ASSERT(item != to, ETL_ERROR(list_iterator));
1930  }
1931 #endif
1932 
1933  node_t& first_node = *first.p_node;
1934  node_t& last_node = *last.p_node;
1935  node_t& to_node = *to.p_node;
1936  node_t& final_node = *last_node.previous;
1937 
1938  // Disconnect the range from the list.
1939  join(*first_node.previous, last_node);
1940 
1941  // Attach it to the new position.
1942  join(*to_node.previous, first_node);
1943  join(final_node, to_node);
1944  }
1945 
1946  //*************************************************************************
1948  //*************************************************************************
1949  void remove_node(node_t& node)
1950  {
1951  // Disconnect the node from the list.
1952  join(*node.previous, *node.next);
1953 
1954  // Destroy the pool object.
1955  destroy_data_node(static_cast<data_node_t&>(node));
1956  }
1957 
1958  //*************************************************************************
1960  //*************************************************************************
1961  data_node_t& allocate_data_node(const_reference value)
1962  {
1963  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1964 
1965  data_node_t* p_data_node = create_data_node();
1966  ::new (&(p_data_node->value)) T(value);
1967  ETL_INCREMENT_DEBUG_COUNT
1968 
1969  return *p_data_node;
1970  }
1971 
1972 #if ETL_CPP11_SUPPORTED
1973  //*************************************************************************
1975  //*************************************************************************
1976  data_node_t& allocate_data_node(rvalue_reference value)
1977  {
1978  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
1979 
1980  data_node_t* p_data_node = create_data_node();
1981  ::new (&(p_data_node->value)) T(etl::move(value));
1982  ETL_INCREMENT_DEBUG_COUNT
1983 
1984  return *p_data_node;
1985  }
1986 #endif
1987 
1988  //*************************************************************************
1990  //*************************************************************************
1991  data_node_t* create_data_node()
1992  {
1993  data_node_t* (etl::ipool::*func)() = &etl::ipool::allocate<data_node_t>;
1994  return (p_node_pool->*func)();
1995  }
1996 
1997  //*************************************************************************
1999  //*************************************************************************
2000  void destroy_data_node(data_node_t& node)
2001  {
2002  ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
2003  node.value.~T();
2004  p_node_pool->release(&node);
2005  ETL_DECREMENT_DEBUG_COUNT
2006  }
2007 
2008  // Disable copy construction.
2009  ilist(const ilist&);
2010 
2011 #if defined(ETL_POLYMORPHIC_LIST) || defined(ETL_POLYMORPHIC_CONTAINERS)
2012  public:
2013  virtual ~ilist()
2014  {
2015  }
2016 #else
2017  protected:
2018  ~ilist()
2019  {
2020  }
2021 #endif
2022  };
2023 
2024  //*************************************************************************
2026  //*************************************************************************
2027  template <typename T, const size_t MAX_SIZE_>
2028  class list : public etl::ilist<T>
2029  {
2030  public:
2031 
2032  ETL_STATIC_ASSERT((MAX_SIZE_ > 0U), "Zero capacity etl::list is not valid");
2033 
2034  static const size_t MAX_SIZE = MAX_SIZE_;
2035 
2036  public:
2037 
2038  typedef T value_type;
2039  typedef T* pointer;
2040  typedef const T* const_pointer;
2041  typedef T& reference;
2042  typedef const T& const_reference;
2043 #if ETL_CPP11_SUPPORTED
2044  typedef T&& rvalue_reference;
2045 #endif
2046  typedef size_t size_type;
2047 
2048  //*************************************************************************
2050  //*************************************************************************
2052  : etl::ilist<T>(node_pool, MAX_SIZE, false)
2053  {
2054  }
2055 
2056  //*************************************************************************
2058  //*************************************************************************
2060  {
2061  this->initialise();
2062  }
2063 
2064  //*************************************************************************
2066  //*************************************************************************
2067  explicit list(size_t initial_size)
2068  : etl::ilist<T>(node_pool, MAX_SIZE, false)
2069  {
2070  this->assign(initial_size, T());
2071  }
2072 
2073  //*************************************************************************
2075  //*************************************************************************
2076  list(size_t initial_size, const T& value)
2077  : etl::ilist<T>(node_pool, MAX_SIZE, false)
2078  {
2079  this->assign(initial_size, value);
2080  }
2081 
2082  //*************************************************************************
2084  //*************************************************************************
2085  list(const list& other)
2086  : etl::ilist<T>(node_pool, MAX_SIZE, false)
2087  {
2088  if (this != &other)
2089  {
2090  this->assign(other.cbegin(), other.cend());
2091  }
2092  }
2093 
2094 #if ETL_CPP11_SUPPORTED
2095  //*************************************************************************
2097  //*************************************************************************
2098  list(list&& other)
2099  : etl::ilist<T>(node_pool, MAX_SIZE, false)
2100  {
2101  if (this != &other)
2102  {
2103  this->initialise();
2104 
2105  typename etl::ilist<T>::iterator itr = other.begin();
2106  while (itr != other.end())
2107  {
2108  this->push_back(etl::move(*itr));
2109  ++itr;
2110  }
2111 
2112  other.initialise();
2113  }
2114  }
2115 #endif
2116 
2117  //*************************************************************************
2119  //*************************************************************************
2120  template <typename TIterator>
2121  list(TIterator first, TIterator last)
2122  : ilist<T>(node_pool, MAX_SIZE, false)
2123  {
2124  this->assign(first, last);
2125  }
2126 
2127 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
2128  //*************************************************************************
2130  //*************************************************************************
2131  list(std::initializer_list<T> init)
2132  : ilist<T>(node_pool, MAX_SIZE, false)
2133  {
2134  this->assign(init.begin(), init.end());
2135  }
2136 #endif
2137 
2138  //*************************************************************************
2140  //*************************************************************************
2141  list& operator = (const list& rhs)
2142  {
2143  if (&rhs != this)
2144  {
2145  this->assign(rhs.cbegin(), rhs.cend());
2146  }
2147 
2148  return *this;
2149  }
2150 
2151 #if ETL_CPP11_SUPPORTED
2152  //*************************************************************************
2154  //*************************************************************************
2155  list& operator = (list&& rhs)
2156  {
2157  this->move_container(etl::move(rhs));
2158 
2159  return *this;
2160  }
2161 #endif
2162 
2163  private:
2164 
2167  };
2168 
2169  //*************************************************************************
2171  //*************************************************************************
2172 #if ETL_CPP17_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
2173  template <typename T, typename... Ts>
2174  list(T, Ts...)
2175  ->list<etl::enable_if_t<(etl::is_same_v<T, Ts> && ...), T>, 1U + sizeof...(Ts)>;
2176 #endif
2177 
2178  //*************************************************************************
2180  //*************************************************************************
2181  template <typename T>
2182  class list_ext : public etl::ilist<T>
2183  {
2184  public:
2185 
2186  typedef T value_type;
2187  typedef T* pointer;
2188  typedef const T* const_pointer;
2189  typedef T& reference;
2190  typedef const T& const_reference;
2191  typedef size_t size_type;
2192 
2193  typedef typename etl::ilist<T>::data_node_t pool_type;
2194 
2195  //*************************************************************************
2197  //*************************************************************************
2199  : etl::ilist<T>(true)
2200  {
2201  }
2202 
2203  //*************************************************************************
2205  //*************************************************************************
2206  explicit list_ext(etl::ipool& node_pool)
2207  : etl::ilist<T>(node_pool, node_pool.max_size(), true)
2208  {
2209  }
2210 
2211  //*************************************************************************
2213  //*************************************************************************
2215  {
2216  this->initialise();
2217  }
2218 
2219  //*************************************************************************
2221  //*************************************************************************
2222  explicit list_ext(size_t initial_size, etl::ipool& node_pool)
2223  : etl::ilist<T>(node_pool, node_pool.max_size(), true)
2224  {
2225  this->assign(initial_size, T());
2226  }
2227 
2228  //*************************************************************************
2230  //*************************************************************************
2231  list_ext(size_t initial_size, const T& value, etl::ipool& node_pool)
2232  : etl::ilist<T>(node_pool, node_pool.max_size(), true)
2233  {
2234  this->assign(initial_size, value);
2235  }
2236 
2237  //*************************************************************************
2239  //*************************************************************************
2240  list_ext(const list_ext& other)
2241  : etl::ilist<T>(*other.p_node_pool, other.p_node_pool->max_size(), true)
2242  {
2243  if (this != &other)
2244  {
2245  this->assign(other.cbegin(), other.cend());
2246  }
2247  }
2248 
2249  //*************************************************************************
2251  //*************************************************************************
2252  list_ext(const list_ext& other, etl::ipool& node_pool)
2253  : etl::ilist<T>(node_pool, node_pool.max_size(), true)
2254  {
2255  if (this != &other)
2256  {
2257  this->assign(other.cbegin(), other.cend());
2258  }
2259  }
2260 
2261 #if ETL_CPP11_SUPPORTED
2262  //*************************************************************************
2264  //*************************************************************************
2265  list_ext(list_ext&& other)
2266  : etl::ilist<T>(*other.p_node_pool, other.p_node_pool->max_size(), true)
2267  {
2268  this->move_container(etl::move(other));
2269  }
2270 
2271  //*************************************************************************
2273  //*************************************************************************
2274  list_ext(list_ext&& other, etl::ipool& node_pool)
2275  : etl::ilist<T>(node_pool, node_pool.max_size(), true)
2276  {
2277  this->move_container(etl::move(other));
2278  }
2279 #endif
2280 
2281  //*************************************************************************
2283  //*************************************************************************
2284  template <typename TIterator>
2285  list_ext(TIterator first, TIterator last, etl::ipool& node_pool)
2286  : ilist<T>(node_pool, node_pool.max_size(), true)
2287  {
2288  this->assign(first, last);
2289  }
2290 
2291 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
2292  //*************************************************************************
2294  //*************************************************************************
2295  list_ext(std::initializer_list<T> init, etl::ipool& node_pool)
2296  : ilist<T>(node_pool, node_pool.max_size(), true)
2297  {
2298  this->assign(init.begin(), init.end());
2299  }
2300 #endif
2301 
2302  //*************************************************************************
2304  //*************************************************************************
2306  {
2307  if (&rhs != this)
2308  {
2309  this->assign(rhs.cbegin(), rhs.cend());
2310  }
2311 
2312  return *this;
2313  }
2314 
2315 #if ETL_CPP11_SUPPORTED
2316  //*************************************************************************
2318  //*************************************************************************
2319  list_ext& operator = (list_ext&& rhs)
2320  {
2321  this->move_container(etl::move(rhs));
2322 
2323  return *this;
2324  }
2325 #endif
2326 
2327  //*************************************************************************
2329  //*************************************************************************
2331  {
2332  // Clear the list of any current elements.
2333  if (this->get_node_pool() != ETL_NULLPTR)
2334  {
2335  this->clear();
2336  }
2337 
2338  this->set_node_pool(pool);
2339  }
2340 
2341  //*************************************************************************
2343  //*************************************************************************
2345  {
2346  return *this->p_node_pool;
2347  }
2348  };
2349 
2350  //*************************************************************************
2355  //*************************************************************************
2356  template <typename T>
2357  bool operator ==(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
2358  {
2359  return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
2360  }
2361 
2362  //*************************************************************************
2367  //*************************************************************************
2368  template <typename T>
2369  bool operator !=(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
2370  {
2371  return !(lhs == rhs);
2372  }
2373 
2374  //*************************************************************************
2380  //*************************************************************************
2381  template <typename T>
2382  bool operator <(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
2383  {
2384  return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
2385  }
2386 
2387  //*************************************************************************
2393  //*************************************************************************
2394  template <typename T>
2395  bool operator >(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
2396  {
2397  return (rhs < lhs);
2398  }
2399 
2400  //*************************************************************************
2406  //*************************************************************************
2407  template <typename T>
2408  bool operator <=(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
2409  {
2410  return !(lhs > rhs);
2411  }
2412 
2413  //*************************************************************************
2419  //*************************************************************************
2420  template <typename T>
2421  bool operator >=(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
2422  {
2423  return !(lhs < rhs);
2424  }
2425 }
2426 
2427 #include "private/minmax_pop.h"
2428 
2429 #undef ETL_FILE
2430 
2431 #endif
const_iterator
Definition: list.h:587
iterator.
Definition: list.h:485
Template deduction guides.
Definition: list.h:2183
list_ext(const list_ext &other, etl::ipool &node_pool)
Copy constructor. Explicit pool.
Definition: list.h:2252
list_ext(size_t initial_size, etl::ipool &node_pool)
Construct from size.
Definition: list.h:2222
list_ext(TIterator first, TIterator last, etl::ipool &node_pool)
Construct from range.
Definition: list.h:2285
void set_pool(etl::ipool &pool)
Set the pool instance.
Definition: list.h:2330
list_ext(size_t initial_size, const T &value, etl::ipool &node_pool)
Construct from size and value.
Definition: list.h:2231
list_ext()
Default constructor.
Definition: list.h:2198
etl::ipool & get_pool() const
Get the pool instance.
Definition: list.h:2344
list_ext(etl::ipool &node_pool)
Default constructor.
Definition: list.h:2206
~list_ext()
Destructor.
Definition: list.h:2214
list_ext(const list_ext &other)
Copy constructor. Implicit pool.
Definition: list.h:2240
A templated list implementation that uses a fixed size buffer.
Definition: list.h:2029
~list()
Destructor.
Definition: list.h:2059
list(const list &other)
Copy constructor.
Definition: list.h:2085
list(TIterator first, TIterator last)
Construct from range.
Definition: list.h:2121
list(size_t initial_size, const T &value)
Construct from size and value.
Definition: list.h:2076
list(size_t initial_size)
Construct from size.
Definition: list.h:2067
list()
Default constructor.
Definition: list.h:2051
ETL_NODISCARD bool is_sorted(TIterator begin, TIterator end)
Definition: algorithm.h:1923
bitset< MAXN > operator&(const bitset< MAXN > &lhs, const bitset< MAXN > &rhs)
Definition: bitset.h:1157
#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
ilist(etl::ipool &node_pool, size_t max_size_, bool pool_is_shared_)
Constructor.
Definition: list.h:1800
const_reverse_iterator rend() const
Gets the reverse end of the list.
Definition: list.h:759
void clear()
Clears the list.
Definition: list.h:1293
const_iterator cbegin() const
Gets the beginning of the list.
Definition: list.h:719
iterator end()
Gets the end of the list.
Definition: list.h:703
void push_back(const T &value)
Pushes a value to the back of the list.
Definition: list.h:983
void emplace_front(const T1 &value1, const T2 &value2)
Emplaces a value to the front of the list.
Definition: list.h:920
ilist(bool pool_is_shared_)
Constructor.
Definition: list.h:1792
reference back()
Gets a reference to the last element.
Definition: list.h:799
size_t size_type
The type used for determining the size of list.
Definition: list.h:162
void reverse()
Reverses the list.
Definition: list.h:203
const_reverse_iterator crend() const
Gets the reverse end of the list.
Definition: list.h:775
void insert(iterator position, size_t n, const_reference value)
Inserts 'n' copies of a value to the list at the specified position.
Definition: list.h:1197
iterator emplace(iterator position, const T1 &value1)
Emplaces a value to the list at the specified position.
Definition: list.h:1138
void splice(iterator to, ilist &other, iterator from)
Splices an element from another list to this.
Definition: list.h:1412
size_type size() const
Gets the size of the list.
Definition: list.h:245
void sort(TCompare compare)
Definition: list.h:1643
size_type available() const
Definition: list.h:289
void splice(iterator to, ilist &other, iterator first, iterator last)
Splices a range of elements from another list to this.
Definition: list.h:1450
void join(node_t &left, node_t &right)
Join two nodes.
Definition: list.h:350
void unique(TIsEqual isEqual)
Definition: list.h:1353
void assign(TIterator first, TIterator last)
Definition: list.h:818
const_reverse_iterator rbegin() const
Gets the reverse beginning of the list.
Definition: list.h:743
list_base(bool pool_is_shared_)
The constructor that is called from derived classes.
Definition: list.h:359
etl::ipool * p_node_pool
The pool of data nodes used in the list.
Definition: list.h:402
size_type max_size() const
Gets the maximum possible size of the list.
Definition: list.h:229
const node_t & get_head() const
Get the head node.
Definition: list.h:316
void resize(size_t n)
Resizes the list.
Definition: list.h:1259
list_base(etl::ipool &node_pool_, size_type max_size_, bool pool_is_shared_)
The constructor that is called from derived classes.
Definition: list.h:370
bool full() const
Checks to see if the list is full.
Definition: list.h:279
reverse_iterator rend()
Gets the reverse end of the list.
Definition: list.h:751
reverse_iterator rbegin()
Gets the reverse beginning of the list.
Definition: list.h:735
iterator insert(iterator position, const_reference value)
Inserts a value to the list at the specified position.
Definition: list.h:1094
size_type MAX_SIZE
The maximum size of the list.
Definition: list.h:404
node_t terminal_node
The node that acts as the list start and end.
Definition: list.h:403
void push_front(const T &value)
Pushes a value to the front of the list.
Definition: list.h:860
void initialise()
Initialise the list.
Definition: list.h:1808
bool pool_is_shared
If true then the pool is shared between lists.
Definition: list.h:405
void emplace_back(const T1 &value1)
Emplaces a value to the back of the list.
Definition: list.h:1023
void emplace_front(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Emplaces a value to the front of the list.
Definition: list.h:954
node_t & get_head()
Get the head node.
Definition: list.h:308
void splice(iterator to, ilist &other)
Splices from another list to this.
Definition: list.h:1381
const_iterator end() const
Gets the end of the list.
Definition: list.h:711
void emplace_front(const T1 &value1, const T2 &value2, const T3 &value3)
Emplaces a value to the front of the list.
Definition: list.h:937
etl::ipool * get_node_pool()
Get the node pool instance.
Definition: list.h:390
reference front()
Gets a reference to the first element.
Definition: list.h:783
void pop_front()
Removes a value from the front of the list.
Definition: list.h:971
const_iterator begin() const
Gets the beginning of the list.
Definition: list.h:695
void merge(ilist &other)
Merge another list into this one. Both lists should be sorted.
Definition: list.h:1494
bool is_trivial_list() const
Is the list a trivial length?
Definition: list.h:300
node_t & get_tail()
Get the tail node.
Definition: list.h:324
void assign(size_t n, const T &value)
Assigns 'n' copies of a value to the list.
Definition: list.h:840
void set_node_pool(etl::ipool &node_pool_)
Set the node pool instance.
Definition: list.h:381
iterator erase(iterator position)
Erases the value at the specified position.
Definition: list.h:1226
void emplace_front(const T1 &value1)
Emplaces a value to the front of the list.
Definition: list.h:903
void merge(ilist &other, TCompare compare)
Merge another list into this one. Both lists should be sorted.
Definition: list.h:1503
void resize(size_t n, const_reference value)
Resizes the list.
Definition: list.h:1267
size_type capacity() const
Gets the maximum possible size of the list.
Definition: list.h:237
ilist & operator=(const ilist &rhs)
Assignment operator.
Definition: list.h:1753
bool empty() const
Checks to see if the list is empty.
Definition: list.h:271
iterator begin()
Gets the beginning of the list.
Definition: list.h:687
iterator erase(iterator first, iterator last)
Erases a range of elements.
Definition: list.h:1236
void sort()
Definition: list.h:1612
const_reference back() const
Gets a reference to the last element.
Definition: list.h:807
void unique()
Definition: list.h:1343
const_reference front() const
Gets a const reference to the first element.
Definition: list.h:791
void insert(iterator position, TIterator first, TIterator last)
Inserts a range of values to the list at the specified position.
Definition: list.h:1212
void insert_node(node_t &position, node_t &node)
Insert a node before 'position'.
Definition: list.h:340
const_iterator cend() const
Gets the end of the list.
Definition: list.h:727
const_reverse_iterator crbegin() const
Gets the reverse beginning of the list.
Definition: list.h:767
const node_t & get_tail() const
Get the tail node.
Definition: list.h:332
~list_base()
Destructor.
Definition: list.h:398
void remove_if(TPredicate predicate)
Removes according to a predicate.
Definition: list.h:1322
bool has_shared_pool() const
true if the list has a shared pool.
Definition: list.h:195
void pop_back()
Removes a value from the back of the list.
Definition: list.h:1082
Definition: list.h:415
Definition: list.h:159
Definition: list.h:103
Definition: list.h:75
Definition: list.h:89
Definition: list.h:117
Definition: list.h:145
Definition: list.h:131
size_t size() const
Returns the number of allocated items in the pool.
Definition: pool.h:309
void release_all()
Release all objects in the pool.
Definition: pool.h:264
bool full() const
Definition: pool.h:327
size_t max_size() const
Returns the maximum number of items in the pool.
Definition: pool.h:285
void release(const void *const p_object)
Definition: pool.h:255
size_t available() const
Returns the number of free items in the pool.
Definition: pool.h:301
Definition: pool.h:118
Definition: pool.h:617
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
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
bool operator==(const etl::ilist< T > &lhs, const etl::ilist< T > &rhs)
Definition: list.h:2357
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::ilist< T > &lhs, const etl::ilist< T > &rhs)
Definition: list.h:2369
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
Definition: compare.h:52
Definition: functional.h:136
The data node element in the list.
Definition: list.h:436
iterator
Definition: iterator.h:422
Definition: functional.h:112
The node element in the list.
Definition: list.h:168
void reverse()
Reverses the previous & next pointers.
Definition: list.h:181
node_t()
Constructor.
Definition: list.h:172
etl::conditional< etl::is_fundamental< T >::value||etl::is_pointer< T >::value, T, const T & >::type type
By default fundamental and pointer types are passed by value.
Definition: parameter_type.h:48