Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

432 lines
9.7KB

  1. /**
  2. * Custom modified version of Michael Lyashenko's BetterList
  3. **/
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using UnityEngine;
  8. namespace Svelto.DataStructures
  9. {
  10. public struct FasterListEnumerator<T> : IEnumerator<T>
  11. {
  12. public T Current
  13. {
  14. get { return _current; }
  15. }
  16. object IEnumerator.Current
  17. {
  18. get { return _current; }
  19. }
  20. T IEnumerator<T>.Current
  21. {
  22. get { return _current; }
  23. }
  24. public FasterListEnumerator(T[] buffer, int size)
  25. {
  26. _size = size;
  27. _counter = 0;
  28. _buffer = buffer;
  29. _current = default(T);
  30. }
  31. public void Dispose()
  32. {
  33. _buffer = null;
  34. }
  35. bool IEnumerator.MoveNext()
  36. {
  37. return MoveNext();
  38. }
  39. void IEnumerator.Reset()
  40. {
  41. Reset();
  42. }
  43. public bool MoveNext()
  44. {
  45. if (_counter < _size)
  46. {
  47. _current = _buffer[_counter++];
  48. return true;
  49. }
  50. _current = default(T);
  51. return false;
  52. }
  53. public void Reset()
  54. {
  55. _counter = 0;
  56. }
  57. T[] _buffer;
  58. int _counter;
  59. int _size;
  60. T _current;
  61. }
  62. public struct FasterReadOnlyList<T> : IList<T>
  63. {
  64. public FasterReadOnlyList(FasterList<T> list)
  65. {
  66. _list = list;
  67. }
  68. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  69. {
  70. return GetEnumerator();
  71. }
  72. IEnumerator IEnumerable.GetEnumerator()
  73. {
  74. return GetEnumerator();
  75. }
  76. public FasterListEnumerator<T> GetEnumerator()
  77. {
  78. return _list.GetEnumerator();
  79. }
  80. public void Add(T item)
  81. {
  82. throw new NotImplementedException();
  83. }
  84. public void Clear()
  85. {
  86. throw new NotImplementedException();
  87. }
  88. public bool Contains(T item)
  89. {
  90. return _list.Contains(item);
  91. }
  92. public void CopyTo(T[] array, int arrayIndex)
  93. {
  94. _list.CopyTo(array, arrayIndex);
  95. }
  96. public bool Remove(T item)
  97. {
  98. throw new NotImplementedException();
  99. }
  100. public int Count { get { return _list.Count; } }
  101. public bool IsReadOnly { get { return true; } }
  102. public int IndexOf(T item)
  103. {
  104. return _list.IndexOf(item);
  105. }
  106. public void Insert(int index, T item)
  107. {
  108. throw new NotImplementedException();
  109. }
  110. public void RemoveAt(int index)
  111. {
  112. throw new NotImplementedException();
  113. }
  114. public T this[int index] { get { return _list[index]; } set { throw new NotImplementedException(); } }
  115. readonly FasterList<T> _list;
  116. }
  117. public class FasterList<T> : IList<T>
  118. {
  119. public int Count
  120. {
  121. get { return _count; }
  122. }
  123. public bool IsReadOnly
  124. {
  125. get { return false; }
  126. }
  127. public FasterList()
  128. {
  129. _count = 0;
  130. _buffer = new T[MIN_SIZE];
  131. }
  132. public FasterList(int initialSize)
  133. {
  134. _count = 0;
  135. _buffer = new T[initialSize];
  136. }
  137. public FasterList(ICollection<T> collection)
  138. {
  139. _buffer = new T[collection.Count];
  140. collection.CopyTo(_buffer, 0);
  141. _count = _buffer.Length;
  142. }
  143. public FasterList(FasterList<T> listCopy)
  144. {
  145. _buffer = new T[listCopy.Count];
  146. listCopy.CopyTo(_buffer, 0);
  147. _count = listCopy.Count;
  148. }
  149. public void Add(T item)
  150. {
  151. if (_count == _buffer.Length)
  152. AllocateMore();
  153. _buffer[_count++] = item;
  154. }
  155. public void AddRange(IEnumerable<T> items, int count)
  156. {
  157. if (_count + count >= _buffer.Length)
  158. AllocateMore(_count + count);
  159. for (var i = items.GetEnumerator(); i.MoveNext();)
  160. {
  161. var item = i.Current;
  162. _buffer[_count++] = item;
  163. }
  164. }
  165. public void AddRange(ICollection<T> items)
  166. {
  167. var count = items.Count;
  168. if (_count + count >= _buffer.Length)
  169. AllocateMore(_count + count);
  170. for (var i = items.GetEnumerator(); i.MoveNext();)
  171. {
  172. var item = i.Current;
  173. _buffer[_count++] = item;
  174. }
  175. }
  176. public void AddRange(FasterList<T> items)
  177. {
  178. var count = items.Count;
  179. if (_count + count >= _buffer.Length)
  180. AllocateMore(_count + count);
  181. Array.Copy(items._buffer, 0, _buffer, _count, count);
  182. _count += count;
  183. }
  184. public void AddRange(T[] items)
  185. {
  186. var count = items.Length;
  187. if (_count + count >= _buffer.Length)
  188. AllocateMore(_count + count);
  189. Array.Copy(items, 0, _buffer, _count, count);
  190. _count += count;
  191. }
  192. public FasterReadOnlyList<T> AsReadOnly()
  193. {
  194. return new FasterReadOnlyList<T>(this);
  195. }
  196. public void Clear()
  197. {
  198. _count = 0;
  199. }
  200. public bool Contains(T item)
  201. {
  202. var index = IndexOf(item);
  203. return index != -1;
  204. }
  205. public void CopyTo(T[] array, int arrayIndex)
  206. {
  207. Array.Copy(_buffer, 0, array, arrayIndex, Count);
  208. }
  209. public FasterListEnumerator<T> GetEnumerator()
  210. {
  211. return new FasterListEnumerator<T>(_buffer, Count);
  212. }
  213. IEnumerator IEnumerable.GetEnumerator()
  214. {
  215. return GetEnumerator();
  216. }
  217. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  218. {
  219. return GetEnumerator();
  220. }
  221. public int IndexOf(T item)
  222. {
  223. var comp = EqualityComparer<T>.Default;
  224. for (var index = _count - 1; index >= 0; --index)
  225. if (comp.Equals(_buffer[index], item))
  226. return index;
  227. return -1;
  228. }
  229. public void Insert(int index, T item)
  230. {
  231. DesignByContract.Check.Require(index < _count, "out of bound index");
  232. if (_count == _buffer.Length) AllocateMore();
  233. Array.Copy(_buffer, index, _buffer, index + 1, _count - index);
  234. _buffer[index] = item;
  235. ++_count;
  236. }
  237. public void Release()
  238. {
  239. _count = 0;
  240. _buffer = null;
  241. }
  242. public bool Remove(T item)
  243. {
  244. var index = IndexOf(item);
  245. if (index == -1)
  246. return false;
  247. RemoveAt(index);
  248. return true;
  249. }
  250. public void RemoveAt(int index)
  251. {
  252. DesignByContract.Check.Require(index < _count, "out of bound index");
  253. --_count;
  254. if (index == _count)
  255. return;
  256. Array.Copy(_buffer, index + 1, _buffer, index, _count - index);
  257. }
  258. public void Resize(int newSize)
  259. {
  260. Array.Resize(ref _buffer, newSize);
  261. _count = newSize;
  262. }
  263. public void SetAt(int index, T value)
  264. {
  265. if (index >= _buffer.Length)
  266. AllocateMore(index + 1);
  267. if (_count <= index)
  268. _count = index + 1;
  269. this[index] = value;
  270. }
  271. public void Sort(Comparison<T> comparer)
  272. {
  273. Trim();
  274. Array.Sort(_buffer, comparer);
  275. }
  276. public T[] ToArray()
  277. {
  278. T[] destinationArray = new T[_count];
  279. Array.Copy(_buffer, 0, destinationArray, 0, _count);
  280. return destinationArray;
  281. }
  282. /// <summary>
  283. /// This function exists to allow fast iterations. The size of the array returned cannot be
  284. /// used. The list count must be used instead.
  285. /// </summary>
  286. /// <returns></returns>
  287. public T[] ToArrayFast()
  288. {
  289. return _buffer;
  290. }
  291. public bool UnorderredRemove(T item)
  292. {
  293. var index = IndexOf(item);
  294. if (index == -1)
  295. return false;
  296. UnorderredRemoveAt(index);
  297. return true;
  298. }
  299. public void UnorderredRemoveAt(int index)
  300. {
  301. DesignByContract.Check.Require(index < _count, "out of bound index");
  302. _buffer[index] = _buffer[--_count];
  303. }
  304. private void AllocateMore()
  305. {
  306. var newList = new T[Mathf.Max(_buffer.Length << 1, MIN_SIZE)];
  307. if (_count > 0) _buffer.CopyTo(newList, 0);
  308. _buffer = newList;
  309. }
  310. private void AllocateMore(int newSize)
  311. {
  312. var oldLength = _buffer.Length;
  313. while (oldLength < newSize)
  314. oldLength <<= 1;
  315. var newList = new T[oldLength];
  316. if (_count > 0) _buffer.CopyTo(newList, 0);
  317. _buffer = newList;
  318. }
  319. private void Trim()
  320. {
  321. if (_count < _buffer.Length)
  322. Resize(_count);
  323. }
  324. public T this[int i]
  325. {
  326. get { DesignByContract.Check.Require(i < _count, "out of bound index"); return _buffer[i]; }
  327. set { DesignByContract.Check.Require(i < _count, "out of bound index"); _buffer[i] = value; }
  328. }
  329. private const int MIN_SIZE = 32;
  330. private T[] _buffer;
  331. private int _count;
  332. }
  333. }