Arduino DLNA Server
List.h
Go to the documentation of this file.
1 #pragma once
2 #ifdef USE_INITIALIZER_LIST
3 #include "InitializerList.h"
4 #endif
5 #include <stddef.h>
6 #include <assert.h>
7 #include "Allocator.h"
8 
9 namespace tiny_dlna {
10 
18 template <class T>
19 class List {
20  public:
21  struct Node {
22  Node *next = nullptr;
23  Node *prior = nullptr;
24  T data;
25  };
26 
27  class Iterator {
28  public:
29  Iterator(Node *node) { this->node = node; }
30  inline Iterator operator++() {
31  if (node->next != nullptr) {
32  node = node->next;
33  is_eof = false;
34  } else
35  is_eof = true;
36  return *this;
37  }
38  inline Iterator operator++(int) { return ++*this; }
39  inline Iterator operator--() {
40  if (node->prior != nullptr) {
41  node = node->prior;
42  is_eof = false;
43  } else
44  is_eof = true;
45  return *this;
46  }
47  inline Iterator operator--(int) { return --*this; }
48  inline Iterator operator+(int offset) {
49  return getIteratorAtOffset(offset);
50  }
51  inline Iterator operator-(int offset) {
52  return getIteratorAtOffset(-offset);
53  }
54  inline bool operator==(Iterator it) { return node == it.get_node(); }
55  inline bool operator!=(Iterator it) { return node != it.get_node(); }
56  inline T &operator*() { return node->data; }
57  inline T *operator->() { return &(node->data); }
58  inline Node *get_node() { return node; }
59  inline operator bool() { return is_eof; }
60 
61  protected:
62  Node *node = nullptr;
63  bool is_eof = false;
64 
66  Node *tmp = node;
67  if (offset > 0) {
68  for (int j = 0; j < offset; j++) {
69  if (tmp->next == nullptr) {
70  return Iterator(tmp);
71  }
72  tmp = tmp->next;
73  }
74  } else if (offset < 0) {
75  for (int j = 0; j < -offset; j++) {
76  if (tmp->prior == nullptr) {
77  return Iterator(tmp);
78  }
79  tmp = tmp->prior;
80  }
81  }
82  Iterator it(tmp);
83  return it;
84  }
85  };
86 
88  List(Allocator &allocator = DefaultAllocator) {
89  p_allocator = &allocator;
90  link();
91  };
93  List(List &ref) = default;
94 
96  template <size_t N>
97  List(const T (&a)[N], Allocator &allocator = DefaultAllocator) {
98  p_allocator = &allocator;
99  link();
100  for (int i = 0; i < N; ++i) push_back(a[i]);
101  }
102 
103  ~List() { clear(); }
104 
105 #ifdef USE_INITIALIZER_LIST
106 
107  List(std::initializer_list<T> iniList) {
108  link();
109  for (auto &obj : iniList) push_back(obj);
110  }
111 #endif
112  bool swap(List<T> &ref) {
113  List<T> tmp(*this);
114  validate();
115 
116  first = ref.first;
117  last = ref.last;
119 
120  ref.first = tmp.first;
121  ref.last = tmp.last;
122  ref.record_count = tmp.record_count;
123 
124  validate();
125  return true;
126  }
127 
128  bool push_back(T data) {
129  Node *node = createNode();
130  if (node == nullptr) return false;
131  node->data = data;
132 
133  // update links
134  Node *old_last_prior = last.prior;
135  node->next = &last;
136  node->prior = old_last_prior;
137  old_last_prior->next = node;
138  last.prior = node;
139 
140  record_count++;
141  validate();
142  return true;
143  }
144 
145  bool push_front(T data) {
146  Node *node = createNode();
147  if (node == nullptr) return false;
148  node->data = data;
149 
150  // update links
151  Node *old_begin_next = first.next;
152  node->prior = &first;
153  node->next = old_begin_next;
154  old_begin_next->prior = node;
155  first.next = node;
156 
157  record_count++;
158  validate();
159  return true;
160  }
161 
162  bool insert(Iterator it, const T &data) {
163  Node *node = createNode();
164  if (node == nullptr) return false;
165  node->data = data;
166 
167  // update links
168  Node *current_node = it.get_node();
169  Node *prior = current_node->prior;
170 
171  prior->next = node;
172  current_node->prior = node;
173  node->prior = prior;
174  node->next = current_node;
175 
176  record_count++;
177  validate();
178  return true;
179  }
180 
181  bool pop_front() {
182  T tmp;
183  return pop_front(tmp);
184  }
185 
186  bool pop_back() {
187  T tmp;
188  return pop_back(tmp);
189  }
190 
191  bool pop_front(T &data) {
192  if (record_count == 0) return false;
193  // get data
194  Node *p_delete = firstDataNode();
195  Node *p_prior = p_delete->prior;
196  Node *p_next = p_delete->next;
197 
198  data = p_delete->data;
199 
200  // remove last node
201  p_prior->next = p_next;
202  p_next->prior = p_prior;
203 
204  deleteNode(p_delete);
205 
206  record_count--;
207 
208  validate();
209  return true;
210  }
211 
212  bool pop_back(T &data) {
213  if (record_count == 0) return false;
214  Node *p_delete = lastDataNode();
215  Node *p_prior = p_delete->prior;
216  Node *p_next = p_delete->next;
217 
218  // get data
219  data = p_delete->data;
220 
221  // remove last node
222  p_prior->next = p_next;
223  p_next->prior = p_prior;
224 
225  deleteNode(p_delete);
226 
227  record_count--;
228 
229  validate();
230  return true;
231  }
232 
233  bool erase(Iterator it) {
234  Node *p_delete = it.get_node();
235  // check for valid iterator
236  if (empty() || p_delete == &first || p_delete == &last) {
237  return false;
238  }
239  Node *p_prior = p_delete->prior;
240  Node *p_next = p_delete->next;
241 
242  // remove last node
243  p_prior->next = p_next;
244  p_next->prior = p_prior;
245 
246  deleteNode(p_delete);
247 
248  record_count--;
249  return true;
250  }
251 
253  Iterator it(firstDataNode());
254  return it;
255  }
256 
258  Iterator it(&last);
259  return it;
260  }
261 
263  Iterator it(lastDataNode());
264  return it;
265  }
266 
268  Iterator it(&first);
269  return it;
270  }
271 
272  size_t size() { return record_count; }
273 
274  bool empty() { return size() == 0; }
275 
276  bool clear() {
277  while (pop_front());
278  validate();
279  return true;
280  }
281 
282  inline T &operator[](int index) {
283  Node *n = firstDataNode();
284  for (int j = 0; j < index; j++) {
285  n = n->next;
286  if (n == nullptr) {
287  return last.data;
288  }
289  }
290  return n->data;
291  }
292 
293  void setAllocator(Allocator &allocator) { p_allocator = &allocator; }
294 
296  T &back() { return *rbegin(); }
297 
298  protected:
299  Node first; // empty dummy first node which which is always before the first
300  // data node
301  Node last; // empty dummy last node which which is always after the last data
302  // node
303  size_t record_count = 0;
304  Allocator *p_allocator = &DefaultAllocator;
305 
307 #if USE_ALLOCATOR
308  Node *node = (Node *)p_allocator->allocate(sizeof(Node)); // new Node();
309 #else
310  Node *node = new Node();
311 #endif
312  return node;
313  }
314 
315  void deleteNode(Node *p_delete) {
316 #if USE_ALLOCATOR
317  p_allocator->free(p_delete); // delete p_delete;
318 #else
319  delete p_delete;
320 #endif
321  }
322 
323  void link() {
324  first.next = &last;
325  last.prior = &first;
326  }
327 
328  Node *lastDataNode() { return last.prior; }
329  Node *firstDataNode() { return first.next; }
330 
331  void validate() {
332  assert(first.next != nullptr);
333  assert(last.prior != nullptr);
334  if (empty()) {
335  assert(first.next = &last);
336  assert(last.prior = &first);
337  }
338  }
339 };
340 
341 } // namespace tiny_dlna
Memory allocateator which uses malloc.
Definition: Allocator.h:21
virtual void * allocate(size_t size)
Allocates memory.
Definition: Allocator.h:61
virtual void free(void *memory)
frees memory
Definition: Allocator.h:77
Definition: List.h:27
bool operator==(Iterator it)
Definition: List.h:54
bool is_eof
Definition: List.h:63
Iterator operator++()
Definition: List.h:30
Iterator(Node *node)
Definition: List.h:29
Iterator operator-(int offset)
Definition: List.h:51
Iterator getIteratorAtOffset(int offset)
Definition: List.h:65
Iterator operator+(int offset)
Definition: List.h:48
T * operator->()
Definition: List.h:57
Node * get_node()
Definition: List.h:58
Node * node
Definition: List.h:62
bool operator!=(Iterator it)
Definition: List.h:55
Iterator operator--()
Definition: List.h:39
Iterator operator++(int)
Definition: List.h:38
T & operator*()
Definition: List.h:56
Iterator operator--(int)
Definition: List.h:47
Double linked list.
Definition: List.h:19
Iterator rend()
Definition: List.h:267
bool pop_back()
Definition: List.h:186
Iterator rbegin()
Definition: List.h:262
bool swap(List< T > &ref)
Definition: List.h:112
Node last
Definition: List.h:301
Node first
Definition: List.h:299
bool push_front(T data)
Definition: List.h:145
bool pop_back(T &data)
Definition: List.h:212
~List()
Definition: List.h:103
List(const T(&a)[N], Allocator &allocator=DefaultAllocator)
Constructor using array.
Definition: List.h:97
Iterator end()
Definition: List.h:257
bool clear()
Definition: List.h:276
size_t size()
Definition: List.h:272
Node * firstDataNode()
Definition: List.h:329
bool push_back(T data)
Definition: List.h:128
Node * createNode()
Definition: List.h:306
T & back()
Provides the last element.
Definition: List.h:296
void link()
Definition: List.h:323
size_t record_count
Definition: List.h:303
void deleteNode(Node *p_delete)
Definition: List.h:315
List(List &ref)=default
copy constructor
List(Allocator &allocator=DefaultAllocator)
Default constructor.
Definition: List.h:88
T & operator[](int index)
Definition: List.h:282
bool insert(Iterator it, const T &data)
Definition: List.h:162
Node * lastDataNode()
Definition: List.h:328
bool empty()
Definition: List.h:274
bool erase(Iterator it)
Definition: List.h:233
bool pop_front()
Definition: List.h:181
Allocator * p_allocator
Definition: List.h:304
bool pop_front(T &data)
Definition: List.h:191
void validate()
Definition: List.h:331
Iterator begin()
Definition: List.h:252
void setAllocator(Allocator &allocator)
Definition: List.h:293
Definition: Allocator.h:6
Definition: List.h:21
Node * prior
Definition: List.h:23
Node * next
Definition: List.h:22
T data
Definition: List.h:24