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.

585 lines
13KB

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace Svelto.DataStructures
  6. {
  7. public struct FasterListEnumerator<T> : IEnumerator<T>
  8. {
  9. public T Current
  10. {
  11. get { return _current; }
  12. }
  13. public FasterListEnumerator(T[] buffer, int size)
  14. {
  15. _size = size;
  16. _counter = 0;
  17. _buffer = buffer;
  18. _current = default(T);
  19. }
  20. object IEnumerator.Current
  21. {
  22. get { return _current; }
  23. }
  24. T IEnumerator<T>.Current
  25. {
  26. get { return _current; }
  27. }
  28. public void Dispose()
  29. {
  30. _buffer = null;
  31. }
  32. public bool MoveNext()
  33. {
  34. if (_counter < _size)
  35. {
  36. _current = _buffer[_counter++];
  37. return true;
  38. }
  39. _current = default(T);
  40. return false;
  41. }
  42. public void Reset()
  43. {
  44. _counter = 0;
  45. }
  46. bool IEnumerator.MoveNext()
  47. {
  48. return MoveNext();
  49. }
  50. void IEnumerator.Reset()
  51. {
  52. Reset();
  53. }
  54. T[] _buffer;
  55. int _counter;
  56. int _size;
  57. T _current;
  58. }
  59. public struct FasterListEnumeratorCast<T, U> : IEnumerator<T> where T:U
  60. {
  61. public T Current
  62. {
  63. get { return (T)_buffer.Current; }
  64. }
  65. public FasterListEnumeratorCast(FasterListEnumerator<U> buffer)
  66. {
  67. _buffer = buffer;
  68. }
  69. object IEnumerator.Current
  70. {
  71. get { return (T)_buffer.Current; }
  72. }
  73. T IEnumerator<T>.Current
  74. {
  75. get { return (T)_buffer.Current; }
  76. }
  77. public void Dispose()
  78. {}
  79. public bool MoveNext()
  80. {
  81. return _buffer.MoveNext();
  82. }
  83. public void Reset()
  84. {
  85. _buffer.Reset();
  86. }
  87. bool IEnumerator.MoveNext()
  88. {
  89. return MoveNext();
  90. }
  91. void IEnumerator.Reset()
  92. {
  93. Reset();
  94. }
  95. FasterListEnumerator<U> _buffer;
  96. }
  97. public struct FasterReadOnlyList<T> : IList<T>
  98. {
  99. public int Count { get { return _list.Count; } }
  100. public bool IsReadOnly { get { return true; } }
  101. public FasterReadOnlyList(FasterList<T> list)
  102. {
  103. _list = list;
  104. }
  105. public T this[int index] { get { return _list[index]; } set { throw new NotImplementedException(); } }
  106. public FasterListEnumerator<T> GetEnumerator()
  107. {
  108. return _list.GetEnumerator();
  109. }
  110. public void Add(T item)
  111. {
  112. throw new NotImplementedException();
  113. }
  114. public void Clear()
  115. {
  116. throw new NotImplementedException();
  117. }
  118. public bool Contains(T item)
  119. {
  120. return _list.Contains(item);
  121. }
  122. public void CopyTo(T[] array, int arrayIndex)
  123. {
  124. _list.CopyTo(array, arrayIndex);
  125. }
  126. public bool Remove(T item)
  127. {
  128. throw new NotImplementedException();
  129. }
  130. public int IndexOf(T item)
  131. {
  132. return _list.IndexOf(item);
  133. }
  134. public void Insert(int index, T item)
  135. {
  136. throw new NotImplementedException();
  137. }
  138. public void RemoveAt(int index)
  139. {
  140. throw new NotImplementedException();
  141. }
  142. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  143. {
  144. return GetEnumerator();
  145. }
  146. IEnumerator IEnumerable.GetEnumerator()
  147. {
  148. return GetEnumerator();
  149. }
  150. readonly FasterList<T> _list;
  151. }
  152. public struct FasterReadOnlyListCast<T, U> : IList<U> where U:T
  153. {
  154. public static FasterList<T> DefaultList = new FasterList<T>();
  155. public int Count { get { return _list.Count; } }
  156. public bool IsReadOnly { get { return true; } }
  157. public FasterReadOnlyListCast(FasterList<T> list)
  158. {
  159. _list = list;
  160. }
  161. public U this[int index] { get { return (U)_list[index]; } set { throw new NotImplementedException(); } }
  162. public FasterListEnumeratorCast<U, T> GetEnumerator()
  163. {
  164. return new FasterListEnumeratorCast<U, T>(_list.GetEnumerator());
  165. }
  166. public void Add(U item)
  167. {
  168. throw new NotImplementedException();
  169. }
  170. public void Clear()
  171. {
  172. throw new NotImplementedException();
  173. }
  174. public bool Contains(U item)
  175. {
  176. return _list.Contains(item);
  177. }
  178. public void CopyTo(U[] array, int arrayIndex)
  179. {
  180. throw new NotImplementedException();
  181. }
  182. public bool Remove(U item)
  183. {
  184. throw new NotImplementedException();
  185. }
  186. public int IndexOf(U item)
  187. {
  188. return _list.IndexOf(item);
  189. }
  190. public void Insert(int index, U item)
  191. {
  192. throw new NotImplementedException();
  193. }
  194. public void RemoveAt(int index)
  195. {
  196. throw new NotImplementedException();
  197. }
  198. IEnumerator<U> IEnumerable<U>.GetEnumerator()
  199. {
  200. return GetEnumerator();
  201. }
  202. IEnumerator IEnumerable.GetEnumerator()
  203. {
  204. return GetEnumerator();
  205. }
  206. readonly FasterList<T> _list;
  207. }
  208. public class FasterList<T> : IList<T>
  209. {
  210. const int MIN_SIZE = 4;
  211. public int Count
  212. {
  213. get { return _count; }
  214. }
  215. public bool IsReadOnly
  216. {
  217. get { return false; }
  218. }
  219. public FasterList()
  220. {
  221. _count = 0;
  222. _buffer = new T[MIN_SIZE];
  223. }
  224. public FasterList(int initialSize)
  225. {
  226. _count = 0;
  227. _buffer = new T[initialSize];
  228. }
  229. public FasterList(ICollection<T> collection)
  230. {
  231. _buffer = new T[collection.Count];
  232. collection.CopyTo(_buffer, 0);
  233. _count = _buffer.Length;
  234. }
  235. public FasterList(FasterList<T> listCopy)
  236. {
  237. _buffer = new T[listCopy.Count];
  238. listCopy.CopyTo(_buffer, 0);
  239. _count = listCopy.Count;
  240. }
  241. public T this[int i]
  242. {
  243. get { DesignByContract.Check.Require(i < _count, "out of bound index"); return _buffer[i]; }
  244. set { DesignByContract.Check.Require(i < _count, "out of bound index"); _buffer[i] = value; }
  245. }
  246. public void Add(T item)
  247. {
  248. if (_count == _buffer.Length)
  249. AllocateMore();
  250. _buffer[_count++] = item;
  251. }
  252. public static FasterList<T> PreFill<U>(int initialSize) where U:T, new()
  253. {
  254. var list = new FasterList<T>(initialSize);
  255. for (int i = 0; i < initialSize; i++)
  256. list.Add(new U());
  257. list.Clear();
  258. return list;
  259. }
  260. public void AddRange(IEnumerable<T> items, int count)
  261. {
  262. AddRange(items.GetEnumerator(), count);
  263. }
  264. public void AddRange(IEnumerator<T> items, int count)
  265. {
  266. if (_count + count >= _buffer.Length)
  267. AllocateMore(_count + count);
  268. while (items.MoveNext())
  269. _buffer[_count++] = items.Current;
  270. }
  271. public void AddRange(ICollection<T> items)
  272. {
  273. AddRange(items.GetEnumerator(), items.Count);
  274. }
  275. public void AddRange(FasterList<T> items)
  276. {
  277. AddRange(items.ToArrayFast(), items.Count);
  278. }
  279. public void AddRange(T[] items, int count)
  280. {
  281. if (count == 0) return;
  282. if (_count + count >= _buffer.Length)
  283. AllocateMore(_count + count);
  284. Array.Copy(items, 0, _buffer, _count, count);
  285. _count += count;
  286. }
  287. public FasterReadOnlyList<T> AsReadOnly()
  288. {
  289. return new FasterReadOnlyList<T>(this);
  290. }
  291. /// <summary>
  292. /// Careful, you could keep on holding references you don't want to hold to anymore
  293. /// Use DeepClear in case.
  294. /// </summary>
  295. public void Clear()
  296. {
  297. _count = 0;
  298. }
  299. public void DeepClear()
  300. {
  301. Array.Clear(_buffer, 0, _buffer.Length);
  302. _count = 0;
  303. }
  304. public bool Contains(T item)
  305. {
  306. var index = IndexOf(item);
  307. return index != -1;
  308. }
  309. public void CopyTo(T[] array, int arrayIndex)
  310. {
  311. Array.Copy(_buffer, 0, array, arrayIndex, Count);
  312. }
  313. public FasterListEnumerator<T> GetEnumerator()
  314. {
  315. return new FasterListEnumerator<T>(_buffer, Count);
  316. }
  317. public int IndexOf(T item)
  318. {
  319. var comp = EqualityComparer<T>.Default;
  320. for (var index = _count - 1; index >= 0; --index)
  321. if (comp.Equals(_buffer[index], item))
  322. return index;
  323. return -1;
  324. }
  325. public void Insert(int index, T item)
  326. {
  327. DesignByContract.Check.Require(index < _count, "out of bound index");
  328. if (_count == _buffer.Length) AllocateMore();
  329. Array.Copy(_buffer, index, _buffer, index + 1, _count - index);
  330. _buffer[index] = item;
  331. ++_count;
  332. }
  333. public void Release()
  334. {
  335. _count = 0;
  336. _buffer = null;
  337. }
  338. public bool Remove(T item)
  339. {
  340. var index = IndexOf(item);
  341. if (index == -1)
  342. return false;
  343. RemoveAt(index);
  344. return true;
  345. }
  346. public void RemoveAt(int index)
  347. {
  348. DesignByContract.Check.Require(index < _count, "out of bound index");
  349. if (index == --_count)
  350. return;
  351. Array.Copy(_buffer, index + 1, _buffer, index, _count - index);
  352. _buffer[_count] = default(T);
  353. }
  354. public void Resize(int newSize)
  355. {
  356. if (newSize < MIN_SIZE)
  357. newSize = MIN_SIZE;
  358. Array.Resize(ref _buffer, newSize);
  359. _count = newSize;
  360. }
  361. public void SetAt(int index, T value)
  362. {
  363. if (index >= _buffer.Length)
  364. AllocateMore(index + 1);
  365. if (_count <= index)
  366. _count = index + 1;
  367. this[index] = value;
  368. }
  369. public void Sort(IComparer<T> comparer)
  370. {
  371. Array.Sort(_buffer, 0, _count, comparer);
  372. }
  373. public T[] ToArray()
  374. {
  375. T[] destinationArray = new T[_count];
  376. Array.Copy(_buffer, 0, destinationArray, 0, _count);
  377. return destinationArray;
  378. }
  379. /// <summary>
  380. /// This function exists to allow fast iterations. The size of the array returned cannot be
  381. /// used. The list count must be used instead.
  382. /// </summary>
  383. /// <returns></returns>
  384. public T[] ToArrayFast()
  385. {
  386. return _buffer;
  387. }
  388. public bool UnorderredRemove(T item)
  389. {
  390. var index = IndexOf(item);
  391. if (index == -1)
  392. return false;
  393. UnorderredRemoveAt(index);
  394. return true;
  395. }
  396. public T UnorderredRemoveAt(int index)
  397. {
  398. DesignByContract.Check.Require(index < _count && _count > 0, "out of bound index");
  399. T item = _buffer[index];
  400. if (index == --_count)
  401. return item;
  402. T swap = _buffer[index];
  403. _buffer[index] = _buffer[_count];
  404. _buffer[_count] = swap;
  405. return item;
  406. }
  407. IEnumerator IEnumerable.GetEnumerator()
  408. {
  409. return GetEnumerator();
  410. }
  411. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  412. {
  413. return GetEnumerator();
  414. }
  415. void AllocateMore()
  416. {
  417. var newList = new T[Mathf.Max(_buffer.Length << 1, MIN_SIZE)];
  418. if (_count > 0) _buffer.CopyTo(newList, 0);
  419. _buffer = newList;
  420. }
  421. void AllocateMore(int newSize)
  422. {
  423. var oldLength = Mathf.Max(_buffer.Length, MIN_SIZE);
  424. while (oldLength < newSize)
  425. oldLength <<= 1;
  426. var newList = new T[oldLength];
  427. if (_count > 0) Array.Copy(_buffer, newList, _count);
  428. _buffer = newList;
  429. }
  430. public void Trim()
  431. {
  432. if (_count < _buffer.Length)
  433. Resize(_count);
  434. }
  435. public bool Reuse(int index, out T result)
  436. {
  437. result = default(T);
  438. if (index >= _buffer.Length)
  439. return false;
  440. result = _buffer[index];
  441. return result != null;
  442. }
  443. T[] _buffer;
  444. int _count;
  445. }
  446. }