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