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(len);
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 
141  resize_internal(copyFrom.size(), false);
142  for (int j = 0; j < copyFrom.size(); j++) {
143  p_data[j] = copyFrom[j];
144  }
145  this->len = copyFrom.size();
146  return *this;
147  }
148 
150  Vector(T *from, T *to, Allocator &allocator = DefaultAllocator) {
151  this->p_allocator = &allocator;
152  this->len = to - from;
153  resize_internal(this->len, false);
154  for (size_t j = 0; j < this->len; j++) {
155  p_data[j] = from[j];
156  }
157  }
158 
160  virtual ~Vector() { reset(); }
161 
162  void setAllocator(Allocator &allocator) {
163  p_allocator = &allocator;
164  }
165 
166  void clear() { len = 0; }
167 
168  int size() { return len; }
169 
170  bool empty() { return size() == 0; }
171 
172  void push_back(T &&value) {
173  resize_internal(len + 1, true);
174  p_data[len] = value;
175  len++;
176  }
177 
178  void push_back(T &value) {
179  resize_internal(len + 1, true);
180  p_data[len] = value;
181  len++;
182  }
183 
184  void push_front(T &value) {
185  resize_internal(len + 1, true);
186  // memmove(p_data,p_data+1,len*sizeof(T));
187  for (int j = len; j >= 0; j--) {
188  p_data[j + 1] = p_data[j];
189  }
190  p_data[0] = 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 pop_back() {
205  if (len > 0) {
206  len--;
207  }
208  }
209 
210  void pop_front() { erase(0); }
211 
212  void assign(iterator v1, iterator v2) {
213  size_t newLen = v2 - v1;
214  resize_internal(newLen, false);
215  this->len = newLen;
216  int pos = 0;
217  for (auto ptr = v1; ptr != v2; ptr++) {
218  p_data[pos++] = *ptr;
219  }
220  }
221 
222  void assign(size_t number, T value) {
223  resize_internal(number, false);
224  this->len = number;
225  for (int j = 0; j < number; j++) {
226  p_data[j] = value;
227  }
228  }
229 
230  void swap(Vector<T> &in) {
231  // save data
232  T *dataCpy = p_data;
233  int bufferLenCpy = bufferLen;
234  int lenCpy = len;
235  // swap this
236  p_data = in.p_data;
237  len = in.len;
238  bufferLen = in.bufferLen;
239  // swp in
240  in.p_data = dataCpy;
241  in.len = lenCpy;
242  in.bufferLen = bufferLenCpy;
243  }
244 
245  T &operator[](int index) {
246  assert(p_data != nullptr);
247  return p_data[index];
248  }
249 
250  T &operator[](const int index) const { return p_data[index]; }
251 
252  bool resize(int newSize, T value) {
253  if (resize(newSize)) {
254  for (int j = 0; j < newSize; j++) {
255  p_data[j] = value;
256  }
257  return true;
258  }
259  return false;
260  }
261 
262  void shrink_to_fit() { resize_internal(this->len, true, true); }
263 
264  int capacity() { return this->bufferLen; }
265 
266  bool resize(int newSize) {
267  int oldSize = this->len;
268  resize_internal(newSize, true);
269  this->len = newSize;
270  return this->len != oldSize;
271  }
272 
273  iterator begin() { return iterator(p_data, 0); }
274 
275  T &back() { return *iterator(p_data + (len - 1), len - 1); }
276 
277  iterator end() { return iterator(p_data + len, len); }
278 
279  // removes a single element
280  void erase(iterator it) { return erase(it.pos()); }
281 
282  // removes a single element
283  void erase(int pos) {
284  if (pos < len) {
285  int lenToEnd = len - pos - 1;
286  // call destructor on data to be erased
287  p_data[pos].~T();
288  // shift values by 1 position
289  memmove((void *)&p_data[pos], (void *)(&p_data[pos + 1]),
290  lenToEnd * sizeof(T));
291 
292  // make sure that we have a valid object at the end
293  p_data[len - 1] = T();
294  len--;
295  }
296  }
297 
298  T *data() { return p_data; }
299 
300  operator bool() const { return p_data != nullptr; }
301 
302  int indexOf(T obj) {
303  for (int j = 0; j < size(); j++) {
304  if (p_data[j] == obj) return j;
305  }
306  return -1;
307  }
308 
309  bool contains(T obj){
310  return indexOf(obj) >= 0;
311  }
312 
313 
314  void swap(T &other) {
315  // save values
316  int temp_blen = bufferLen;
317  int temp_len = len;
318  T *temp_data = p_data;
319  // swap from other
320  bufferLen = other.bufferLen;
321  len = other.len;
322  p_data = other.p_data;
323  // set other
324  other.bufferLen = temp_blen;
325  other.len = temp_len;
326  other.p_data = temp_data;
327  }
328 
329  void reset() {
330  clear();
331  shrink_to_fit();
332  deleteArray(p_data, size()); // delete [] this->p_data;
333  p_data = nullptr;
334  }
335 
336  protected:
337  int bufferLen = 0;
338  int len = 0;
339  T *p_data = nullptr;
340  Allocator *p_allocator = &DefaultAllocator;
341 
342  void resize_internal(int newSize, bool copy, bool shrink = false) {
343  if (newSize <= 0) return;
344  if (newSize > bufferLen || this->p_data == nullptr || shrink) {
345  T *oldData = p_data;
346  int oldBufferLen = this->bufferLen;
347  p_data = newArray(newSize); // new T[newSize+1];
348  assert(p_data != nullptr);
349  this->bufferLen = newSize;
350  if (oldData != nullptr) {
351  if (copy && this->len > 0) {
352  // save existing data
353  memmove((void*)p_data, (void*)oldData, len * sizeof(T));
354  // clear to prevent double release
355  memset((void*)oldData, 0, len * sizeof(T));
356  }
357  if (shrink) {
358  cleanup(oldData, newSize, oldBufferLen);
359  }
360  deleteArray(oldData, oldBufferLen); // delete [] oldData;
361  }
362  }
363  }
364 
365  T *newArray(int newSize) {
366  T *data;
367 #if USE_ALLOCATOR
368  data = p_allocator->createArray<T>(newSize); // new T[newSize+1];
369 #else
370  data = new T[newSize];
371 #endif
372  return data;
373  }
374 
375  void deleteArray(T *oldData, int oldBufferLen) {
376 #if USE_ALLOCATOR
377  p_allocator->removeArray(oldData, oldBufferLen); // delete [] oldData;
378 #else
379  delete[] oldData;
380 #endif
381  }
382 
383 
384  void cleanup(T *data, int from, int to) {
385  for (int j = from; j < to; j++) {
386  data[j].~T();
387  }
388  }
389 };
390 
391 } // 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:150
Vector(Vector< T > &&moveFrom)
Move constructor.
Definition: Vector.h:117
virtual ~Vector()
Destructor.
Definition: Vector.h:160
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(size_t len=0, Allocator &allocator=DefaultAllocator)
Default constructor: size 0 with DefaultAllocator.
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:140
Vector(Allocator &allocator)
Constructor with only allocator.
Definition: Vector.h:103
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10