as_array.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2012 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(int 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. void SetLength(size_t numElements);
  46. void 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. const T &operator [](size_t index) const;
  51. T &operator [](size_t index);
  52. T *AddressOf();
  53. const T *AddressOf() const;
  54. void Concatenate(const asCArray<T> &);
  55. void Concatenate(T*, unsigned int count);
  56. bool Exists(T &element) const;
  57. int IndexOf(T &element) const;
  58. void RemoveIndex(size_t index); // Removes the entry without reordering the array
  59. void RemoveValue(const T &element);
  60. bool operator==(const asCArray<T> &) const;
  61. bool operator!=(const asCArray<T> &) const;
  62. protected:
  63. T *array;
  64. size_t length;
  65. size_t maxLength;
  66. char buf[8];
  67. };
  68. // Implementation
  69. template <class T>
  70. T *asCArray<T>::AddressOf()
  71. {
  72. return array;
  73. }
  74. template <class T>
  75. const T *asCArray<T>::AddressOf() const
  76. {
  77. return array;
  78. }
  79. template <class T>
  80. asCArray<T>::asCArray(void)
  81. {
  82. array = 0;
  83. length = 0;
  84. maxLength = 0;
  85. }
  86. template <class T>
  87. asCArray<T>::asCArray(const asCArray<T> &copy)
  88. {
  89. array = 0;
  90. length = 0;
  91. maxLength = 0;
  92. *this = copy;
  93. }
  94. template <class T>
  95. asCArray<T>::asCArray(int reserve)
  96. {
  97. array = 0;
  98. length = 0;
  99. maxLength = 0;
  100. Allocate(reserve, false);
  101. }
  102. template <class T>
  103. asCArray<T>::~asCArray(void)
  104. {
  105. // Allocating a zero length array will free all memory
  106. Allocate(0,0);
  107. }
  108. template <class T>
  109. size_t asCArray<T>::GetLength() const
  110. {
  111. return length;
  112. }
  113. template <class T>
  114. const T &asCArray<T>::operator [](size_t index) const
  115. {
  116. asASSERT(index < length);
  117. return array[index];
  118. }
  119. template <class T>
  120. T &asCArray<T>::operator [](size_t index)
  121. {
  122. asASSERT(index < length);
  123. return array[index];
  124. }
  125. template <class T>
  126. void asCArray<T>::PushLast(const T &element)
  127. {
  128. if( length == maxLength )
  129. {
  130. if( maxLength == 0 )
  131. Allocate(1, false);
  132. else
  133. Allocate(2*maxLength, true);
  134. if( length == maxLength )
  135. {
  136. // Out of memory. Return without doing anything
  137. return;
  138. }
  139. }
  140. array[length++] = element;
  141. }
  142. template <class T>
  143. T asCArray<T>::PopLast()
  144. {
  145. asASSERT(length > 0);
  146. return array[--length];
  147. }
  148. template <class T>
  149. void asCArray<T>::Allocate(size_t numElements, bool keepData)
  150. {
  151. // We have 4 situations
  152. // 1. The previous array is 8 bytes or smaller and the new array is also 8 bytes or smaller
  153. // 2. The previous array is 8 bytes or smaller and the new array is larger than 8 bytes
  154. // 3. The previous array is larger than 8 bytes and the new array is 8 bytes or smaller
  155. // 4. The previous array is larger than 8 bytes and the new array is also larger than 8 bytes
  156. T *tmp = 0;
  157. if( numElements )
  158. {
  159. if( sizeof(T)*numElements <= 8 )
  160. // Use the internal buffer
  161. tmp = (T*)buf;
  162. else
  163. {
  164. // Allocate the array and construct each of the elements
  165. tmp = asNEWARRAY(T,numElements);
  166. if( tmp == 0 )
  167. {
  168. // Out of memory. Return without doing anything
  169. return;
  170. }
  171. }
  172. if( array == tmp )
  173. {
  174. // Construct only the newly allocated elements
  175. for( size_t n = length; n < numElements; n++ )
  176. new (&tmp[n]) T();
  177. }
  178. else
  179. {
  180. // Construct all elements
  181. for( size_t n = 0; n < numElements; n++ )
  182. new (&tmp[n]) T();
  183. }
  184. }
  185. if( array )
  186. {
  187. size_t oldLength = length;
  188. if( array == tmp )
  189. {
  190. if( keepData )
  191. {
  192. if( length > numElements )
  193. length = numElements;
  194. }
  195. else
  196. length = 0;
  197. // Call the destructor for elements that are no longer used
  198. for( size_t n = length; n < oldLength; n++ )
  199. array[n].~T();
  200. }
  201. else
  202. {
  203. if( keepData )
  204. {
  205. if( length > numElements )
  206. length = numElements;
  207. for( size_t n = 0; n < length; n++ )
  208. tmp[n] = array[n];
  209. }
  210. else
  211. length = 0;
  212. // Call the destructor for all elements
  213. for( size_t n = 0; n < oldLength; n++ )
  214. array[n].~T();
  215. if( array != (T*)buf )
  216. asDELETEARRAY(array);
  217. }
  218. }
  219. array = tmp;
  220. maxLength = numElements;
  221. }
  222. template <class T>
  223. void asCArray<T>::AllocateNoConstruct(size_t numElements, bool keepData)
  224. {
  225. // We have 4 situations
  226. // 1. The previous array is 8 bytes or smaller and the new array is also 8 bytes or smaller
  227. // 2. The previous array is 8 bytes or smaller and the new array is larger than 8 bytes
  228. // 3. The previous array is larger than 8 bytes and the new array is 8 bytes or smaller
  229. // 4. The previous array is larger than 8 bytes and the new array is also larger than 8 bytes
  230. T *tmp = 0;
  231. if( numElements )
  232. {
  233. if( sizeof(T)*numElements <= 8 )
  234. // Use the internal buffer
  235. tmp = (T*)buf;
  236. else
  237. {
  238. // Allocate the array and construct each of the elements
  239. tmp = asNEWARRAY(T,numElements);
  240. if( tmp == 0 )
  241. {
  242. // Out of memory. Return without doing anything
  243. return;
  244. }
  245. }
  246. }
  247. if( array )
  248. {
  249. if( array == tmp )
  250. {
  251. if( keepData )
  252. {
  253. if( length > numElements )
  254. length = numElements;
  255. }
  256. else
  257. length = 0;
  258. }
  259. else
  260. {
  261. if( keepData )
  262. {
  263. if( length > numElements )
  264. length = numElements;
  265. memcpy(tmp, array, sizeof(T)*length);
  266. }
  267. else
  268. length = 0;
  269. if( array != (T*)buf )
  270. asDELETEARRAY(array);
  271. }
  272. }
  273. array = tmp;
  274. maxLength = numElements;
  275. }
  276. template <class T>
  277. size_t asCArray<T>::GetCapacity() const
  278. {
  279. return maxLength;
  280. }
  281. template <class T>
  282. void asCArray<T>::SetLength(size_t numElements)
  283. {
  284. if( numElements > maxLength )
  285. {
  286. Allocate(numElements, true);
  287. if( numElements > maxLength )
  288. {
  289. // Out of memory. Return without doing anything
  290. return;
  291. }
  292. }
  293. length = numElements;
  294. }
  295. template <class T>
  296. void asCArray<T>::SetLengthNoConstruct(size_t numElements)
  297. {
  298. if( numElements > maxLength )
  299. {
  300. AllocateNoConstruct(numElements, true);
  301. if( numElements > maxLength )
  302. {
  303. // Out of memory. Return without doing anything
  304. return;
  305. }
  306. }
  307. length = numElements;
  308. }
  309. template <class T>
  310. void asCArray<T>::Copy(const T *data, size_t count)
  311. {
  312. if( maxLength < count )
  313. {
  314. Allocate(count, false);
  315. if( maxLength < count )
  316. {
  317. // Out of memory. Return without doing anything
  318. return;
  319. }
  320. }
  321. for( size_t n = 0; n < count; n++ )
  322. array[n] = data[n];
  323. length = count;
  324. }
  325. template <class T>
  326. asCArray<T> &asCArray<T>::operator =(const asCArray<T> &copy)
  327. {
  328. Copy(copy.array, copy.length);
  329. return *this;
  330. }
  331. template <class T>
  332. bool asCArray<T>::operator ==(const asCArray<T> &other) const
  333. {
  334. if( length != other.length ) return false;
  335. for( asUINT n = 0; n < length; n++ )
  336. if( array[n] != other.array[n] )
  337. return false;
  338. return true;
  339. }
  340. template <class T>
  341. bool asCArray<T>::operator !=(const asCArray<T> &other) const
  342. {
  343. return !(*this == other);
  344. }
  345. template <class T>
  346. void asCArray<T>::Concatenate(const asCArray<T> &other)
  347. {
  348. if( maxLength < length + other.length )
  349. Allocate(length + other.length, true);
  350. for( size_t n = 0; n < other.length; n++ )
  351. array[length+n] = other.array[n];
  352. length += other.length;
  353. }
  354. template <class T>
  355. void asCArray<T>::Concatenate(T* array, unsigned int count)
  356. {
  357. for( unsigned int c = 0; c < count; c++ )
  358. PushLast(array[c]);
  359. }
  360. template <class T>
  361. bool asCArray<T>::Exists(T &e) const
  362. {
  363. return IndexOf(e) == -1 ? false : true;
  364. }
  365. template <class T>
  366. int asCArray<T>::IndexOf(T &e) const
  367. {
  368. for( size_t n = 0; n < length; n++ )
  369. if( array[n] == e ) return (int)n;
  370. return -1;
  371. }
  372. template <class T>
  373. void asCArray<T>::RemoveIndex(size_t index)
  374. {
  375. if( index < length )
  376. {
  377. for( size_t n = index; n < length-1; n++ )
  378. array[n] = array[n+1];
  379. PopLast();
  380. }
  381. }
  382. template <class T>
  383. void asCArray<T>::RemoveValue(const T &e)
  384. {
  385. for( size_t n = 0; n < length; n++ )
  386. {
  387. if( array[n] == e )
  388. {
  389. RemoveIndex(n);
  390. break;
  391. }
  392. }
  393. }
  394. END_AS_NAMESPACE
  395. #endif