Dynalib Utils
DynaArrayImpl.h
Go to the documentation of this file.
1 //
2 // Created by Ken Kopelson on 15/10/17.
3 //
4 
13 #ifndef DYNAARRAYIMPL_H
14 #define DYNAARRAYIMPL_H
15 
16 #include <iostream>
17 #include <type_traits>
18 using namespace std;
19 #include "BitManip.h"
20 #include "DynaAllocImpl.h"
21 #include "DynaArray.h"
22 #include "CheckForError.h"
23 #include "Exception.h"
24 
25 #define MAKE_ARRAYTYPE_INSTANCE(C, T) \
26  template class DynaAllocArray<C>; \
27  template class DynaArray<C>; \
28  typedef DynaAllocArray<C> T##AllocArray; \
29  typedef DynaArray<C> T##Array
30 
31 //===========================================================================
32 // Static Methods
33 //===========================================================================
34 
35 //===========================================================================
36 // Constructors/Destructor
37 //===========================================================================
38 template <class T> DynaArray<T>::DynaArray(uint initCapacity) {
39  adjustSize(initCapacity);
40 }
41 
42 template <class T> DynaArray<T>::DynaArray(T* array, int count) {
43  _insertArray(array, 0, 0, count);
44 }
45 
46 template <class T> DynaArray<T>::~DynaArray() {
48  _members = nullptr;
49 }
50 
51 template <class T> DynaArray<T>::DynaArray(const DynaArray<T>& other) {
52  _flags = other._flags;
53  _insertArray(other._members, 0, 0, other._count);
54 }
55 
56 template<class T> DynaArray<T>* DynaArray<T>::copy() {
57  return new DynaArray<T>(*this);
58 }
59 
60 //===========================================================================
61 // Private Methods
62 //===========================================================================
63 template <class T> void DynaArray<T>::_insertArray(T* array, int arrayOffset, int toIndex, int count) {
64  if ((_count + count) >= _capacity)
65  adjustSizeLog(count);
66  if (toIndex < _count)
67  memmove(_members + toIndex + count, _members + toIndex, (_count - toIndex) * sizeof(T));
68  _count += count;
69  memmove(_members + toIndex, array + arrayOffset, count * sizeof(T));
70 }
71 
72 template <class T> void DynaArray<T>::_swap(int index1, int index2) {
73  T tmp = _members[ index1 ];
74  _members[ index1 ] = _members[ index2 ];
75  _members[ index2 ] = tmp;
76 }
77 
78 template <class T> DynaArray<T>* DynaArray<T>::_copyRange(int frIndex, int toIndex) {
79  int range = toIndex - frIndex + 1;
80  auto* newArray = new DynaArray<T>(range);
81  newArray->setAllFlags(_flags);
82  newArray->_insertArray(getInternalTypedArray(), frIndex, 0, range);
83  return newArray;
84 }
85 
86 template <class T> void DynaArray<T>::_deleteExcessCapacity() {
87  if ((_capacity - _count) >= DynaAllocArray<T>::getAllocUnits())
88  adjustSize(0);
89 }
90 
91 template <class T> void DynaArray<T>::_deleteRange(int frIndex, int toIndex) {
92  if (toIndex == END_OF_LIST)
93  toIndex = _count;
94  else
95  ++toIndex;
96  memmove(_members + frIndex, _members + toIndex, (_count - toIndex) * sizeof(T));
97  _count -= (toIndex - frIndex);
98  // Zero out any remaining slots at the end of the array
99  for (int idx = _count; idx < _capacity; ++idx) {
100  _members[idx] = 0;
101  }
102  if (IS_ALL_SET(_flags, AUTO_TRIM))
103  _deleteExcessCapacity();
104 }
105 
106 template <class T> void DynaArray<T>::_clearRange(int frIndex, int toIndex) {
107  if (toIndex == END_OF_LIST)
108  toIndex = _count - 1;
109  for (int idx = frIndex; idx <= toIndex; ++idx) {
110  _members[idx] = 0;
111  }
112  SET_BITS(_flags, PACK_NEEDED);
113  if (IS_ALL_SET(_flags, AUTO_TRIM))
114  _deleteExcessCapacity();
115 }
116 
117 template <class T> void DynaArray<T>::_deleteOrClear(int frIndex, int toIndex) {
118  if (IS_ALL_SET(_flags, AUTO_PACK))
119  _deleteRange(frIndex, toIndex);
120  else
121  _clearRange(frIndex, toIndex);
122 }
123 
124 template <class T> bool DynaArray<T>::_setAutoPack(bool isPack) {
125  if (isPack) {
126  setFlags(AUTO_PACK);
127  pack();
128  }
129  else
130  clearFlags(AUTO_PACK);
131  return isPack;
132 }
133 
134 template <class T> bool DynaArray<T>::_setAutoTrim(bool isTrim) {
135  if (isTrim) {
136  setFlags(AUTO_TRIM);
137  trim();
138  }
139  else
140  clearFlags(AUTO_TRIM);
141  return isTrim;
142 }
143 
144 template <class T> void DynaArray<T>::setAutoPackTrim(bool pack, bool trim) {
145  if (!_setAutoPack(pack))
146  _setAutoTrim(trim);
147 }
148 
149 //===========================================================================
150 // Public Methods
151 //===========================================================================
152 template <class T> DynaArray<T>& DynaArray<T>::operator= (const DynaArray<T>& array) {
153  if (this == &array)
154  return *this;
155 
156  // do the copy
157  // return the existing object so we can chain this operator
158  return *this;
159 }
160 
162  append(value);
163  return *this;
164 };
165 
166 template <class T> DynaArray<T>& DynaArray<T>::operator+=(T& value) {
167  append(value);
168  return *this;
169 }
170 
171 template <class T> DynaArray<T>& DynaArray<T>::operator-=(int index) {
172  deleteItem(index);
173  return *this;
174 };
175 
177  append(value);
178  return *this;
179 }
180 
181 template <class T> DynaArray<T>& DynaArray<T>::operator<<(T& value) {
182  append(value);
183  return *this;
184 }
185 
186 template <class T> void DynaArray<T>::setCapacity(uint newCapacity) {
187  if (newCapacity != _capacity) {
188  _members = DynaAllocArray<T>::reallocArray(_members, _capacity, newCapacity);
189  _capacity = newCapacity;
190  if (_count > _capacity)
191  _count = _capacity;
192  }
193 }
194 
195 template <class T> void DynaArray<T>::determineTheCount(int invalidValue) {
196  _count = 0;
197  bool found = false;
198  for (int i = 0; i < _capacity; ++i) {
199  if (_members[i] == invalidValue) {
200  found = true;
201  _count = (uint)i;
202  break;
203  }
204  }
205  if (!found) {
206  _count = _capacity;
207  }
208 }
209 
210 // template <class T> void DynaArray<T>::determineTheCountFromEnd(int invalidValue) {
211 // _count = _capacity;
212 // bool found = false;
213 // for (int i = _capacity - 1; i >= 0; --i) {
214 // if (!found) {
215 // if (_members[i] == invalidValue) {
216 // found = true;
217 // _count = (uint)i;
218 // }
219 // }
220 // else {
221 // if (_members[i] != invalidValue)
222 // break;
223 // _count = (uint)i;
224 // }
225 // }
226 // }
227 
228 template <class T> void DynaArray<T>::setCount(uint count) {
229  if (count != _count) {
230  if (count > _capacity)
231  count = _capacity;
232  _count = count;
233  }
234 }
235 
236 template <class T> void DynaArray<T>::adjustSize(int delta) {
237  setCapacity(_count + delta);
238 }
239 
240 template <class T> void DynaArray<T>::adjustSizeLog(int delta) {
241  setCapacity(((_count + delta) * 3 / 2) + 1);
242 }
243 
244 template <class T> void DynaArray<T>::pack() {
245  for (int idx = _count - 1; idx >= 0; --idx) {
246  if (_members[idx] == 0)
247  remove(idx);
248  }
249 }
250 
251 template <class T> void DynaArray<T>::clear() {
252  if (_count > 0)
253  deleteItems(0, _count - 1);
254 }
255 
256 template <class T> int DynaArray<T>::indexOf(T value, uint start, uint step) {
257  uint cnt = getCount();
258  for (uint i = start; i < cnt; i += step) {
259  if (_members[i] == value)
260  return i;
261  }
262  return END_OF_LIST;
263 }
264 
265 template <class T> int DynaArray<T>::indexOf(T* value, uint arraySize, uint start, uint step) {
266  uint cnt = getCount();
267  for (uint i = start; i < cnt; i += step) {
268  for (uint j = 0; j < arraySize; ++j) {
269  if (_members[i] == value[j])
270  return i;
271  }
272  }
273  return END_OF_LIST;
274 }
275 
276 template <class T> int DynaArray<T>::indexOf(T value) {
277  return indexOf(value, 0, 1);
278 }
279 
280 template <class T> int DynaArray<T>::indexOf(T* value, uint arraySize) {
281  return indexOf(value, arraySize, 0, 1);
282 }
283 
284 template <class T> int DynaArray<T>::revIndexOf(T value, uint start, uint step) {
285  int last = getCount() - 1;
286  for (int i = last - start; i >= 0; i -= step) {
287  if (_members[i] == value)
288  return i;
289  }
290  return END_OF_LIST;
291 }
292 
293 template <class T> int DynaArray<T>::revIndexOf(T* value, uint arraySize, uint start, uint step) {
294  int last = getCount() - 1;
295  for (int i = last - start; i >= 0; i -= step) {
296  for (int j = arraySize - 1; j >= 0; --j) {
297  if (_members[i] == value[j])
298  return i;
299  }
300  }
301  return END_OF_LIST;
302 }
303 
304 template <class T> int DynaArray<T>::revIndexOf(T value) {
305  return revIndexOf(value, 0, 1);
306 }
307 
308 template <class T> int DynaArray<T>::revIndexOf(T* value, uint arraySize) {
309  return revIndexOf(value, arraySize, 0, 1);
310 }
311 
312 template <class T> int DynaArray<T>::insert(int index, T value) {
313  if (index == END_OF_LIST)
314  index = _count;
315  else
316  CheckForError::assertInBounds(index, _count);
317  if (_count >= _capacity)
318  adjustSizeLog(1);
319  if (index < _count)
320  memmove(_members + index + 1, _members + index, (_count - index) * sizeof(T));
321  ++_count;
322  _members[index] = value;
323  return index;
324 }
325 
326 template <class T> int DynaArray<T>::insert(int index, T* value) {
327  return insert(index, *value);
328 }
329 
330 template <class T> int DynaArray<T>::insert(int index, T* values, uint length) {
331  return 0;
332 }
333 
334 template <class T> int DynaArray<T>::insert(int index, uint8_t* values, uint offset, uint length) {
335  return 0;
336 }
337 
338 template <class T> int DynaArray<T>::insert(int index, DynaArray<T>* array) {
339  return 0;
340 }
341 
342 template <class T> int DynaArray<T>::append(T value) {
343  return insert(END_OF_LIST, value);
344 }
345 
346 template <class T> int DynaArray<T>::append(T* values, uint length) {
347  return insert(END_OF_LIST, values, length);
348 }
349 
350 template <class T> int DynaArray<T>::append(uint8_t* values, uint offset, uint length) {
351  return insert(END_OF_LIST, values, offset, length);
352 }
353 
354 template <class T> int DynaArray<T>::append(DynaArray<T>* array) {
355  return insert(END_OF_LIST, array);
356 }
357 
358 template <class T> T DynaArray<T>::setValue(int index, T value) {
359  CheckForError::assertInBounds(index, _count - 1);
360  T oldItem = _members[index];
361  _members[index] = value;
362  return oldItem;
363 }
364 
365 template <class T> void DynaArray<T>::move(int index, int destIndex) {
366  CheckForError::assertInBounds(index, _count - 1);
367  CheckForError::assertInBounds(destIndex, _count);
368  if (index != destIndex) {
369  T item = _members[index];
370  if (destIndex < index) {
371  int moveCount = index - destIndex;
372  if (moveCount == 1)
373  _swap(index, destIndex);
374  else {
375  memmove(_members + destIndex + 1, _members + destIndex, (index - destIndex) * sizeof(T));
376  _members[destIndex] = item;
377  }
378  }
379  else if (index < --destIndex){
380  int moveCount = destIndex - index;
381  if (moveCount == 1)
382  _swap(index, destIndex);
383  else {
384  memmove(_members + index, _members + index + 1, (destIndex - index) * sizeof(T));
385  _members[destIndex] = item;
386  }
387  }
388  }
389 }
390 
391 template <class T> void DynaArray<T>::slide(int frIndex, int toIndex) {
392  CheckForError::assertInBounds( frIndex, _count - 1 );
393  CheckForError::assertInBounds( toIndex, _count - 1 );
394  if ( frIndex != toIndex ) {
395  T item = _members[ frIndex ];
396  if ( frIndex < toIndex ) {
397  memmove(_members + frIndex, _members + frIndex + 1, (toIndex - frIndex) * sizeof(T));
398  _members[ toIndex ] = item;
399  }
400  else {
401  memmove( _members + toIndex + 1, _members + toIndex, (frIndex - toIndex) * sizeof(T));
402  _members[ toIndex ] = item;
403  }
404  }
405 }
406 
407 template <class T> T DynaArray<T>::remove(int index) {
408  CheckForError::assertInBounds(index, _count - 1);
409  T item = _members[index];
410  _deleteOrClear(index, index);
411  return item;
412 }
413 
414 template <class T> DynaArray<T>* DynaArray<T>::remove(int frIndex, int toIndex) {
415  CheckForError::assertInBounds(frIndex, toIndex);
416  CheckForError::assertInBounds(toIndex, _count - 1);
417  DynaArray<T>* newArray = _copyRange(frIndex, toIndex);
418  _deleteOrClear(frIndex, toIndex);
419  return newArray;
420 }
421 
422 template <class T> void DynaArray<T>::deleteItem(int index) {
423  CheckForError::assertInBounds(index, _count - 1);
424  _deleteOrClear(index, index);
425 }
426 
427 template <class T> void DynaArray<T>::deleteItems(int frIndex, int toIndex) {
428  CheckForError::assertInBounds(frIndex, toIndex);
429  CheckForError::assertInBounds(toIndex, _count - 1);
430  _deleteOrClear(frIndex, toIndex);
431 }
432 
433 template <class T> void DynaArray<T>::push(T value) {
434  insert(0, value);
435 }
436 
437 template <class T> T DynaArray<T>::pop() {
438  if (_count > 0)
439  return remove(0);
440  else
441  throw EmptyStackException();
442 }
443 
444 template <class T> T DynaArray<T>::popLast() {
445  if (_count > 0)
446  return remove(_count - 1);
447  else
448  throw EmptyStackException();
449 }
450 
451 template <class T> DynaArrayIter<T> DynaArray<T>::begin () const {
452  return DynaArrayIter<T>( this, 0 );
453 }
454 
455 template <class T> DynaArrayIter<T> DynaArray<T>::end () const {
456  return DynaArrayIter<T>( this, _count );
457 }
458 
459 
460 #endif //DYNAARRAYIMPL_H
void push(T value)
Definition: DynaArrayImpl.h:433
#define END_OF_LIST
Definition: DynaArray.h:19
GeneratorWrapper< T > values(std::initializer_list< T > values)
Definition: catch.hpp:4009
Definition: DynaAlloc.h:13
static bool assertInBounds(int index, int maxIndex, const std::string &msg="???")
Definition: CheckForError.cpp:42
void deleteItem(int index)
Definition: DynaArrayImpl.h:422
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:4005
void deleteItems(int frIndex, int toIndex)
Definition: DynaArrayImpl.h:427
T popLast()
Definition: DynaArrayImpl.h:444
GeneratorWrapper< T > range(T const &start, T const &end, T const &step)
Definition: catch.hpp:4699
#define SET_BITS(value, bits)
Definition: BitManip.h:8
virtual ~DynaArray()
Definition: DynaArrayImpl.h:46
DynaArray< T > & operator<<(T value)
Definition: DynaArrayImpl.h:176
#define AUTO_TRIM
Definition: DynaArray.h:18
void slide(int frIndex, int toIndex)
Definition: DynaArrayImpl.h:391
#define AUTO_PACK
Definition: DynaArray.h:16
void pack()
Definition: DynaArrayImpl.h:244
DynaArrayIter< T > begin() const
Definition: DynaArrayImpl.h:451
void setAutoPackTrim(bool pack, bool trim)
Definition: DynaArrayImpl.h:144
T setValue(int index, T value)
Definition: DynaArrayImpl.h:358
std::string trim(std::string const &str)
Returns a new string without whitespace at the start/end.
Definition: DynaArray.h:28
Definition: Exception.h:65
void adjustSizeLog(int delta)
Definition: DynaArrayImpl.h:240
void adjustSize(int delta)
Definition: DynaArrayImpl.h:236
static T * reallocArray(T *array, uint oldCount, uint newCount)
Definition: DynaAllocImpl.h:19
static T * deleteArray(T *array)
Definition: DynaAllocImpl.h:46
T remove(int index)
Definition: DynaArrayImpl.h:407
int revIndexOf(T value, uint start, uint step)
Definition: DynaArrayImpl.h:284
#define PACK_NEEDED
Definition: DynaArray.h:17
CONSTDATA date::last_spec last
Definition: date.h:1834
int insert(int index, T value)
Definition: DynaArrayImpl.h:312
void move(int index, int destIndex)
Definition: DynaArrayImpl.h:365
#define IS_ALL_SET(value, bits)
Definition: BitManip.h:10
DynaArray< T > & operator-=(int index)
Definition: DynaArrayImpl.h:171
DynaArray< T > & operator=(const DynaArray< T > &array)
Definition: DynaArrayImpl.h:152
int indexOf(T value, uint start, uint step)
Definition: DynaArrayImpl.h:256
DynaArray()=default
int append(T value)
Definition: DynaArrayImpl.h:342
void setCapacity(uint newCapacity)
Definition: DynaArrayImpl.h:186
DynaArray< T > & operator+=(T value)
Definition: DynaArrayImpl.h:161
DynaArrayIter< T > end() const
Definition: DynaArrayImpl.h:455
void determineTheCount(int invalidValue)
Definition: DynaArrayImpl.h:195
void setAllFlags(uint8_t flags)
Definition: DynaArray.h:49
Definition: DynaArray.h:26
void setCount(uint count)
Definition: DynaArrayImpl.h:228
DynaArray< T > * copy() override
Definition: DynaArrayImpl.h:56
void clear()
Definition: DynaArrayImpl.h:251
T pop()
Definition: DynaArrayImpl.h:437