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.

551 lines
12KB

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