ListDictionary.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #nullable disable
  2. using System.Collections;
  3. using System.Runtime.CompilerServices;
  4. using Jint.Runtime;
  5. namespace Jint.Collections
  6. {
  7. internal sealed class ListDictionary<TValue> : IEnumerable<KeyValuePair<Key, TValue>>
  8. {
  9. private DictionaryNode _head;
  10. private int _count;
  11. private bool _checkExistingKeys;
  12. public ListDictionary(Key key, TValue value, bool checkExistingKeys)
  13. {
  14. _checkExistingKeys = checkExistingKeys;
  15. _head = new DictionaryNode
  16. {
  17. Key = key,
  18. Value = value
  19. };
  20. _count = 1;
  21. }
  22. public TValue this[Key key]
  23. {
  24. get
  25. {
  26. TryGetValue(key, out var value);
  27. return value;
  28. }
  29. set
  30. {
  31. DictionaryNode last = null;
  32. DictionaryNode node;
  33. var checkExistingKeys = _checkExistingKeys;
  34. for (node = _head; node != null; node = node.Next)
  35. {
  36. var oldKey = node.Key;
  37. if (checkExistingKeys && oldKey == key)
  38. {
  39. break;
  40. }
  41. last = node;
  42. }
  43. if (node != null)
  44. {
  45. // Found it
  46. node.Value = value;
  47. return;
  48. }
  49. AddNode(key, value, last);
  50. }
  51. }
  52. public bool TryGetValue(Key key, out TValue value)
  53. {
  54. var node = _head;
  55. while (node != null)
  56. {
  57. if (node.Key == key)
  58. {
  59. value = node.Value;
  60. return true;
  61. }
  62. node = node.Next;
  63. }
  64. value = default;
  65. return false;
  66. }
  67. public void SetOrUpdateValue<TState>(Key key, Func<TValue, TState, TValue> updater, TState state)
  68. {
  69. DictionaryNode last = null;
  70. DictionaryNode node;
  71. for (node = _head; node != null; node = node.Next)
  72. {
  73. if (node.Key == key)
  74. {
  75. node.Value = updater(node.Value, state);
  76. return;
  77. }
  78. last = node;
  79. }
  80. AddNode(key, updater(default, state), last);
  81. }
  82. public int Count
  83. {
  84. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  85. get => _count;
  86. }
  87. public void Add(Key key, TValue value)
  88. {
  89. DictionaryNode last = null;
  90. DictionaryNode node;
  91. var checkExistingKeys = _checkExistingKeys;
  92. for (node = _head; node != null; node = node.Next)
  93. {
  94. var oldKey = node.Key;
  95. if (checkExistingKeys && oldKey == key)
  96. {
  97. ExceptionHelper.ThrowArgumentException();
  98. }
  99. last = node;
  100. }
  101. AddNode(key, value, last);
  102. }
  103. private void AddNode(Key key, TValue value, DictionaryNode last)
  104. {
  105. var newNode = new DictionaryNode
  106. {
  107. Key = key,
  108. Value = value
  109. };
  110. if (_head is null)
  111. {
  112. _head = newNode;
  113. }
  114. else
  115. {
  116. last.Next = newNode;
  117. }
  118. _count++;
  119. }
  120. public void Clear()
  121. {
  122. _count = 0;
  123. _head = null;
  124. }
  125. public bool ContainsKey(Key key)
  126. {
  127. for (var node = _head; node != null; node = node.Next)
  128. {
  129. var oldKey = node.Key;
  130. if (oldKey == key)
  131. {
  132. return true;
  133. }
  134. }
  135. return false;
  136. }
  137. internal bool CheckExistingKeys
  138. {
  139. set => _checkExistingKeys = value;
  140. }
  141. public NodeEnumerator GetEnumerator()
  142. {
  143. return new NodeEnumerator(this);
  144. }
  145. IEnumerator<KeyValuePair<Key, TValue>> IEnumerable<KeyValuePair<Key, TValue>>.GetEnumerator()
  146. {
  147. return new NodeEnumerator(this);
  148. }
  149. IEnumerator IEnumerable.GetEnumerator()
  150. {
  151. return new NodeEnumerator(this);
  152. }
  153. public bool Remove(Key key)
  154. {
  155. DictionaryNode last = null;
  156. DictionaryNode node;
  157. for (node = _head; node != null; node = node.Next)
  158. {
  159. var oldKey = node.Key;
  160. if (oldKey == key)
  161. {
  162. break;
  163. }
  164. last = node;
  165. }
  166. if (node == null)
  167. {
  168. return false;
  169. }
  170. if (node == _head)
  171. {
  172. _head = node.Next;
  173. }
  174. else
  175. {
  176. last.Next = node.Next;
  177. }
  178. _count--;
  179. return true;
  180. }
  181. internal struct NodeEnumerator : IEnumerator<KeyValuePair<Key, TValue>>
  182. {
  183. private readonly ListDictionary<TValue> _list;
  184. private DictionaryNode _current;
  185. private bool _start;
  186. public NodeEnumerator(ListDictionary<TValue> list)
  187. {
  188. _list = list;
  189. _start = true;
  190. _current = null;
  191. }
  192. public KeyValuePair<Key, TValue> Current => new KeyValuePair<Key, TValue>(_current.Key, _current.Value);
  193. public bool MoveNext()
  194. {
  195. if (_start)
  196. {
  197. _current = _list._head;
  198. _start = false;
  199. }
  200. else if (_current != null)
  201. {
  202. _current = _current.Next;
  203. }
  204. return _current != null;
  205. }
  206. void IEnumerator.Reset()
  207. {
  208. _start = true;
  209. _current = null;
  210. }
  211. public void Dispose()
  212. {
  213. }
  214. object IEnumerator.Current => _current;
  215. }
  216. internal sealed class DictionaryNode
  217. {
  218. public Key Key;
  219. public TValue Value;
  220. public DictionaryNode Next;
  221. }
  222. }
  223. }