RingBuffer.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. using System;
  2. using UnityEngine;
  3. namespace Leap.Unity.Graphing
  4. {
  5. public class RingBuffer<T>
  6. {
  7. public RingBuffer(int minCapacity = 8)
  8. {
  9. if (minCapacity <= 0)
  10. {
  11. throw new ArgumentException("Capacity must be positive and nonzero.");
  12. }
  13. int num = Mathf.ClosestPowerOfTwo(minCapacity);
  14. if (num < minCapacity)
  15. {
  16. num *= 2;
  17. }
  18. this._array = new T[num];
  19. this.recalculateIndexMask();
  20. this._front = 0u;
  21. this._count = 0u;
  22. }
  23. public int Count
  24. {
  25. get
  26. {
  27. return (int)this._count;
  28. }
  29. }
  30. public void Clear()
  31. {
  32. if (this._count != 0u)
  33. {
  34. Array.Clear(this._array, 0, this._array.Length);
  35. this._front = 0u;
  36. this._count = 0u;
  37. }
  38. }
  39. public void PushBack(T t)
  40. {
  41. this.doubleCapacityIfFull();
  42. this._count += 1u;
  43. this._array[(int)((UIntPtr)this.getBackIndex())] = t;
  44. }
  45. public void PushFront(T t)
  46. {
  47. this.doubleCapacityIfFull();
  48. this._count += 1u;
  49. this._front = (this._front - 1u & this._indexMask);
  50. this._array[(int)((UIntPtr)this._front)] = t;
  51. }
  52. public void PopBack()
  53. {
  54. this.checkForEmpty("pop back");
  55. this._array[(int)((UIntPtr)this.getBackIndex())] = default(T);
  56. this._count -= 1u;
  57. }
  58. public void PopFront()
  59. {
  60. this.checkForEmpty("pop front");
  61. this._array[(int)((UIntPtr)this._front)] = default(T);
  62. this._count -= 1u;
  63. this._front = (this._front + 1u & this._indexMask);
  64. }
  65. public void PopBack(out T back)
  66. {
  67. this.checkForEmpty("pop back");
  68. uint backIndex = this.getBackIndex();
  69. back = this._array[(int)((UIntPtr)backIndex)];
  70. this._array[(int)((UIntPtr)backIndex)] = default(T);
  71. this._count -= 1u;
  72. }
  73. public void PopFront(out T front)
  74. {
  75. this.checkForEmpty("pop front");
  76. front = this._array[(int)((UIntPtr)this._front)];
  77. this._array[(int)((UIntPtr)this._front)] = default(T);
  78. this._front = (this._front + 1u & this._indexMask);
  79. this._count -= 1u;
  80. }
  81. public T Front
  82. {
  83. get
  84. {
  85. this.checkForEmpty("get front");
  86. return this._array[(int)((UIntPtr)this._front)];
  87. }
  88. set
  89. {
  90. this.checkForEmpty("set front");
  91. this._array[(int)((UIntPtr)this._front)] = value;
  92. }
  93. }
  94. public T Back
  95. {
  96. get
  97. {
  98. this.checkForEmpty("get back");
  99. return this._array[(int)((UIntPtr)this.getBackIndex())];
  100. }
  101. set
  102. {
  103. this.checkForEmpty("set back");
  104. this._array[(int)((UIntPtr)this.getBackIndex())] = value;
  105. }
  106. }
  107. public T this[int index]
  108. {
  109. get
  110. {
  111. this.checkForValidIndex((uint)index);
  112. return this._array[(int)((UIntPtr)this.getIndex((uint)index))];
  113. }
  114. set
  115. {
  116. this.checkForValidIndex((uint)index);
  117. this._array[(int)((UIntPtr)this.getIndex((uint)index))] = value;
  118. }
  119. }
  120. public string ToDebugString()
  121. {
  122. string str = "[";
  123. uint backIndex = this.getBackIndex();
  124. uint num = 0u;
  125. while ((ulong)num < (ulong)((long)this._array.Length))
  126. {
  127. bool flag;
  128. if (this._count == 0u)
  129. {
  130. flag = true;
  131. }
  132. else if (this._count == 1u)
  133. {
  134. flag = (num != this._front);
  135. }
  136. else if (this._front < backIndex)
  137. {
  138. flag = (num < this._front || num > backIndex);
  139. }
  140. else
  141. {
  142. flag = (num < this._front && num > backIndex);
  143. }
  144. string text = string.Empty;
  145. if (num == this._front)
  146. {
  147. text = "{";
  148. }
  149. else
  150. {
  151. text = " ";
  152. }
  153. if (flag)
  154. {
  155. text += ".";
  156. }
  157. else
  158. {
  159. text += this._array[(int)((UIntPtr)num)].ToString();
  160. }
  161. if (num == backIndex)
  162. {
  163. text += "}";
  164. }
  165. else
  166. {
  167. text += " ";
  168. }
  169. str += text;
  170. num += 1u;
  171. }
  172. return str + "]";
  173. }
  174. private uint getBackIndex()
  175. {
  176. return this._front + this._count - 1u & this._indexMask;
  177. }
  178. private uint getIndex(uint index)
  179. {
  180. return this._front + index & this._indexMask;
  181. }
  182. private void doubleCapacityIfFull()
  183. {
  184. if ((ulong)this._count >= (ulong)((long)this._array.Length))
  185. {
  186. T[] array = new T[this._array.Length * 2];
  187. uint backIndex = this.getBackIndex();
  188. if (this._front <= backIndex)
  189. {
  190. Array.Copy(this._array, (long)((ulong)this._front), array, 0L, (long)((ulong)this._count));
  191. }
  192. else
  193. {
  194. uint num = (uint)(this._array.Length - (int)this._front);
  195. Array.Copy(this._array, (long)((ulong)this._front), array, 0L, (long)((ulong)num));
  196. Array.Copy(this._array, 0L, array, (long)((ulong)num), (long)((ulong)(this._count - num)));
  197. }
  198. this._front = 0u;
  199. this._array = array;
  200. this.recalculateIndexMask();
  201. }
  202. }
  203. private void recalculateIndexMask()
  204. {
  205. this._indexMask = (uint)(this._array.Length - 1);
  206. }
  207. private void checkForValidIndex(uint index)
  208. {
  209. if (index >= this._count)
  210. {
  211. throw new IndexOutOfRangeException(string.Concat(new object[]
  212. {
  213. "The index ",
  214. index,
  215. " was out of range for the RingBuffer with size ",
  216. this._count,
  217. "."
  218. }));
  219. }
  220. }
  221. private void checkForEmpty(string actionName)
  222. {
  223. if (this._count == 0u)
  224. {
  225. throw new InvalidOperationException("Cannot " + actionName + " because the RingBuffer is empty.");
  226. }
  227. }
  228. private T[] _array;
  229. private uint _front;
  230. private uint _count;
  231. private uint _indexMask;
  232. }
  233. }