arduino-audio-tools
Vector.h
1 #pragma once
2 #ifdef USE_INITIALIZER_LIST
3 #include "InitializerList.h"
4 #endif
5 #include <assert.h>
6 
7 #include "Allocator.h"
8 
9 namespace audio_tools {
10 
20 template <class T>
21 class Vector {
22  public:
29  class iterator {
30  protected:
31  T *ptr;
32  size_t pos_;
33 
34  public:
35  iterator() {}
36  iterator(T *parPtr, size_t pos) {
37  this->ptr = parPtr;
38  this->pos_ = pos;
39  }
40  // copy constructor
41  iterator(const iterator &copyFrom) {
42  ptr = copyFrom.ptr;
43  pos_ = copyFrom.pos_;
44  }
45  iterator operator++(int n) {
46  ptr++;
47  pos_++;
48  return *this;
49  }
50  iterator operator++() {
51  ptr++;
52  pos_++;
53  return *this;
54  }
55  iterator operator--(int n) {
56  ptr--;
57  pos_--;
58  return *this;
59  }
60  iterator operator--() {
61  ptr--;
62  pos_--;
63  return *this;
64  }
65  iterator operator+(int offset) {
66  pos_ += offset;
67  return iterator(ptr + offset, offset);
68  }
69  bool operator==(iterator it) { return ptr == it.getPtr(); }
70  bool operator<(iterator it) { return ptr < it.getPtr(); }
71  bool operator<=(iterator it) { return ptr <= it.getPtr(); }
72  bool operator>(iterator it) { return ptr > it.getPtr(); }
73  bool operator>=(iterator it) { return ptr >= it.getPtr(); }
74  bool operator!=(iterator it) { return ptr != it.getPtr(); }
75  T &operator*() { return *ptr; }
76  T *operator->() { return ptr; }
77  T *getPtr() { return ptr; }
78  size_t pos() { return pos_; }
79  size_t operator-(iterator it) { return (ptr - it.getPtr()); }
80  };
81 
82 #ifdef USE_INITIALIZER_LIST
83 
85  Vector(std::initializer_list<T> iniList) {
86  resize(iniList.size());
87  int pos = 0;
88  for (auto &obj : iniList) {
89  p_data[pos++] = obj;
90  }
91  }
92 
93 #endif
94 
96  Vector(size_t len = 0, Allocator &allocator = DefaultAllocator) {
97  setAllocator(allocator);
98  resize_internal(len, false, false);
99  }
100 
101 
103  Vector(Allocator &allocator) {
104  setAllocator(allocator);
105  }
106 
108  Vector(int size, T value, Allocator &allocator = DefaultAllocator) {
109  setAllocator(allocator);
110  resize(size);
111  for (int j = 0; j < size; j++) {
112  p_data[j] = value;
113  }
114  }
115 
117  Vector(Vector<T> &&moveFrom) {
118  swap(moveFrom);
119  moveFrom.clear();
120  };
121 
123  Vector &operator=(Vector &&moveFrom) {
124  swap(moveFrom);
125  moveFrom.clear();
126  return *this;
127  }
128 
130  Vector(Vector<T> &copyFrom) {
131  this->p_allocator = copyFrom.p_allocator;
132  resize_internal(copyFrom.size(), false);
133  for (int j = 0; j < copyFrom.size(); j++) {
134  p_data[j] = copyFrom[j];
135  }
136  this->len = copyFrom.size();
137  }
138 
140  template <typename TT, int N>
141  Vector(TT (&a)[N]) {
142  resize_internal(N, false);
143  for (int j = 0; j < N; j++) {
144  p_data[j] = a[j];
145  }
146  this->len = N;
147  }
148 
151  resize_internal(copyFrom.size(), false);
152  for (int j = 0; j < copyFrom.size(); j++) {
153  p_data[j] = copyFrom[j];
154  }
155  this->len = copyFrom.size();
156  return *this;
157  }
158 
160  Vector(T *from, T *to, Allocator &allocator = DefaultAllocator) {
161  this->p_allocator = &allocator;
162  this->len = to - from;
163  resize_internal(this->len, false);
164  for (size_t j = 0; j < this->len; j++) {
165  p_data[j] = from[j];
166  }
167  }
168 
170  virtual ~Vector() { reset(); }
171 
172  void setAllocator(Allocator &allocator) {
173  p_allocator = &allocator;
174  }
175 
176  void clear() { len = 0; }
177 
178  int size() { return len; }
179 
180  bool empty() { return size() == 0; }
181 
182  void push_back(T &&value) {
183  resize_internal(len + 1, true);
184  p_data[len] = value;
185  len++;
186  }
187 
188  void push_back(T &value) {
189  resize_internal(len + 1, true);
190  p_data[len] = value;
191  len++;
192  }
193 
194  void push_front(T &value) {
195  resize_internal(len + 1, true);
196  // memmove(p_data,p_data+1,len*sizeof(T));
197  for (int j = len; j >= 0; j--) {
198  p_data[j + 1] = p_data[j];
199  }
200  p_data[0] = value;
201  len++;
202  }
203 
204  void push_front(T &&value) {
205  resize_internal(len + 1, true);
206  // memmove(p_data,p_data+1,len*sizeof(T));
207  for (int j = len; j >= 0; j--) {
208  p_data[j + 1] = p_data[j];
209  }
210  p_data[0] = value;
211  len++;
212  }
213 
214  void pop_back() {
215  if (len > 0) {
216  len--;
217  }
218  }
219 
220  void pop_front() { erase(0); }
221 
222  void assign(iterator v1, iterator v2) {
223  size_t newLen = v2 - v1;
224  resize_internal(newLen, false);
225  this->len = newLen;
226  int pos = 0;
227  for (auto ptr = v1; ptr != v2; ptr++) {
228  p_data[pos++] = *ptr;
229  }
230  }
231 
232  void assign(size_t number, T value) {
233  resize_internal(number, false);
234  this->len = number;
235  for (int j = 0; j < number; j++) {
236  p_data[j] = value;
237  }
238  }
239 
240  void swap(Vector<T> &in) {
241  // save data
242  T *dataCpy = p_data;
243  int bufferLenCpy = bufferLen;
244  int lenCpy = len;
245  // swap this
246  p_data = in.p_data;
247  len = in.len;
248  bufferLen = in.bufferLen;
249  // swp in
250  in.p_data = dataCpy;
251  in.len = lenCpy;
252  in.bufferLen = bufferLenCpy;
253  }
254 
255  T &operator[](int index) {
256  assert(p_data != nullptr);
257  return p_data[index];
258  }
259 
260  T &operator[](const int index) const { return p_data[index]; }
261 
262  bool resize(int newSize, T value) {
263  if (resize(newSize)) {
264  for (int j = 0; j < newSize; j++) {
265  p_data[j] = value;
266  }
267  return true;
268  }
269  return false;
270  }
271 
272  void shrink_to_fit() { resize_internal(this->len, true, true); }
273 
274  int capacity() { return this->bufferLen; }
275 
276  bool resize(int newSize) {
277  int oldSize = this->len;
278  resize_internal(newSize, true);
279  this->len = newSize;
280  return this->len != oldSize;
281  }
282 
283  iterator begin() { return iterator(p_data, 0); }
284 
285  T &back() { return *iterator(p_data + (len - 1), len - 1); }
286 
287  iterator end() { return iterator(p_data + len, len); }
288 
289  // removes a single element
290  void erase(iterator it) { return erase(it.pos()); }
291 
292  // removes a single element
293  void erase(int pos) {
294  if (pos < len) {
295  int lenToEnd = len - pos - 1;
296  // call destructor on data to be erased
297  p_data[pos].~T();
298  // shift values by 1 position
299  memmove((void *)&p_data[pos], (void *)(&p_data[pos + 1]),
300  lenToEnd * sizeof(T));
301 
302  // make sure that we have a valid object at the end
303 #if defined(NO_INPLACE_INIT_SUPPORT)
304  p_data[len - 1] = T();
305 #else
306  new (&(p_data[len - 1])) T();
307 #endif
308  len--;
309  }
310  }
311 
312  T *data() { return p_data; }
313 
314  operator bool() const { return p_data != nullptr; }
315 
316  int indexOf(T obj) {
317  for (int j = 0; j < size(); j++) {
318  if (p_data[j] == obj) return j;
319  }
320  return -1;
321  }
322 
323  bool contains(T obj){
324  return indexOf(obj) >= 0;
325  }
326 
327 
328  void swap(T &other) {
329  // save values
330  int temp_blen = bufferLen;
331  int temp_len = len;
332  T *temp_data = p_data;
333  // swap from other
334  bufferLen = other.bufferLen;
335  len = other.len;
336  p_data = other.p_data;
337  // set other
338  other.bufferLen = temp_blen;
339  other.len = temp_len;
340  other.p_data = temp_data;
341  }
342 
343  void reset() {
344  clear();
345  shrink_to_fit();
346  deleteArray(p_data, size()); // delete [] this->p_data;
347  p_data = nullptr;
348  }
349 
350  protected:
351  int bufferLen = 0;
352  int len = 0;
353  T *p_data = nullptr;
354  Allocator *p_allocator = &DefaultAllocator;
355 
356  void resize_internal(int newSize, bool copy, bool shrink = false) {
357  if (newSize <= 0) return;
358  if (newSize > bufferLen || this->p_data == nullptr || shrink) {
359  T *oldData = p_data;
360  int oldBufferLen = this->bufferLen;
361  p_data = newArray(newSize); // new T[newSize+1];
362  assert(p_data != nullptr);
363  this->bufferLen = newSize;
364  if (oldData != nullptr) {
365  if (copy && this->len > 0) {
366  // save existing data
367  memmove((void*)p_data, (void*)oldData, len * sizeof(T));
368  // clear to prevent double release
369  memset((void*)oldData, 0, len * sizeof(T));
370  }
371  if (shrink) {
372  cleanup(oldData, newSize, oldBufferLen);
373  }
374  deleteArray(oldData, oldBufferLen); // delete [] oldData;
375  }
376  }
377  }
378 
379  T *newArray(int newSize) {
380  T *data;
381 #if USE_ALLOCATOR
382  data = p_allocator->createArray<T>(newSize); // new T[newSize+1];
383 #else
384  data = new T[newSize];
385 #endif
386  return data;
387  }
388 
389  void deleteArray(T *oldData, int oldBufferLen) {
390 #if USE_ALLOCATOR
391  p_allocator->removeArray(oldData, oldBufferLen); // delete [] oldData;
392 #else
393  delete[] oldData;
394 #endif
395  }
396 
397 
398  void cleanup(T *data, int from, int to) {
399  for (int j = from; j < to; j++) {
400  data[j].~T();
401  }
402  }
403 };
404 
405 } // namespace audio_tools
Memory allocateator which uses malloc.
Definition: Allocator.h:22
Iterator for the Vector class.
Definition: Vector.h:29
Vector implementation which provides the most important methods as defined by std::vector....
Definition: Vector.h:21
Vector(T *from, T *to, Allocator &allocator=DefaultAllocator)
legacy constructor with pointer range
Definition: Vector.h:160
Vector(Vector< T > &&moveFrom)
Move constructor.
Definition: Vector.h:117
virtual ~Vector()
Destructor.
Definition: Vector.h:170
Vector(int size, T value, Allocator &allocator=DefaultAllocator)
Allocate size and initialize array.
Definition: Vector.h:108
Vector(Vector< T > &copyFrom)
copy constructor
Definition: Vector.h:130
Vector(TT(&a)[N])
convert from c array
Definition: Vector.h:141
Vector(size_t len=0, Allocator &allocator=DefaultAllocator)
Default constructor: size 0 with DefaultAllocator: The len defines the capacity.
Definition: Vector.h:96
Vector & operator=(Vector &&moveFrom)
Move operator.
Definition: Vector.h:123
Vector< T > & operator=(Vector< T > &copyFrom)
copy operator
Definition: Vector.h:150
Vector(Allocator &allocator)
Constructor with only allocator.
Definition: Vector.h:103
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:823