acarray.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. #ifndef AC_ACARRAY_H
  2. #define AC_ACARRAY_H
  3. //////////////////////////////////////////////////////////////////////////////
  4. //
  5. // Copyright 2015 Autodesk, Inc. All rights reserved.
  6. //
  7. // Use of this software is subject to the terms of the Autodesk license
  8. // agreement provided at the time of installation or download, or which
  9. // otherwise accompanies this software in either electronic or hard copy form.
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. //
  13. // DESCRIPTION:
  14. //
  15. // This file contains the definition for a dynamic array, called
  16. // AcArray<T,R>, of objects of type "T".
  17. //
  18. // "Dynamic array" means that the array can grow without bounds,
  19. // unlike declaring an array of objects of type "T" in the
  20. // usual manner. For example declaring "T myArray[10]"
  21. // is limited to holding only ten entries.
  22. //
  23. // In order to use the class AcArray<T,R>, you need to understand
  24. // a couple of simple, yet key, concepts:
  25. //
  26. // 1) The logical length of the array.
  27. // - How many entries have been placed into the array,
  28. // initially always zero.
  29. // 2) The physical length of the array.
  30. // - How many entries the array will hold before it
  31. // automatically "grows" larger.
  32. // 3) The grow length of the array.
  33. // - How much the array will grow when required.
  34. //
  35. // The physical length of the array is the actual length of the
  36. // physically allocated, but perhaps not fully used, array.
  37. // As a point of clarification, the size in bytes of the array
  38. // buffer for an array called `myArray' would be:
  39. //
  40. // sizeOf(T) * myArray.physicalLength().
  41. //
  42. // The physical length of the array can be zero or any positive
  43. // integer.
  44. //
  45. // The logical length of the array (or just the "length()") reflects
  46. // how many elements of T have been placed into the array
  47. // with, for example, append() or insertAt(). Many member-functions
  48. // are only valid for indices that are greater than or equal to
  49. // zero AND less than length(). For example, indexing into the
  50. // array with the operator[] is only valid for indices in this range.
  51. //
  52. // You can explicitly set the logical length() to any value and
  53. // if the physical length is not large enough the array will grow to
  54. // that length. Note that if the logical length is explicitly reset
  55. // to a larger value, then all the entries from the old length up
  56. // to the new length may contain garbage values, therefor they must be
  57. // initialized explicitly.
  58. //
  59. // The logical length is always less than or equal to the physical
  60. // length. NOTE that the array ALWAYS starts out empty, i.e., the
  61. // length() always starts at zero regardless of the initial physical
  62. // length.
  63. //
  64. // If you add an element to the array causing the logical length
  65. // to become greater than the physical length of the array then
  66. // additional space is allocated to increase the physical length.
  67. // The amount of the increase is the larger of: the current grow
  68. // length, or double the current logical length if the space used
  69. // is less than 64k bytes, or the number items that will grow
  70. // the total space by an additional 64k bytes.
  71. //
  72. // The grow length must be a positive number, that is, zero is an illegal
  73. // grow length.
  74. //
  75. #include <memory.h>
  76. #include <stdlib.h>
  77. #include <algorithm>
  78. #include <type_traits>
  79. #include "adesk.h"
  80. #include "assert.h"
  81. //Fix for defect 672405
  82. #ifdef ASSERT
  83. #define AC_ARRAY_ASSERT ASSERT
  84. #elif defined assert
  85. #define AC_ARRAY_ASSERT assert
  86. #elif defined _ASSERTE
  87. #define AC_ARRAY_ASSERT _ASSERTE
  88. #else
  89. #define AC_ARRAY_ASSERT(T)
  90. #endif
  91. #pragma pack (push, 8)
  92. #define ACARRAY_GROWTH_THRESHOLD 0x10000
  93. // The legacy name AllocatorSelector may go away in the future
  94. #define AllocatorSelector AcArrayItemCopierSelector
  95. // If the contained class T can be safely copied by the memcpy operator you
  96. // should use the AcArrayMemCopyReallocator template with the array.
  97. // If the class you intend to contain requires the use of operator=() for
  98. // the copying during reallocation you should use AcArrayObjectCopyReallocator
  99. //
  100. // The default copy behaviour is based on the is_trivial trait of the type T
  101. //
  102. // If bMove is true, then the old data is not needed and it's safe to move it
  103. // (using C++ 11 move semantics) instead of copying it, for performance.
  104. //
  105. // If bSameBuffer is true, then bMove must be true also and we are moving elements
  106. // left or right in a buffer, and so we have to do that in a safe way without
  107. // clobbering source data.
  108. template <class T> class AcArrayMemCopyReallocator
  109. {
  110. public:
  111. static void copyItems(T* pDest, size_t nBufLen, const T * pSource, size_t nCount,
  112. bool bMove, bool bSameBuffer)
  113. {
  114. bMove; // avoid unreferenced param warning
  115. AC_ARRAY_ASSERT(nCount <= nBufLen);
  116. AC_ARRAY_ASSERT(nCount >= 0);
  117. AC_ARRAY_ASSERT(nCount < 0x40000000); // 1G sanity check
  118. AC_ARRAY_ASSERT(pSource > pDest || (pDest >= pSource + nCount)); // no overlap
  119. AC_ARRAY_ASSERT(bMove || !bSameBuffer);
  120. if (nCount > 0) {
  121. if (bSameBuffer)
  122. memmove_s(pDest, nBufLen * sizeof(T), pSource, nCount * sizeof(T));
  123. else
  124. memcpy_s(pDest, nBufLen * sizeof(T), pSource, nCount * sizeof(T));
  125. }
  126. }
  127. };
  128. template <class T> class AcArrayObjectCopyReallocator
  129. {
  130. public:
  131. static void copyItems(T* pDest, size_t nBufLen, const T * pSource, size_t nCount,
  132. bool bMove, bool bSameBuffer)
  133. {
  134. bMove; // avoid unreferenced param warning. this one will be used eventually
  135. nBufLen; // avoid unreferenced param warning
  136. bSameBuffer;
  137. AC_ARRAY_ASSERT(nCount <= nBufLen);
  138. AC_ARRAY_ASSERT(nCount >= 0);
  139. AC_ARRAY_ASSERT(nCount < 0x40000000); // 1G sanity check
  140. AC_ARRAY_ASSERT(pSource > pDest || (pDest >= pSource + nCount)); // no overlap
  141. AC_ARRAY_ASSERT(bMove || !bSameBuffer);
  142. while (nCount--)
  143. {
  144. *pDest = *pSource;
  145. pDest++;
  146. pSource++;
  147. }
  148. }
  149. };
  150. template<typename T, bool>
  151. struct AcArrayItemCopierSelector;
  152. template<typename T>
  153. struct AcArrayItemCopierSelector<T, false>
  154. {
  155. typedef AcArrayObjectCopyReallocator<T> allocator;
  156. };
  157. template<typename T>
  158. struct AcArrayItemCopierSelector<T, true>
  159. {
  160. typedef AcArrayMemCopyReallocator<T> allocator;
  161. };
  162. template <typename T, typename R = typename AcArrayItemCopierSelector<T, std::is_trivial<T>::value>::allocator > class AcArray
  163. {
  164. public:
  165. AcArray(int initPhysicalLength = 0, int initGrowLength = 8);
  166. AcArray(const AcArray<T,R>&);
  167. AcArray(AcArray<T,R>&&);
  168. ~AcArray();
  169. typedef R Allocator;
  170. // This enum is useful for validating that an AcArray uses the efficient copy method.
  171. // E.g.: static_assert(AcArray<MyType>::eUsesMemCopy, "AcArray<MyType> uses slow copy!");
  172. enum {eUsesMemCopy = std::is_same<R, AcArrayMemCopyReallocator<T>>::value};
  173. // Copy operator.
  174. //
  175. AcArray<T,R>& operator = (const AcArray<T,R>&);
  176. AcArray<T,R>& operator = (AcArray<T,R>&&);
  177. bool operator == (const AcArray<T,R>&) const;
  178. // Indexing into the array.
  179. //
  180. T& operator [] (int);
  181. const T & operator [] (int) const;
  182. // More access to array-elements.
  183. //
  184. const T & at (int index) const;
  185. T & at (int index);
  186. AcArray<T,R>& setAt (int index, const T& value);
  187. AcArray<T,R>& setAll (const T& value);
  188. T& first ();
  189. const T & first () const;
  190. T& last ();
  191. const T & last () const;
  192. // Adding array-elements.
  193. //
  194. int append (const T& value);
  195. AcArray<T,R>& append (const AcArray<T,R>& array);
  196. AcArray<T,R>& insertAt (int index, const T& value);
  197. // Removing array-elements.
  198. //
  199. AcArray<T,R>& removeAt (int index);
  200. bool remove (const T& value, int start = 0);
  201. AcArray<T,R>& removeFirst ();
  202. AcArray<T,R>& removeLast ();
  203. AcArray<T,R>& removeAll ();
  204. AcArray<T,R>& removeSubArray (int startIndex, int endIndex);
  205. // Query about array-elements.
  206. //
  207. bool contains (const T& value, int start = 0) const;
  208. bool find (const T& value, int& foundAt,
  209. int start = 0) const;
  210. int find (const T& value) const;
  211. int findFrom (const T& value, int start) const;
  212. // Array length.
  213. //
  214. int length () const; // Logical length.
  215. bool isEmpty () const;
  216. int logicalLength() const;
  217. AcArray<T,R>& setLogicalLength(int);
  218. int physicalLength() const;
  219. AcArray<T,R>& setPhysicalLength(int);
  220. // Automatic resizing.
  221. //
  222. int growLength () const;
  223. AcArray<T,R>& setGrowLength(int);
  224. // Utility.
  225. //
  226. AcArray<T,R>& reverse ();
  227. AcArray<T,R>& swap (int i1, int i2);
  228. // Treat as simple array of T.
  229. //
  230. const T* asArrayPtr () const;
  231. T* asArrayPtr ();
  232. // begin() and end() methods return iterators which allow things like
  233. // range based for loops, std::sort, std::for_each etc to use AcArrays
  234. // E.g.: for (const auto & elt : arr) sum += elt;
  235. //
  236. T * begin() { return mpArray; }
  237. T * end() { return mpArray + mLogicalLen; }
  238. const T * begin() const { return mpArray; }
  239. const T * end() const { return mpArray + mLogicalLen; }
  240. protected:
  241. T* mpArray;
  242. int mPhysicalLen;// Actual buffer length.
  243. int mLogicalLen;// Number of items in the array.
  244. int mGrowLen; // Buffer grows by this value.
  245. bool allocPhysBuf();
  246. bool deletePhysBuf(T *pBuf, size_t nCount);
  247. bool isValid (int) const;
  248. };
  249. #pragma pack (pop)
  250. #ifdef GE_LOCATED_NEW
  251. #include "gegblnew.h"
  252. #endif
  253. #pragma pack (push, 8)
  254. // Inline methods.
  255. template <class T, class R> inline bool
  256. AcArray<T,R>::contains(const T& value, int start) const
  257. { return this->findFrom(value, start) != -1; }
  258. template <class T, class R> inline int
  259. AcArray<T,R>::length() const
  260. { return mLogicalLen; }
  261. template <class T, class R> inline bool
  262. AcArray<T,R>::isEmpty() const
  263. { return mLogicalLen == 0; }
  264. template <class T, class R> inline int
  265. AcArray<T,R>::logicalLength() const
  266. { return mLogicalLen; }
  267. template <class T, class R> inline int
  268. AcArray<T,R>::physicalLength() const
  269. { return mPhysicalLen; }
  270. template <class T, class R> inline int
  271. AcArray<T,R>::growLength() const
  272. { return mGrowLen; }
  273. template <class T, class R> inline const T*
  274. AcArray<T,R>::asArrayPtr() const
  275. { return mpArray; }
  276. template <class T, class R> inline T*
  277. AcArray<T,R>::asArrayPtr()
  278. { return mpArray; }
  279. template <class T, class R> inline bool
  280. AcArray<T,R>::isValid(int i) const
  281. { return i >= 0 && i < mLogicalLen; }
  282. template <class T, class R> inline T&
  283. AcArray<T,R>::operator [] (int i)
  284. { AC_ARRAY_ASSERT(this->isValid(i)); return mpArray[i]; }
  285. template <class T, class R> inline const T&
  286. AcArray<T,R>::operator [] (int i) const
  287. { AC_ARRAY_ASSERT(this->isValid(i)); return mpArray[i]; }
  288. template <class T, class R> inline T&
  289. AcArray<T,R>::at(int i)
  290. { AC_ARRAY_ASSERT(this->isValid(i)); return mpArray[i]; }
  291. template <class T, class R> inline const T&
  292. AcArray<T,R>::at(int i) const
  293. { AC_ARRAY_ASSERT(this->isValid(i)); return mpArray[i]; }
  294. template <class T, class R> inline AcArray<T,R>&
  295. AcArray<T,R>::setAt(int i, const T& value)
  296. { AC_ARRAY_ASSERT(this->isValid(i)); mpArray[i] = value; return *this; }
  297. template <class T, class R> inline T&
  298. AcArray<T,R>::first()
  299. { AC_ARRAY_ASSERT(!this->isEmpty()); return mpArray[0]; }
  300. template <class T, class R> inline const T&
  301. AcArray<T,R>::first() const
  302. { AC_ARRAY_ASSERT(!this->isEmpty()); return mpArray[0]; }
  303. template <class T, class R> inline T&
  304. AcArray<T,R>::last()
  305. { AC_ARRAY_ASSERT(!this->isEmpty()); return mpArray[mLogicalLen-1]; }
  306. template <class T, class R> inline const T&
  307. AcArray<T,R>::last() const
  308. { AC_ARRAY_ASSERT(!this->isEmpty()); return mpArray[mLogicalLen-1]; }
  309. template <class T, class R> inline int
  310. AcArray<T,R>::append(const T& value)
  311. { insertAt(mLogicalLen, value); return mLogicalLen-1; }
  312. template <class T, class R> inline AcArray<T,R>&
  313. AcArray<T,R>::removeFirst()
  314. { AC_ARRAY_ASSERT(!isEmpty()); return removeAt(0); }
  315. template <class T, class R> inline AcArray<T,R>&
  316. AcArray<T,R>::removeLast()
  317. {
  318. AC_ARRAY_ASSERT(!isEmpty());
  319. if (!isEmpty())
  320. mLogicalLen--;
  321. return *this;
  322. }
  323. template <class T, class R> inline AcArray<T,R>&
  324. AcArray<T,R>::removeAll()
  325. { this->setLogicalLength(0); return *this; }
  326. template <class T, class R> inline AcArray<T,R>&
  327. AcArray<T,R>::setGrowLength(int glen)
  328. { AC_ARRAY_ASSERT(glen > 0); mGrowLen = glen; return *this; }
  329. template < class T, class R >
  330. AcArray< T, R > ::AcArray(int physicalLength, int growLength)
  331. : mpArray(nullptr),
  332. mPhysicalLen(physicalLength),
  333. mLogicalLen(0),
  334. mGrowLen(growLength)
  335. {
  336. // Replacing is_pod with is_trivial. is_trivial should be a superset of is_pod
  337. static_assert(std::is_trivial<T>::value || !std::is_pod<T>::value, "is_pod but not is_trivial?");
  338. AC_ARRAY_ASSERT(mGrowLen > 0);
  339. AC_ARRAY_ASSERT(mPhysicalLen >= 0);
  340. if (mPhysicalLen > 0)
  341. this->allocPhysBuf();
  342. }
  343. // This is the usual copy constructor with the caveat that,
  344. // if the system can not allocate enough memory to satisfy the
  345. // request then it is assumed that the entire system is in a
  346. // dangerously low memory situation, and there is no alternative
  347. // but to have the system gracefully abort (i.e., prompting the
  348. // users to save files, and/or free up more memory, or what-have-you).
  349. //
  350. template <class T, class R>
  351. AcArray<T,R>::AcArray(const AcArray<T,R>& src)
  352. : mpArray(nullptr),
  353. mPhysicalLen(src.mPhysicalLen),
  354. mLogicalLen(src.mLogicalLen),
  355. mGrowLen(src.mGrowLen)
  356. {
  357. AC_ARRAY_ASSERT(mPhysicalLen >= mLogicalLen);
  358. if (mLogicalLen <= 0) {
  359. AC_ARRAY_ASSERT(mLogicalLen == 0);
  360. mPhysicalLen = 0; // we don't need a buffer yet
  361. }
  362. if (mPhysicalLen <= 0) {
  363. AC_ARRAY_ASSERT(mPhysicalLen == 0);
  364. AC_ARRAY_ASSERT(mLogicalLen == 0);
  365. }
  366. else {
  367. AC_ARRAY_ASSERT(mLogicalLen > 0);
  368. if (this->allocPhysBuf())
  369. R::copyItems(mpArray, mPhysicalLen, src.mpArray, mLogicalLen,
  370. /*bMove*/false, /*bSameBuffer*/false);
  371. }
  372. }
  373. template <class T, class R>
  374. AcArray<T,R>::AcArray(AcArray<T,R>&& src)
  375. : mpArray(src.mpArray),
  376. mPhysicalLen(src.mPhysicalLen),
  377. mLogicalLen(src.mLogicalLen),
  378. mGrowLen(src.mGrowLen)
  379. {
  380. src.mpArray = nullptr;
  381. src.mPhysicalLen = 0;
  382. src.mLogicalLen = 0;
  383. src.mGrowLen = 8;
  384. }
  385. template <class T, class R>
  386. AcArray<T,R>::~AcArray()
  387. {
  388. this->deletePhysBuf(mpArray, mPhysicalLen);
  389. }
  390. // The assignment operator. The assignment operator copies
  391. // the data from the source array to this array. If the
  392. // source array contains more elements that this array has
  393. // space to store, then this array is grown to meet the demand.
  394. // Otherwise, the physical length of this array does not change.
  395. // After this operation is completed the logical lengths of the
  396. // two arrays will be equal. The grow length of this array is
  397. // not affected by this operation.
  398. //
  399. template <class T, class R> AcArray<T,R>&
  400. AcArray<T,R>::operator = (const AcArray<T,R>& src)
  401. {
  402. if (this != &src) {
  403. if (src.mLogicalLen <= 0) {
  404. AC_ARRAY_ASSERT(src.mLogicalLen == 0);
  405. mLogicalLen = 0; // leave physical buffer as is
  406. }
  407. else {
  408. if (mPhysicalLen < src.mLogicalLen) {
  409. if (mpArray != nullptr) {
  410. deletePhysBuf(mpArray, mPhysicalLen);
  411. mpArray = nullptr;
  412. }
  413. mPhysicalLen = src.mLogicalLen;
  414. if (!this->allocPhysBuf())
  415. return *this;
  416. }
  417. mLogicalLen = src.mLogicalLen;
  418. AC_ARRAY_ASSERT(mLogicalLen > 0);
  419. AC_ARRAY_ASSERT(mPhysicalLen >= mLogicalLen);
  420. R::copyItems(mpArray, mPhysicalLen, src.mpArray, mLogicalLen,
  421. /*bMove*/false, /*bSameBuffer*/false);
  422. }
  423. }
  424. return *this;
  425. }
  426. template <class T, class R> AcArray<T,R>&
  427. AcArray<T,R>::operator = (AcArray<T,R>&& src)
  428. {
  429. if (this != &src) {
  430. mPhysicalLen = src.mPhysicalLen;
  431. mpArray = src.mpArray;
  432. mLogicalLen = src.mLogicalLen;
  433. mGrowLen = src.mGrowLen;
  434. src.mpArray = nullptr;
  435. src.mPhysicalLen = 0;
  436. src.mLogicalLen = 0;
  437. src.mGrowLen = 8;
  438. }
  439. return *this;
  440. }
  441. // The equal to operator. The equal to operator compares
  442. // the data in two arrays. If the logical length of the
  443. // two arrays are the same and the corresponding entries of
  444. // the two arrays are equal, true is returned. Otherwise,
  445. // false is returned.
  446. //
  447. template <class T, class R> bool
  448. AcArray<T,R>::operator == (const AcArray<T,R>& cpr) const
  449. {
  450. if (mLogicalLen == cpr.mLogicalLen) {
  451. for (int i = 0; i < mLogicalLen; i++)
  452. if (mpArray[i] != cpr.mpArray[i])
  453. return false;
  454. return true;
  455. }
  456. return false;
  457. }
  458. // Sets all the elements within the logical-length of the array,
  459. // (that is, elements 0..length()-1), to `value'.
  460. //
  461. template <class T, class R> AcArray<T,R>&
  462. AcArray<T,R>::setAll(const T& value)
  463. {
  464. for (int i = 0; i < mLogicalLen; i++) {
  465. mpArray[i] = value;
  466. }
  467. return *this;
  468. }
  469. // Appends the `otherArray' to the end of this array. The logical length of
  470. // this array will increase by the logical length of the `otherArray'.
  471. // Special case: appending to self, where otherArray == this. That works,
  472. // because otherArray.mapArray gets updated by setPhysicalLength.
  473. //
  474. template <class T, class R> AcArray<T,R>&
  475. AcArray<T,R>::append(const AcArray<T,R>& otherArray)
  476. {
  477. const int otherLen = otherArray.length();
  478. if (otherLen == 0)
  479. return *this;
  480. const int newLen = mLogicalLen + otherLen;
  481. if (newLen > mPhysicalLen) // grow the buffer
  482. setPhysicalLength(mLogicalLen + std::max<int>(otherLen, mGrowLen));
  483. R::copyItems(mpArray + mLogicalLen, (mPhysicalLen-mLogicalLen), otherArray.mpArray, otherLen,
  484. /*bMove*/false, /*bSameBuffer*/false);
  485. mLogicalLen = newLen;
  486. return *this;
  487. }
  488. // Inserts `value' at `index'. The value formerly at `index'
  489. // gets moved to `index+1', `index+1 gets moved to `index+2' and so on.
  490. // Note that insertAt(length(), value) is equivalent to append(value).
  491. // The logical length of the array will increase by one. If the physical
  492. // length is not long enough it will increase by the grow length (with the
  493. // usual caveat about insufficient memory).
  494. //
  495. template <class T, class R> AcArray<T,R>&
  496. AcArray<T,R>::insertAt(int index, const T& value)
  497. {
  498. AC_ARRAY_ASSERT(index >= 0 && index <= mLogicalLen);
  499. AC_ARRAY_ASSERT(mLogicalLen <= mPhysicalLen);
  500. if (index < 0 || index > mLogicalLen)
  501. return *this;
  502. const T tmp(value); // make a copy in case value is coming from this array!
  503. if (mLogicalLen >= mPhysicalLen) {
  504. AC_ARRAY_ASSERT(mLogicalLen == mPhysicalLen);
  505. const int growth = (mLogicalLen * sizeof(T)) < ACARRAY_GROWTH_THRESHOLD ?
  506. mLogicalLen : ACARRAY_GROWTH_THRESHOLD / sizeof(T);
  507. setPhysicalLength(mLogicalLen + std::max<int>(growth, mGrowLen));
  508. }
  509. if (index != mLogicalLen) {
  510. AC_ARRAY_ASSERT(mLogicalLen >= 0);
  511. T* p = mpArray + mLogicalLen;
  512. T* pStop = mpArray + index;
  513. do {
  514. *p = *(p-1);
  515. } while (--p != pStop);
  516. }
  517. mpArray[index] = tmp;
  518. mLogicalLen++;
  519. return *this;
  520. }
  521. // Removes the element at `index'. The logical length will
  522. // decrease by one. `index' MUST BE within bounds.
  523. //
  524. template <class T, class R> AcArray<T,R>&
  525. AcArray<T,R>::removeAt(int index)
  526. {
  527. AC_ARRAY_ASSERT(isValid(index));
  528. AC_ARRAY_ASSERT(mLogicalLen <= mPhysicalLen);
  529. AC_ARRAY_ASSERT(!isEmpty());
  530. if (isEmpty() || !isValid(index))
  531. return *this;
  532. // Shift array elements to the left if needed.
  533. //
  534. if (index < mLogicalLen - 1) {
  535. R::copyItems(mpArray + index, mPhysicalLen - index,
  536. mpArray + index + 1, mLogicalLen - 1 - index,
  537. /*bMove*/true, /*bSameBuffer*/true);
  538. }
  539. mLogicalLen--;
  540. return *this;
  541. }
  542. // Removes all elements starting with 'startIndex' and ending with 'endIndex'
  543. // The logical length will decrease by number of removed elements.
  544. // Both `startIndex' and 'endIndex' MUST BE within bounds.
  545. //
  546. template <class T, class R> AcArray<T,R>&
  547. AcArray<T,R>::removeSubArray(int startIndex, int endIndex)
  548. {
  549. AC_ARRAY_ASSERT(isValid(startIndex));
  550. AC_ARRAY_ASSERT(startIndex <= endIndex);
  551. if ( endIndex >= mLogicalLen - 1) {
  552. mLogicalLen = startIndex; // deleting to the right end
  553. return *this;
  554. }
  555. // We didn't delete the right end, so shift remaining elements down
  556. //
  557. const int kNumToRemove = endIndex + 1 - startIndex;
  558. const int kNumToShift = mLogicalLen - 1 - endIndex;
  559. AC_ARRAY_ASSERT(kNumToShift >= 1);
  560. R::copyItems(mpArray + startIndex, mPhysicalLen - startIndex,
  561. mpArray + endIndex + 1, kNumToShift,
  562. /*bMove*/true, /*bSameBuffer*/true);
  563. mLogicalLen -= kNumToRemove;
  564. return *this;
  565. }
  566. // Returns true if and only if the array contains `value' from
  567. // index `start' onwards. Returns, in `index', the first location
  568. // that contains `value'. The search begins at position `start'.
  569. // `start' is supplied with a default value of `0', i.e., the
  570. // beginning of the array.
  571. //
  572. template <class T, class R> bool
  573. AcArray<T,R>::find(const T& value, int& index, int start) const
  574. {
  575. const int nFoundAt = this->findFrom(value, start);
  576. if (nFoundAt == -1)
  577. return false;
  578. index = nFoundAt;
  579. return true;
  580. }
  581. template <class T, class R> int
  582. AcArray<T,R>::find(const T& value) const
  583. {
  584. return this->findFrom(value, 0); // search from the beginning
  585. }
  586. template <class T, class R> int
  587. AcArray<T,R>::findFrom(const T& value, int start) const
  588. {
  589. AC_ARRAY_ASSERT(start >= 0);
  590. if (start < 0)
  591. return -1;
  592. for (int i = start; i < this->mLogicalLen; i++) {
  593. if (mpArray[i] == value)
  594. return i;
  595. }
  596. return -1;
  597. }
  598. // Allows you to set the logical length of the array.
  599. // If you try to set the logical length to be greater than
  600. // the physical length, then the array is grown to a
  601. // reasonable size (thus increasing both the logical length
  602. // AND the physical length).
  603. // Also, the physical length will grow in growth length
  604. // steps.
  605. template <class T, class R> AcArray<T,R>&
  606. AcArray<T,R>::setLogicalLength(int n)
  607. {
  608. AC_ARRAY_ASSERT(n >= 0);
  609. if (n < 0)
  610. n = 0; // avoid going negative
  611. AC_ARRAY_ASSERT(n < 0x40000000); // 1G sanity check
  612. if (n > mPhysicalLen) {
  613. const int growth = (mPhysicalLen * sizeof(T)) < ACARRAY_GROWTH_THRESHOLD ?
  614. mPhysicalLen : ACARRAY_GROWTH_THRESHOLD / sizeof(T);
  615. int minSize = mPhysicalLen + std::max<int>(growth, mGrowLen);
  616. if ( n > minSize)
  617. minSize = n;
  618. setPhysicalLength(minSize);
  619. }
  620. mLogicalLen = n;
  621. AC_ARRAY_ASSERT(mLogicalLen <= mPhysicalLen);
  622. return *this;
  623. }
  624. template <class T, class R> bool
  625. AcArray<T,R>::allocPhysBuf()
  626. {
  627. AC_ARRAY_ASSERT(mPhysicalLen > 0);
  628. AC_ARRAY_ASSERT(mpArray == nullptr);
  629. #ifdef GE_LOCATED_NEW
  630. mpArray = GENEWLOCVEC(T, mPhysicalLen, this) ();
  631. #else
  632. mpArray = new T[mPhysicalLen];
  633. #endif
  634. AC_ARRAY_ASSERT(mpArray != nullptr);
  635. if (mpArray == nullptr) { // shouldn't happen
  636. mPhysicalLen = 0;
  637. mLogicalLen = 0;
  638. return false;
  639. }
  640. return true;
  641. }
  642. template <class T, class R> bool
  643. AcArray<T,R>::deletePhysBuf(T *pBuf, size_t nCount)
  644. {
  645. nCount; // avoid unused arg warning
  646. if (pBuf == nullptr) {
  647. AC_ARRAY_ASSERT(nCount == 0);
  648. }
  649. else {
  650. AC_ARRAY_ASSERT(nCount > 0);
  651. delete[] pBuf;
  652. }
  653. return true;
  654. }
  655. // Allows you to set the physical length of the array.
  656. // If you set the physical length to be less than
  657. // the logical length, then the logical length is reset
  658. // to match the new physical length. A physical length
  659. // of zero is valid.
  660. //
  661. template <class T, class R> AcArray<T,R>&
  662. AcArray<T,R>::setPhysicalLength(int n)
  663. {
  664. AC_ARRAY_ASSERT(mPhysicalLen >= mLogicalLen);
  665. AC_ARRAY_ASSERT((mPhysicalLen == 0) == (mpArray == nullptr));
  666. AC_ARRAY_ASSERT(n >= 0);
  667. AC_ARRAY_ASSERT(n < 0x40000000); // 1G sanity check
  668. if (n == mPhysicalLen || n < 0)
  669. return *this; // nothing to do
  670. T* pOldArray = mpArray;
  671. const size_t nOldLen = mPhysicalLen;
  672. mPhysicalLen = n; // could be growing or shrinking
  673. mpArray = nullptr;
  674. if (mPhysicalLen < mLogicalLen)
  675. mLogicalLen = mPhysicalLen; // shrinking the array
  676. if (mPhysicalLen != 0)
  677. if (this->allocPhysBuf())
  678. R::copyItems(mpArray, mPhysicalLen, pOldArray, mLogicalLen,
  679. /*bMove*/true, /*bSameBuffer*/false); // move items (if any) to new buf
  680. deletePhysBuf(pOldArray, nOldLen); // Blow away the old array buffer.
  681. return *this;
  682. }
  683. // Reverses the order of the array. That is if you have two
  684. // arrays, `a' and `b', then if you assign `a = b' then call
  685. // `a.reverse()' then a[0] == b[n], a[1] == b[n-1],... a[n] == b[0].
  686. //
  687. template <class T, class R> AcArray<T,R>&
  688. AcArray<T,R>::reverse()
  689. {
  690. for (int i = 0; i < mLogicalLen/2; i++) {
  691. const T tmp = mpArray[i];
  692. mpArray[i] = mpArray[mLogicalLen - 1 - i];
  693. mpArray[mLogicalLen - 1 - i] = tmp;
  694. }
  695. return *this;
  696. }
  697. // Swaps the elements in `i1' and `i2'.
  698. //
  699. template <class T, class R> AcArray<T,R>&
  700. AcArray<T,R>::swap(int i1, int i2)
  701. {
  702. AC_ARRAY_ASSERT(isValid(i1));
  703. AC_ARRAY_ASSERT(isValid(i2));
  704. if (i1 == i2) return *this;
  705. const T tmp = mpArray[i1];
  706. mpArray[i1] = mpArray[i2];
  707. mpArray[i2] = tmp;
  708. return *this;
  709. }
  710. // Returns true if and only if `value' was removed from the array from
  711. // position `start' onwards. Only the first occurrence of `value'
  712. // is removed. Calling this function is equivalent to doing a "find(),
  713. // then "removeAt()".
  714. //
  715. template <class T, class R> bool
  716. AcArray<T,R>::remove(const T& value, int start)
  717. {
  718. const int i = this->findFrom(value, start);
  719. if (i == -1)
  720. return false;
  721. this->removeAt(i);
  722. return true;
  723. }
  724. #include "acarrayhelper.h"
  725. #pragma pack (pop)
  726. #endif