123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- #nullable disable
- using System.Collections;
- using System.Runtime.CompilerServices;
- namespace Jint.Collections;
- internal class HybridDictionary<TValue> : IEnumerable<KeyValuePair<Key, TValue>>
- {
- private const int CutoverPoint = 9;
- private const int InitialDictionarySize = 13;
- private const int FixedSizeCutoverPoint = 6;
- private readonly bool _checkExistingKeys;
- private ListDictionary<TValue> _list;
- internal StringDictionarySlim<TValue> _dictionary;
- public HybridDictionary() : this(0, checkExistingKeys: true)
- {
- }
- public HybridDictionary(int initialSize, bool checkExistingKeys)
- {
- _checkExistingKeys = checkExistingKeys;
- if (initialSize >= FixedSizeCutoverPoint)
- {
- _dictionary = new StringDictionarySlim<TValue>(initialSize);
- }
- }
- protected HybridDictionary(StringDictionarySlim<TValue> dictionary)
- {
- _checkExistingKeys = true;
- _dictionary = dictionary;
- }
- public TValue this[Key key]
- {
- get
- {
- TryGetValue(key, out var value);
- return value;
- }
- set
- {
- if (_dictionary != null)
- {
- _dictionary[key] = value;
- }
- else if (_list != null)
- {
- if (_list.Count >= CutoverPoint - 1)
- {
- SwitchToDictionary(key, value, tryAdd: false);
- }
- else
- {
- _list[key] = value;
- }
- }
- else
- {
- _list = new ListDictionary<TValue>(key, value, _checkExistingKeys);
- }
- }
- }
- public bool TryGetValue(Key key, out TValue value)
- {
- if (_dictionary != null)
- {
- return _dictionary.TryGetValue(key, out value);
- }
- if (_list != null)
- {
- return _list.TryGetValue(key, out value);
- }
- value = default;
- return false;
- }
- public void SetOrUpdateValue<TState>(Key key, Func<TValue, TState, TValue> updater, TState state)
- {
- if (_dictionary != null)
- {
- _dictionary.SetOrUpdateValue(key, updater, state);
- }
- else if (_list != null)
- {
- _list.SetOrUpdateValue(key, updater, state);
- }
- else
- {
- _list = new ListDictionary<TValue>(key, updater(default, state), _checkExistingKeys);
- }
- }
- private bool SwitchToDictionary(Key key, TValue value, bool tryAdd)
- {
- var dictionary = new StringDictionarySlim<TValue>(InitialDictionarySize);
- foreach (var pair in _list)
- {
- dictionary[pair.Key] = pair.Value;
- }
- bool result;
- if (tryAdd)
- {
- result = dictionary.TryAdd(key, value);
- }
- else
- {
- dictionary[key] = value;
- result = true;
- }
- _dictionary = dictionary;
- _list = null;
- return result;
- }
- public int Count
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _dictionary?.Count ?? _list?.Count ?? 0;
- }
- public bool TryAdd(Key key, TValue value)
- {
- if (_dictionary != null)
- {
- return _dictionary.TryAdd(key, value);
- }
- else
- {
- _list ??= new ListDictionary<TValue>(key, value, _checkExistingKeys);
- if (_list.Count + 1 >= CutoverPoint)
- {
- return SwitchToDictionary(key, value, tryAdd: true);
- }
- else
- {
- return _list.Add(key, value, tryAdd: true);
- }
- }
- }
- public void Add(Key key, TValue value)
- {
- if (_dictionary != null)
- {
- _dictionary.GetOrAddValueRef(key) = value;
- }
- else
- {
- if (_list == null)
- {
- _list = new ListDictionary<TValue>(key, value, _checkExistingKeys);
- }
- else
- {
- if (_list.Count + 1 >= CutoverPoint)
- {
- SwitchToDictionary(key, value, tryAdd: false);
- }
- else
- {
- _list.Add(key, value);
- }
- }
- }
- }
- public void Clear()
- {
- _dictionary?.Clear();
- _list?.Clear();
- }
- public bool ContainsKey(Key key)
- {
- if (_dictionary != null)
- {
- return _dictionary.ContainsKey(key);
- }
- if (_list != null)
- {
- return _list.ContainsKey(key);
- }
- return false;
- }
- IEnumerator<KeyValuePair<Key, TValue>> IEnumerable<KeyValuePair<Key, TValue>>.GetEnumerator()
- {
- if (_dictionary != null)
- {
- return _dictionary.GetEnumerator();
- }
- if (_list != null)
- {
- return _list.GetEnumerator();
- }
- return System.Linq.Enumerable.Empty<KeyValuePair<Key, TValue>>().GetEnumerator();
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- if (_dictionary != null)
- {
- return _dictionary.GetEnumerator();
- }
- if (_list != null)
- {
- return _list.GetEnumerator();
- }
- return System.Linq.Enumerable.Empty<KeyValuePair<Key, TValue>>().GetEnumerator();
- }
- public bool Remove(Key key)
- {
- if (_dictionary != null)
- {
- return _dictionary.Remove(key);
- }
- return _list != null && _list.Remove(key);
- }
- /// <summary>
- /// Optimization when no need to check for existing items.
- /// </summary>
- public bool CheckExistingKeys
- {
- set
- {
- if (_list != null)
- {
- _list.CheckExistingKeys = value;
- }
- }
- }
- }
|