as_array.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2014 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. #ifndef AS_ARRAY_H
  24. #define AS_ARRAY_H
  25. #if !defined(AS_NO_MEMORY_H)
  26. #include <memory.h>
  27. #endif
  28. #include <string.h> // some compilers declare memcpy() here
  29. #ifdef _MSC_VER
  30. #pragma warning(disable:4345) // warning about a change in how the code is handled in this version
  31. #endif
  32. BEGIN_AS_NAMESPACE
  33. template <class T> class asCArray
  34. {
  35. public:
  36. asCArray();
  37. asCArray(const asCArray<T> &);
  38. asCArray(size_t reserve);
  39. ~asCArray();
  40. void Allocate(size_t numElements, bool keepData);
  41. void AllocateNoConstruct(size_t numElements, bool keepData);
  42. size_t GetCapacity() const;
  43. void PushLast(const T &element);
  44. T PopLast();
  45. bool SetLength(size_t numElements);
  46. bool SetLengthNoConstruct(size_t numElements);
  47. size_t GetLength() const;
  48. void Copy(const T*, size_t count);
  49. asCArray<T> &operator =(const asCArray<T> &);
  50. void SwapWith(asCArray<T> &other);
  51. const T &operator [](size_t index) const;
  52. T &operator [](size_t index);
  53. T *AddressOf();
  54. const T *AddressOf() const;
  55. bool Concatenate(const asCArray<T> &);
  56. void Concatenate(T*, unsigned int count);
  57. bool Exists(const T &element) const;
  58. int IndexOf(const T &element) const;
  59. void RemoveIndex(size_t index); // Removes the entry without reordering the array
  60. void RemoveValue(const T &element); // Removes the value without reordering the array
  61. void RemoveIndexUnordered(size_t index); // Removes the entry without keeping the order
  62. bool operator==(const asCArray<T> &) const;
  63. bool operator!=(const asCArray<T> &) const;
  64. protected:
  65. T *array;
  66. size_t length;
  67. size_t maxLength;
  68. char buf[8];
  69. };
  70. // Implementation
  71. template <class T>
  72. T *asCArray<T>::AddressOf()
  73. {
  74. return array;
  75. }
  76. template <class T>
  77. const T *asCArray<T>::AddressOf() const
  78. {
  79. return array;
  80. }
  81. template <class T>
  82. asCArray<T>::asCArray(void)
  83. {
  84. array = 0;
  85. length = 0;
  86. maxLength = 0;
  87. }
  88. template <class T>
  89. asCArray<T>::asCArray(const asCArray<T> &copy)
  90. {
  91. array = 0;
  92. length = 0;
  93. maxLength = 0;
  94. *this = copy;
  95. }
  96. template <class T>
  97. asCArray<T>::asCArray(size_t reserve)
  98. {
  99. array = 0;
  100. length = 0;
  101. maxLength = 0;
  102. Allocate(reserve, false);
  103. }
  104. template <class T>
  105. asCArray<T>::~asCArray(void)
  106. {
  107. // Allocating a zero length array will free all memory
  108. Allocate(0,0);
  109. }
  110. template <class T>
  111. size_t asCArray<T>::GetLength() const
  112. {
  113. return length;
  114. }
  115. template <class T>
  116. const T &asCArray<T>::operator [](size_t index) const
  117. {
  118. asASSERT(index < length);
  119. return array[index];
  120. }
  121. template <class T>
  122. T &asCArray<T>::operator [](size_t index)
  123. {
  124. asASSERT(index < length);
  125. return array[index];
  126. }
  127. template <class T>
  128. void asCArray<T>::PushLast(const T &element)
  129. {
  130. if( length == maxLength )
  131. {
  132. if( maxLength == 0 )
  133. Allocate(1, false);
  134. else
  135. Allocate(2*maxLength, true);
  136. if( length == maxLength )
  137. {
  138. // Out of memory. Return without doing anything
  139. return;
  140. }
  141. }
  142. array[length++] = element;
  143. }
  144. template <class T>
  145. T asCArray<T>::PopLast()
  146. {
  147. asASSERT(length > 0);
  148. return array[--length];
  149. }
  150. template <class T>
  151. void asCArray<T>::Allocate(size_t numElements, bool keepData)
  152. {
  153. // We have 4 situations
  154. // 1. The previous array is 8 bytes or smaller and the new array is also 8 bytes or smaller
  155. // 2. The previous array is 8 bytes or smaller and the new array is larger than 8 bytes
  156. // 3. The previous array is larger than 8 bytes and the new array is 8 bytes or smaller
  157. // 4. The previous array is larger than 8 bytes and the new array is also larger than 8 bytes
  158. T *tmp = 0;
  159. if( numElements )
  160. {
  161. if( sizeof(T)*numElements <= 8 )
  162. // Use the internal buffer
  163. tmp = reinterpret_cast<T*>(buf);
  164. else
  165. {
  166. // Allocate the array and construct each of the elements
  167. tmp = asNEWARRAY(T,numElements);
  168. if( tmp == 0 )
  169. {
  170. // Out of memory. Return without doing anything
  171. return;
  172. }
  173. }
  174. if( array == tmp )
  175. {
  176. // Construct only the newly allocated elements
  177. for( size_t n = length; n < numElements; n++ )
  178. new (&tmp[n]) T();
  179. }
  180. else
  181. {
  182. // Construct all elements
  183. for( size_t n = 0; n < numElements; n++ )
  184. new (&tmp[n]) T();
  185. }
  186. }
  187. if( array )
  188. {
  189. size_t oldLength = length;
  190. if( array == tmp )
  191. {
  192. if( keepData )
  193. {
  194. if( length > numElements )
  195. length = numElements;
  196. }
  197. else
  198. length = 0;
  199. // Call the destructor for elements that are no longer used
  200. for( size_t n = length; n < oldLength; n++ )
  201. array[n].~T();
  202. }
  203. else
  204. {
  205. if( keepData )
  206. {
  207. if( length > numElements )
  208. length = numElements;
  209. for( size_t n = 0; n < length; n++ )
  210. tmp[n] = array[n];
  211. }
  212. else
  213. length = 0;
  214. // Call the destructor for all elements
  215. for( size_t n = 0; n < oldLength; n++ )
  216. array[n].~T();
  217. if( array != reinterpret_cast<T*>(buf) )
  218. asDELETEARRAY(array);
  219. }
  220. }
  221. array = tmp;
  222. maxLength = numElements;
  223. }
  224. template <class T>
  225. void asCArray<T>::AllocateNoConstruct(size_t numElements, bool keepData)
  226. {
  227. // We have 4 situations
  228. // 1. The previous array is 8 bytes or smaller and the new array is also 8 bytes or smaller
  229. // 2. The previous array is 8 bytes or smaller and the new array is larger than 8 bytes
  230. // 3. The previous array is larger than 8 bytes and the new array is 8 bytes or smaller
  231. // 4. The previous array is larger than 8 bytes and the new array is also larger than 8 bytes
  232. T *tmp = 0;
  233. if( numElements )
  234. {
  235. if( sizeof(T)*numElements <= 8 )
  236. // Use the internal buffer
  237. tmp = reinterpret_cast<T*>(buf);
  238. else
  239. {
  240. // Allocate the array and construct each of the elements
  241. tmp = asNEWARRAY(T,numElements);
  242. if( tmp == 0 )
  243. {
  244. // Out of memory. Return without doing anything
  245. return;
  246. }
  247. }
  248. }
  249. if( array )
  250. {
  251. if( array == tmp )
  252. {
  253. if( keepData )
  254. {
  255. if( length > numElements )
  256. length = numElements;
  257. }
  258. else
  259. length = 0;
  260. }
  261. else
  262. {
  263. if( keepData )
  264. {
  265. if( length > numElements )
  266. length = numElements;
  267. memcpy(tmp, array, sizeof(T)*length);
  268. }
  269. else
  270. length = 0;
  271. if( array != reinterpret_cast<T*>(buf) )
  272. asDELETEARRAY(array);
  273. }
  274. }
  275. array = tmp;
  276. maxLength = numElements;
  277. }
  278. template <class T>
  279. size_t asCArray<T>::GetCapacity() const
  280. {
  281. return maxLength;
  282. }
  283. template <class T>
  284. bool asCArray<T>::SetLength(size_t numElements)
  285. {
  286. if( numElements > maxLength )
  287. {
  288. Allocate(numElements, true);
  289. if( numElements > maxLength )
  290. {
  291. // Out of memory. Return without doing anything
  292. return false;
  293. }
  294. }
  295. length = numElements;
  296. return true;
  297. }
  298. template <class T>
  299. bool asCArray<T>::SetLengthNoConstruct(size_t numElements)
  300. {
  301. if( numElements > maxLength )
  302. {
  303. AllocateNoConstruct(numElements, true);
  304. if( numElements > maxLength )
  305. {
  306. // Out of memory. Return without doing anything
  307. return false;
  308. }
  309. }
  310. length = numElements;
  311. return true;
  312. }
  313. template <class T>
  314. void asCArray<T>::Copy(const T *data, size_t count)
  315. {
  316. if( maxLength < count )
  317. {
  318. Allocate(count, false);
  319. if( maxLength < count )
  320. {
  321. // Out of memory. Return without doing anything
  322. return;
  323. }
  324. }
  325. for( size_t n = 0; n < count; n++ )
  326. array[n] = data[n];
  327. length = count;
  328. }
  329. template <class T>
  330. asCArray<T> &asCArray<T>::operator =(const asCArray<T> &copy)
  331. {
  332. Copy(copy.array, copy.length);
  333. return *this;
  334. }
  335. template <class T>
  336. void asCArray<T>::SwapWith(asCArray<T> &other)
  337. {
  338. T *tmpArray = array;
  339. size_t tmpLength = length;
  340. size_t tmpMaxLength = maxLength;
  341. char tmpBuf[sizeof(buf)];
  342. memcpy(tmpBuf, buf, sizeof(buf));
  343. array = other.array;
  344. length = other.length;
  345. maxLength = other.maxLength;
  346. memcpy(buf, other.buf, sizeof(buf));
  347. other.array = tmpArray;
  348. other.length = tmpLength;
  349. other.maxLength = tmpMaxLength;
  350. memcpy(other.buf, tmpBuf, sizeof(buf));
  351. // If the data is in the internal buffer, then the array pointer must refer to it
  352. if( array == reinterpret_cast<T*>(other.buf) )
  353. array = reinterpret_cast<T*>(buf);
  354. if( other.array == reinterpret_cast<T*>(buf) )
  355. other.array = reinterpret_cast<T*>(other.buf);
  356. }
  357. template <class T>
  358. bool asCArray<T>::operator ==(const asCArray<T> &other) const
  359. {
  360. if( length != other.length ) return false;
  361. for( size_t n = 0; n < length; n++ )
  362. if( array[n] != other.array[n] )
  363. return false;
  364. return true;
  365. }
  366. template <class T>
  367. bool asCArray<T>::operator !=(const asCArray<T> &other) const
  368. {
  369. return !(*this == other);
  370. }
  371. // Returns false if the concatenation wasn't successful due to out of memory
  372. template <class T>
  373. bool asCArray<T>::Concatenate(const asCArray<T> &other)
  374. {
  375. if( maxLength < length + other.length )
  376. {
  377. Allocate(length + other.length, true);
  378. if( maxLength < length + other.length )
  379. {
  380. // Out of memory
  381. return false;
  382. }
  383. }
  384. for( size_t n = 0; n < other.length; n++ )
  385. array[length+n] = other.array[n];
  386. length += other.length;
  387. // Success
  388. return true;
  389. }
  390. template <class T>
  391. void asCArray<T>::Concatenate(T* array, unsigned int count)
  392. {
  393. for( unsigned int c = 0; c < count; c++ )
  394. PushLast(array[c]);
  395. }
  396. template <class T>
  397. bool asCArray<T>::Exists(const T &e) const
  398. {
  399. return IndexOf(e) == -1 ? false : true;
  400. }
  401. template <class T>
  402. int asCArray<T>::IndexOf(const T &e) const
  403. {
  404. for( size_t n = 0; n < length; n++ )
  405. if( array[n] == e ) return static_cast<int>(n);
  406. return -1;
  407. }
  408. template <class T>
  409. void asCArray<T>::RemoveIndex(size_t index)
  410. {
  411. if( index < length )
  412. {
  413. for( size_t n = index; n < length-1; n++ )
  414. array[n] = array[n+1];
  415. PopLast();
  416. }
  417. }
  418. template <class T>
  419. void asCArray<T>::RemoveValue(const T &e)
  420. {
  421. for( size_t n = 0; n < length; n++ )
  422. {
  423. if( array[n] == e )
  424. {
  425. RemoveIndex(n);
  426. break;
  427. }
  428. }
  429. }
  430. template <class T>
  431. void asCArray<T>::RemoveIndexUnordered(size_t index)
  432. {
  433. if( index == length - 1 )
  434. PopLast();
  435. else if( index < length )
  436. array[index] = PopLast();
  437. }
  438. END_AS_NAMESPACE
  439. #endif