array.inl - Engine C API Reference

array.inl
  1. #include "assert.h"
  2. namespace stingray_plugin_foundation {
  3. template <class T> Array<T>::Array(Allocator &allocator) : _size(0), _capacity(0), _data(0), _allocator(&allocator)
  4. {
  5. }
  6. template <class T> Array<T>::Array(unsigned size, Allocator &allocator) : _size(0), _capacity(0), _data(0), _allocator(&allocator)
  7. {
  8. resize(size);
  9. }
  10. template <class T> Array<T>::Array(const NoAllocator &) : _size(0), _capacity(0), _data(0), _allocator(0)
  11. {
  12. }
  13. template <class T> void Array<T>::set_allocator(Allocator &allocator)
  14. {
  15. _allocator = &allocator;
  16. }
  17. template <class T> Array<T>::Array( const Array<T> &o ) : _size(0), _capacity(0), _data(0), _allocator(o._allocator)
  18. {
  19. set_capacity(o.size());
  20. copy(_data, o._data, o.size());
  21. _size = o.size();
  22. }
  23. template <class T> void Array<T>::operator=(const Array<T> &o)
  24. {
  25. resize(o.size());
  26. copy(_data, o._data, o.size());
  27. }
  28. template <class T> typename Array<T>::reference Array<T>::operator[](unsigned i) {
  29. XENSURE(i < _size);
  30. return _data[i];
  31. }
  32. template <class T> typename Array<T>::const_reference Array<T>::operator[](unsigned i) const {
  33. XENSURE(i < _size);
  34. return _data[i];
  35. }
  36. template <class T> void Array<T>::reserve(unsigned capacity)
  37. {
  38. if (capacity > _capacity)
  39. grow(capacity);
  40. }
  41. template <class T> template <class ASSIGNABLE>
  42. void Array<T>::push_back(const ASSIGNABLE &item)
  43. {
  44. if (_size + 1 > _capacity)
  45. grow();
  46. _data[_size++] = item;
  47. }
  48. template <class T> void Array<T>::pop_back()
  49. {
  50. _size--;
  51. }
  52. template <class T> void Array<T>::swap(Array<T> &o)
  53. {
  54. XENSURE(_allocator == o._allocator);
  55. std::swap(_size, o._size);
  56. std::swap(_capacity, o._capacity);
  57. std::swap(_data, o._data);
  58. std::swap(_allocator, o._allocator);
  59. }
  60. template <class T> template <class ASSIGNABLE>
  61. typename Array<T>::iterator Array<T>::insert(iterator pos, const ASSIGNABLE& x)
  62. {
  63. if (_size + 1 > _capacity) {
  64. unsigned i = (unsigned)(pos - _data);
  65. grow();
  66. pos = _data + i;
  67. }
  68. move(pos + 1, pos, (unsigned)((_data + _size) - pos));
  69. *pos = x;
  70. ++_size;
  71. return pos;
  72. }
  73. template <class T> typename Array<T>::iterator Array<T>::insert(iterator pos)
  74. {
  75. if (_size + 1 > _capacity) {
  76. unsigned i = pos - _data;
  77. grow();
  78. pos = _data + i;
  79. }
  80. move(pos + 1, pos, (_data + _size) - pos);
  81. ++_size;
  82. return pos;
  83. }
  84. template <class T> void Array<T>::insert(iterator pos, const_iterator from, const_iterator to)
  85. {
  86. unsigned add = (unsigned)(to - from);
  87. if (_size + add > _capacity) {
  88. size_t i = pos - _data;
  89. grow(_size + add);
  90. pos = _data + i;
  91. }
  92. move(pos + add, pos, (unsigned)((_data + _size) - pos));
  93. copy(pos, from, add);
  94. _size += add;
  95. }
  96. template <class T> typename Array<T>::iterator Array<T>::erase(iterator pos)
  97. {
  98. XASSERT(pos >= begin() && pos < end(), "Trying to remove outside array.");
  99. move(pos, pos + 1, (unsigned)((_data + _size) - pos - 1));
  100. --_size;
  101. return pos;
  102. }
  103. template <class T> typename Array<T>::iterator Array<T>::erase(iterator first, iterator last)
  104. {
  105. move(first, last, (unsigned)((_data + _size) - last));
  106. _size -= (unsigned)(last - first);
  107. return first;
  108. }
  109. template <class T> template <typename EQUATABLE> void Array<T>::erase(const EQUATABLE &item)
  110. {
  111. iterator it = find(item);
  112. XENSURE(it != end());
  113. erase(it);
  114. }
  115. template <class T> void Array<T>::resize(unsigned size)
  116. {
  117. if (size > _capacity)
  118. grow(size);
  119. _size = size;
  120. }
  121. template <class T> void Array<T>::set_capacity(unsigned capacity)
  122. {
  123. if (capacity == _capacity)
  124. return;
  125. if (capacity < _size)
  126. resize(capacity);
  127. pointer new_data = 0;
  128. if (capacity > 0) {
  129. unsigned align = alignof(value_type) > 4 ? alignof(value_type) : 4;
  130. new_data = (pointer)_allocator->allocate(sizeof(value_type)*capacity, align);
  131. copy(new_data, _data, _size);
  132. }
  133. _allocator->deallocate(_data);
  134. _data = new_data;
  135. _capacity = capacity;
  136. }
  137. template <class T> void Array<T>::move(pointer to, pointer from, unsigned n)
  138. {
  139. memmove((void *)to, (void *)from, sizeof(T) * n);
  140. }
  141. template <class T> void Array<T>::copy(pointer to, const_pointer from, unsigned n)
  142. {
  143. memcpy((void *)to, (void *)from, sizeof(T) * n);
  144. }
  145. template <class T>
  146. template <class STREAM> void Array<T>::serialize(STREAM &stream)
  147. {
  148. unsigned sz = size();
  149. stream & sz;
  150. resize(sz);
  151. for (unsigned i=0; i<sz; ++i)
  152. stream & (*this)[i];
  153. }
  154. template <class STREAM, class T>
  155. void raw_array_serialize(STREAM &s, Array<T> &data)
  156. {
  157. unsigned n = data.size();
  158. s & n;
  159. data.resize(n);
  160. if (n > 0) {
  161. if (s.is_output())
  162. s.write(data.begin(), n * sizeof(T));
  163. else
  164. s.read(data.begin(), n * sizeof(T));
  165. }
  166. }
  167. template <>
  168. template <class STREAM> void Array<char>::serialize(STREAM &stream) {
  169. raw_array_serialize(stream, *this);
  170. }
  171. template <>
  172. template <class STREAM> void Array<uint8_t>::serialize(STREAM &stream) {
  173. raw_array_serialize(stream, *this);
  174. }
  175. template <>
  176. template <class STREAM> void Array<int8_t>::serialize(STREAM &stream) {
  177. raw_array_serialize(stream, *this);
  178. }
  179. template <>
  180. template <class STREAM> void Array<uint16_t>::serialize(STREAM &stream) {
  181. raw_array_serialize(stream, *this);
  182. }
  183. template <>
  184. template <class STREAM> void Array<int16_t>::serialize(STREAM &stream) {
  185. raw_array_serialize(stream, *this);
  186. }
  187. template <>
  188. template <class STREAM> void Array<uint32_t>::serialize(STREAM &stream) {
  189. raw_array_serialize(stream, *this);
  190. }
  191. template <>
  192. template <class STREAM> void Array<int32_t>::serialize(STREAM &stream) {
  193. raw_array_serialize(stream, *this);
  194. }
  195. template <>
  196. template <class STREAM> void Array<int64_t>::serialize(STREAM &stream) {
  197. raw_array_serialize(stream, *this);
  198. }
  199. template <>
  200. template <class STREAM> void Array<uint64_t>::serialize(STREAM &stream) {
  201. raw_array_serialize(stream, *this);
  202. }
  203. template<class T> bool Array<T>::operator==(const Array<T> &o) const
  204. {
  205. if (size() != o.size())
  206. return false;
  207. return memcmp(_data, o._data, sizeof(T)*size()) == 0;
  208. }
  209. template<class T> bool Array<T>::operator<(const Array<T> &o) const
  210. {
  211. if (size() != o.size())
  212. return size() < o.size();
  213. return memcmp(_data, o._data, sizeof(T)*size()) < 0;
  214. }
  215. template <class T> void Array<T>::grow(unsigned min_capacity)
  216. {
  217. uint64_t new_capacity = (uint64_t)_capacity*2 + 10;
  218. if (new_capacity < min_capacity)
  219. new_capacity = min_capacity;
  220. else if (new_capacity > UINT32_MAX)
  221. new_capacity = UINT32_MAX;
  222. set_capacity((unsigned)new_capacity);
  223. }
  224. template <class T> typename Array<T>::pointer Array<T>::steal()
  225. {
  226. pointer return_value = _data;
  227. _data = 0;
  228. _capacity = 0;
  229. _size = 0;
  230. return return_value;
  231. }
  232. } // namespace stingray_plugin_foundation