Int32Map.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace FontStashSharp
  5. {
  6. class ThrowHelper
  7. {
  8. public static void KeyNotFoundException()
  9. {
  10. throw new KeyNotFoundException();
  11. }
  12. public static void ArgumentOutOfRangeException()
  13. {
  14. throw new ArgumentOutOfRangeException();
  15. }
  16. public static void InvalidOperationException()
  17. {
  18. throw new InvalidOperationException();
  19. }
  20. public static void ArgumentException()
  21. {
  22. throw new ArgumentException();
  23. }
  24. }
  25. class SizingHelper
  26. {
  27. static readonly int[] Primes = {
  28. 3, 5, 7, 11, 17, 23, 37, 53, 79, 113, 163, 229, 331, 463, 653, 919, 1289, 1811, 2539, 3557, 4987, 6983, 9781, 13693, 19181, 26861, 37607, 52667, 73751, 103289,
  29. 144611, 202471, 283463, 396871, 555637, 777901, 1089091, 1524763, 2134697, 2988607, 4184087, 5857727, 8200847, 11481199, 16073693, 22503181, 31504453, 44106241,
  30. 61748749, 86448259, 121027583, 169438627, 237214097, 332099741, 464939639, 650915521, 911281733, 1275794449, 1786112231
  31. };
  32. public static int GetSizingPrime(int min)
  33. {
  34. for (var index = 0; index < Primes.Length; ++index)
  35. {
  36. var num = Primes[index];
  37. if (num >= min)
  38. return num;
  39. }
  40. throw new Exception("Trying to find a too large prime.");
  41. }
  42. public static int NextSizingPrime(int min)
  43. {
  44. for (var index = 0; index < Primes.Length; ++index)
  45. {
  46. var num = Primes[index];
  47. if (num > min)
  48. return num;
  49. }
  50. throw new Exception("Trying to find a too large prime.");
  51. }
  52. }
  53. public class Int32Map<TValue> : IEnumerable<KeyValuePair<int, TValue>>
  54. {
  55. int[] _buckets;
  56. Entry[] _entries;
  57. int _count;
  58. int _version;
  59. int _freeList;
  60. int _freeCount;
  61. public Int32Map() : this(0) { }
  62. public Int32Map(int capacity)
  63. {
  64. if (capacity < 0)
  65. ThrowHelper.ArgumentOutOfRangeException();
  66. if (capacity > 0)
  67. Initialize(capacity);
  68. }
  69. public int Count
  70. {
  71. get { return _count - _freeCount; }
  72. }
  73. public TValue this[int key]
  74. {
  75. get
  76. {
  77. unchecked
  78. {
  79. if (_buckets != null)
  80. {
  81. var num = key & int.MaxValue;
  82. for (var index = _buckets[num % _buckets.Length]; index >= 0; index = _entries[index].Next)
  83. if (_entries[index].Key == key)
  84. return _entries[index].Value;
  85. }
  86. ThrowHelper.KeyNotFoundException();
  87. return default(TValue);
  88. }
  89. }
  90. set { Insert(key, value, false); }
  91. }
  92. IEnumerator<KeyValuePair<int, TValue>> IEnumerable<KeyValuePair<int, TValue>>.GetEnumerator()
  93. {
  94. return GetEnumerator();
  95. }
  96. IEnumerator IEnumerable.GetEnumerator()
  97. {
  98. throw new NotImplementedException();
  99. }
  100. public void Add(int key, TValue value)
  101. {
  102. Insert(key, value, true);
  103. }
  104. public void Clear()
  105. {
  106. if (_count <= 0)
  107. return;
  108. for (var index = 0; index < _buckets.Length; ++index)
  109. _buckets[index] = -1;
  110. Array.Clear(_entries, 0, _count);
  111. _freeList = -1;
  112. _count = 0;
  113. _freeCount = 0;
  114. _version = _version + 1;
  115. }
  116. public bool ContainsKey(int key)
  117. {
  118. return FindEntry(key) >= 0;
  119. }
  120. int FindEntry(int key)
  121. {
  122. unchecked
  123. {
  124. if (_buckets != null)
  125. {
  126. var num = key & int.MaxValue;
  127. for (var index = _buckets[num % _buckets.Length]; index >= 0; index = _entries[index].Next)
  128. if (_entries[index].Key == key)
  129. return index;
  130. }
  131. return -1;
  132. }
  133. }
  134. void Initialize(int capacity)
  135. {
  136. var prime = SizingHelper.GetSizingPrime(capacity);
  137. _buckets = new int[prime];
  138. for (var index = 0; index < _buckets.Length; ++index)
  139. _buckets[index] = -1;
  140. _entries = new Entry[prime];
  141. _freeList = -1;
  142. }
  143. void Insert(int key, TValue value, bool add)
  144. {
  145. unchecked
  146. {
  147. if (_buckets == null)
  148. Initialize(0);
  149. var num1 = key & int.MaxValue;
  150. var index1 = num1 % _buckets.Length;
  151. var num2 = 0;
  152. for (var index2 = _buckets[index1]; index2 >= 0; index2 = _entries[index2].Next)
  153. {
  154. if (_entries[index2].Key == key)
  155. {
  156. if (add)
  157. ThrowHelper.ArgumentException();
  158. _entries[index2].Value = value;
  159. _version = _version + 1;
  160. return;
  161. }
  162. ++num2;
  163. }
  164. int index3;
  165. if (_freeCount > 0)
  166. {
  167. index3 = _freeList;
  168. _freeList = _entries[index3].Next;
  169. _freeCount = _freeCount - 1;
  170. }
  171. else
  172. {
  173. if (_count == _entries.Length)
  174. {
  175. Resize();
  176. index1 = num1 % _buckets.Length;
  177. }
  178. index3 = _count;
  179. _count = _count + 1;
  180. }
  181. _entries[index3].HashCode = num1;
  182. _entries[index3].Next = _buckets[index1];
  183. _entries[index3].Key = key;
  184. _entries[index3].Value = value;
  185. _buckets[index1] = index3;
  186. _version = _version + 1;
  187. if (num2 <= 100)
  188. return;
  189. Resize(_entries.Length + _entries.Length / 4 + 1);
  190. }
  191. }
  192. void Resize()
  193. {
  194. Resize(SizingHelper.NextSizingPrime(_count));
  195. }
  196. void Resize(int newSize)
  197. {
  198. var numArray = new int[newSize];
  199. for (var index = 0; index < numArray.Length; ++index)
  200. numArray[index] = -1;
  201. var entryArray = new Entry[newSize];
  202. Array.Copy(_entries, 0, entryArray, 0, _count);
  203. for (var index1 = 0; index1 < _count; ++index1)
  204. if (entryArray[index1].HashCode >= 0)
  205. {
  206. var index2 = entryArray[index1].HashCode % newSize;
  207. entryArray[index1].Next = numArray[index2];
  208. numArray[index2] = index1;
  209. }
  210. _buckets = numArray;
  211. _entries = entryArray;
  212. }
  213. public bool Remove(int key)
  214. {
  215. unchecked
  216. {
  217. if (_buckets != null)
  218. {
  219. var num = key & int.MaxValue;
  220. var index1 = num % _buckets.Length;
  221. var index2 = -1;
  222. for (var index3 = _buckets[index1]; index3 >= 0; index3 = _entries[index3].Next)
  223. {
  224. if (_entries[index3].Key == key)
  225. {
  226. if (index2 < 0)
  227. _buckets[index1] = _entries[index3].Next;
  228. else
  229. _entries[index2].Next = _entries[index3].Next;
  230. _entries[index3].HashCode = -1;
  231. _entries[index3].Next = _freeList;
  232. _entries[index3].Key = default(int);
  233. _entries[index3].Value = default(TValue);
  234. _freeList = index3;
  235. _freeCount = _freeCount + 1;
  236. _version = _version + 1;
  237. return true;
  238. }
  239. index2 = index3;
  240. }
  241. }
  242. return false;
  243. }
  244. }
  245. public bool TryGetValue(int key, out TValue value)
  246. {
  247. unchecked
  248. {
  249. if (_buckets != null)
  250. {
  251. var num = key & int.MaxValue;
  252. for (var index = _buckets[num % _buckets.Length]; index >= 0; index = _entries[index].Next)
  253. if (_entries[index].Key == key)
  254. {
  255. value = _entries[index].Value;
  256. return true;
  257. }
  258. }
  259. value = default(TValue);
  260. return false;
  261. }
  262. }
  263. public Enumerator GetEnumerator()
  264. {
  265. return new Enumerator(this);
  266. }
  267. struct Entry
  268. {
  269. public int HashCode;
  270. public int Next;
  271. public int Key;
  272. public TValue Value;
  273. }
  274. public struct Enumerator : IEnumerator<KeyValuePair<int, TValue>>
  275. {
  276. readonly Int32Map<TValue> _parent;
  277. readonly int _version;
  278. int _index;
  279. KeyValuePair<int, TValue> _current;
  280. public void Reset()
  281. {
  282. throw new NotImplementedException();
  283. }
  284. object IEnumerator.Current
  285. {
  286. get { return _current; }
  287. }
  288. public KeyValuePair<int, TValue> Current
  289. {
  290. get { return _current; }
  291. }
  292. internal Enumerator(Int32Map<TValue> parent)
  293. {
  294. _parent = parent;
  295. _version = parent._version;
  296. _index = 0;
  297. _current = new KeyValuePair<int, TValue>();
  298. }
  299. public bool MoveNext()
  300. {
  301. if (_version != _parent._version)
  302. ThrowHelper.InvalidOperationException();
  303. for (; (uint)_index < (uint)_parent._count; _index = _index + 1)
  304. if (_parent._entries[_index].HashCode >= 0)
  305. {
  306. _current = new KeyValuePair<int, TValue>(_parent._entries[_index].Key, _parent._entries[_index].Value);
  307. _index = _index + 1;
  308. return true;
  309. }
  310. _index = _parent._count + 1;
  311. _current = new KeyValuePair<int, TValue>();
  312. return false;
  313. }
  314. public void Dispose() { }
  315. }
  316. }
  317. }