as_array.h 7.4 KB

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