as_array.h 8.9 KB

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