BetterList.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. //----------------------------------------------
  2. // NGUI: Next-Gen UI kit
  3. // Copyright © 2011-2014 Tasharen Entertainment
  4. //----------------------------------------------
  5. using UnityEngine;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. /// <summary>
  9. /// This improved version of the System.Collections.Generic.List that doesn't release the buffer on Clear(),
  10. /// resulting in better performance and less garbage collection.
  11. /// PRO: BetterList performs faster than List when you Add and Remove items (although slower if you remove from the beginning).
  12. /// CON: BetterList performs worse when sorting the list. If your operations involve sorting, use the standard List instead.
  13. /// </summary>
  14. public class BetterList<T>
  15. {
  16. #if UNITY_FLASH
  17. List<T> mList = new List<T>();
  18. /// <summary>
  19. /// Direct access to the buffer. Note that you should not use its 'Length' parameter, but instead use BetterList.size.
  20. /// </summary>
  21. public T this[int i]
  22. {
  23. get { return mList[i]; }
  24. set { mList[i] = value; }
  25. }
  26. /// <summary>
  27. /// Compatibility with the non-flash syntax.
  28. /// </summary>
  29. public List<T> buffer { get { return mList; } }
  30. /// <summary>
  31. /// Direct access to the buffer's size. Note that it's only public for speed and efficiency. You shouldn't modify it.
  32. /// </summary>
  33. public int size { get { return mList.Count; } }
  34. /// <summary>
  35. /// For 'foreach' functionality.
  36. /// </summary>
  37. public IEnumerator<T> GetEnumerator () { return mList.GetEnumerator(); }
  38. /// <summary>
  39. /// Clear the array by resetting its size to zero. Note that the memory is not actually released.
  40. /// </summary>
  41. public void Clear () { mList.Clear(); }
  42. /// <summary>
  43. /// Clear the array and release the used memory.
  44. /// </summary>
  45. public void Release () { mList.Clear(); }
  46. /// <summary>
  47. /// Add the specified item to the end of the list.
  48. /// </summary>
  49. public void Add (T item) { mList.Add(item); }
  50. /// <summary>
  51. /// Insert an item at the specified index, pushing the entries back.
  52. /// </summary>
  53. public void Insert (int index, T item)
  54. {
  55. if (index > -1 && index < mList.Count) mList.Insert(index, item);
  56. else mList.Add(item);
  57. }
  58. /// <summary>
  59. /// Returns 'true' if the specified item is within the list.
  60. /// </summary>
  61. public bool Contains (T item) { return mList.Contains(item); }
  62. /// <summary>
  63. /// Return the index of the specified item.
  64. /// </summary>
  65. public int IndexOf (T item) { return mList.IndexOf(item); }
  66. /// <summary>
  67. /// Remove the specified item from the list. Note that RemoveAt() is faster and is advisable if you already know the index.
  68. /// </summary>
  69. public bool Remove (T item) { return mList.Remove(item); }
  70. /// <summary>
  71. /// Remove an item at the specified index.
  72. /// </summary>
  73. public void RemoveAt (int index) { mList.RemoveAt(index); }
  74. /// <summary>
  75. /// Remove an item from the end.
  76. /// </summary>
  77. public T Pop ()
  78. {
  79. if (buffer != null && size != 0)
  80. {
  81. T val = buffer[mList.Count - 1];
  82. mList.RemoveAt(mList.Count - 1);
  83. return val;
  84. }
  85. return default(T);
  86. }
  87. /// <summary>
  88. /// Mimic List's ToArray() functionality, except that in this case the list is resized to match the current size.
  89. /// </summary>
  90. public T[] ToArray () { return mList.ToArray(); }
  91. /// <summary>
  92. /// List.Sort equivalent.
  93. /// </summary>
  94. public void Sort (System.Comparison<T> comparer) { mList.Sort(comparer); }
  95. #else
  96. /// <summary>
  97. /// Direct access to the buffer. Note that you should not use its 'Length' parameter, but instead use BetterList.size.
  98. /// </summary>
  99. public T[] buffer;
  100. /// <summary>
  101. /// Direct access to the buffer's size. Note that it's only public for speed and efficiency. You shouldn't modify it.
  102. /// </summary>
  103. public int size = 0;
  104. /// <summary>
  105. /// For 'foreach' functionality.
  106. /// </summary>
  107. [DebuggerHidden]
  108. [DebuggerStepThrough]
  109. public IEnumerator<T> GetEnumerator()
  110. {
  111. if (buffer != null)
  112. {
  113. for (int i = 0; i < size; ++i)
  114. {
  115. yield return buffer[i];
  116. }
  117. }
  118. }
  119. /// <summary>
  120. /// Convenience function. I recommend using .buffer instead.
  121. /// </summary>
  122. [DebuggerHidden]
  123. public T this[int i]
  124. {
  125. get { return buffer[i]; }
  126. set { buffer[i] = value; }
  127. }
  128. /// <summary>
  129. /// Helper function that expands the size of the array, maintaining the content.
  130. /// </summary>
  131. void AllocateMore()
  132. {
  133. T[] newList = (buffer != null) ? new T[Mathf.Max(buffer.Length << 1, 32)] : new T[32];
  134. if (buffer != null && size > 0) buffer.CopyTo(newList, 0);
  135. buffer = newList;
  136. }
  137. /// <summary>
  138. /// Trim the unnecessary memory, resizing the buffer to be of 'Length' size.
  139. /// Call this function only if you are sure that the buffer won't need to resize anytime soon.
  140. /// </summary>
  141. void Trim()
  142. {
  143. if (size > 0)
  144. {
  145. if (size < buffer.Length)
  146. {
  147. T[] newList = new T[size];
  148. for (int i = 0; i < size; ++i) newList[i] = buffer[i];
  149. buffer = newList;
  150. }
  151. }
  152. else buffer = null;
  153. }
  154. /// <summary>
  155. /// Clear the array by resetting its size to zero. Note that the memory is not actually released.
  156. /// </summary>
  157. public void Clear() { size = 0; }
  158. /// <summary>
  159. /// Clear the array and release the used memory.
  160. /// </summary>
  161. public void Release() { size = 0; buffer = null; }
  162. /// <summary>
  163. /// Add the specified item to the end of the list.
  164. /// </summary>
  165. public void Add(T item)
  166. {
  167. if (buffer == null || size == buffer.Length) AllocateMore();
  168. buffer[size++] = item;
  169. }
  170. /// <summary>
  171. /// Insert an item at the specified index, pushing the entries back.
  172. /// </summary>
  173. public void Insert(int index, T item)
  174. {
  175. if (buffer == null || size == buffer.Length) AllocateMore();
  176. if (index > -1 && index < size)
  177. {
  178. for (int i = size; i > index; --i) buffer[i] = buffer[i - 1];
  179. buffer[index] = item;
  180. ++size;
  181. }
  182. else Add(item);
  183. }
  184. /// <summary>
  185. /// Returns 'true' if the specified item is within the list.
  186. /// </summary>
  187. public bool Contains(T item)
  188. {
  189. if (buffer == null) return false;
  190. for (int i = 0; i < size; ++i) if (buffer[i].Equals(item)) return true;
  191. return false;
  192. }
  193. /// <summary>
  194. /// Return the index of the specified item.
  195. /// </summary>
  196. public int IndexOf(T item)
  197. {
  198. if (buffer == null) return -1;
  199. for (int i = 0; i < size; ++i) if (buffer[i].Equals(item)) return i;
  200. return -1;
  201. }
  202. /// <summary>
  203. /// Remove the specified item from the list. Note that RemoveAt() is faster and is advisable if you already know the index.
  204. /// </summary>
  205. public bool Remove(T item)
  206. {
  207. if (buffer != null)
  208. {
  209. EqualityComparer<T> comp = EqualityComparer<T>.Default;
  210. for (int i = 0; i < size; ++i)
  211. {
  212. if (comp.Equals(buffer[i], item))
  213. {
  214. --size;
  215. buffer[i] = default(T);
  216. for (int b = i; b < size; ++b) buffer[b] = buffer[b + 1];
  217. buffer[size] = default(T);
  218. return true;
  219. }
  220. }
  221. }
  222. return false;
  223. }
  224. /// <summary>
  225. /// Remove an item at the specified index.
  226. /// </summary>
  227. public void RemoveAt(int index)
  228. {
  229. if (buffer != null && index > -1 && index < size)
  230. {
  231. --size;
  232. buffer[index] = default(T);
  233. for (int b = index; b < size; ++b) buffer[b] = buffer[b + 1];
  234. buffer[size] = default(T);
  235. }
  236. }
  237. /// <summary>
  238. /// Remove an item from the end.
  239. /// </summary>
  240. public T Pop()
  241. {
  242. if (buffer != null && size != 0)
  243. {
  244. T val = buffer[--size];
  245. buffer[size] = default(T);
  246. return val;
  247. }
  248. return default(T);
  249. }
  250. /// <summary>
  251. /// Mimic List's ToArray() functionality, except that in this case the list is resized to match the current size.
  252. /// </summary>
  253. public T[] ToArray() { Trim(); return buffer; }
  254. //class Comparer : System.Collections.IComparer
  255. //{
  256. // public System.Comparison<T> func;
  257. // public int Compare (object x, object y) { return func((T)x, (T)y); }
  258. //}
  259. //Comparer mComp = new Comparer();
  260. /// <summary>
  261. /// List.Sort equivalent. Doing Array.Sort causes GC allocations.
  262. /// </summary>
  263. //public void Sort (System.Comparison<T> comparer)
  264. //{
  265. // if (size > 0)
  266. // {
  267. // mComp.func = comparer;
  268. // System.Array.Sort(buffer, 0, size, mComp);
  269. // }
  270. //}
  271. /// <summary>
  272. /// List.Sort equivalent. Manual sorting causes no GC allocations.
  273. /// </summary>
  274. [DebuggerHidden]
  275. [DebuggerStepThrough]
  276. public void Sort(CompareFunc comparer)
  277. {
  278. int start = 0;
  279. int max = size - 1;
  280. bool changed = true;
  281. while (changed)
  282. {
  283. changed = false;
  284. for (int i = start; i < max; ++i)
  285. {
  286. // Compare the two values
  287. if (comparer(buffer[i], buffer[i + 1]) > 0)
  288. {
  289. // Swap the values
  290. T temp = buffer[i];
  291. buffer[i] = buffer[i + 1];
  292. buffer[i + 1] = temp;
  293. changed = true;
  294. }
  295. else if (!changed)
  296. {
  297. // Nothing has changed -- we can start here next time
  298. start = (i == 0) ? 0 : i - 1;
  299. }
  300. }
  301. }
  302. }
  303. /// <summary>
  304. /// Comparison function should return -1 if left is less than right, 1 if left is greater than right, and 0 if they match.
  305. /// </summary>
  306. public delegate int CompareFunc(T left, T right);
  307. #endif
  308. }