Support Dictionary for Hash Mapping
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; [DebuggerDisplay("Count = {Count}")] [Serializable] public class AcDictionary<TKey, TValue> : MonitorActionFuncWrapper, IEnumerable<KeyValuePair<TKey, TValue>> { public MSet15<TKey> _keys; public TValue[] _values; public AcDictionary() : this(101, EqualityComparer<TKey>.Default) { } public AcDictionary(int size) : this(size, EqualityComparer<TKey>.Default) { } public AcDictionary(int size, IEqualityComparer<TKey> comparer) { if (comparer == null) comparer = EqualityComparer<TKey>.Default; _keys = new MSet15<TKey>(size); _values = new TValue[size]; _keys.Comparer = comparer; } public AcDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer = null) { if (comparer == null) comparer = EqualityComparer<TKey>.Default; _keys.Comparer = comparer; foreach (var kp in collection) Add(kp.Key, kp.Value); } public int Count => _keys.Count; public TValue this[TKey key] { get { var pos = _keys.FindEntry(key); return pos == -1 ? default : _values[pos]; } set => Add(key, value); } public TValue[] Values => _values; public KeyValuePair<TKey, TValue>[] KeyValuePairs => ToArray(); public TKey[] Keys => _keys.ToArray(); public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return Lock(this, () => { return GetEnum(); }); } IEnumerator IEnumerable.GetEnumerator() { return Lock(this, () => { return GetEnum(); }); } private IEnumerator<KeyValuePair<TKey, TValue>> GetEnum() { for (var i = 0; i < Count; i++) if (_keys.Slots[i].HashCode > 0) yield return new KeyValuePair<TKey, TValue>(_keys.Slots[i].Value, _values[i]); } public bool Add(TKey key, TValue value) { return Lock(this, () => { if (!_keys.Add(key)) { if (Values.Length != _keys.Slots.Length) { var nValues = new TValue[_keys.Slots.Length]; Array.Copy(_values, nValues, _values.Length); _values = nValues; } Values[_keys.Position] = value; return false; } Values[_keys.Position] = value; return true; }); } public void Remove(TKey key) { Lock(this, () => { var pos = _keys.FindEntry(key); if (pos != -1) { Values[pos] = default; _keys.Remove(key); } }); } public bool ContainsKey(TKey key) { return Lock(this, () => { return _keys.FindEntry(key) != -1; }); } public bool ContainsValue(TValue value) { return Lock(this, () => { var vab = value.GetBytes(); foreach (var v in _values) { if (v == null) continue; var vab1 = v.GetBytes(); if (vab.Compare(vab1)) return true; } return false; }); } public int FindKeyIndex(TKey key) { return Lock(this, () => { return _keys.FindEntry(key); }); } public KeyValuePair<TKey, TValue>[] ToArray() { return Lock(this, () => { var array = new KeyValuePair<TKey, TValue>[Count]; var idx = 0; foreach (var k in _keys) if (_keys.FindEntry(k) != -1) { var v = _values[_keys.Position]; array[idx] = new KeyValuePair<TKey, TValue>(k, v); idx++; } return array; }); } public void Clear() { Lock(this, () => { _keys = new MSet15<TKey>(_keys.Slots.Length); _values = new TValue[_keys.Slots.Length]; }); } }
[SecuritySafeCritical] public static unsafe bool Compare(this byte[] a1, byte[] a2) { if (a1 == null && a2 == null) return true; if (a1 == null || a2 == null || a1.Length != a2.Length) return false; fixed (byte* p1 = a1, p2 = a2) { var Len = a1.Length; byte* x1 = p1, x2 = p2; while (Len > 7) { if (*(long*) x2 != *(long*) x1) return false; x1 += 8; x2 += 8; Len -= 8; } switch (Len % 8) { case 0: break; case 7: if (*(int*) x2 != *(int*) x1) return false; x1 += 4; x2 += 4; if (*(short*) x2 != *(short*) x1) return false; x1 += 2; x2 += 2; if (*x2 != *x1) return false; break; case 6: if (*(int*) x2 != *(int*) x1) return false; x1 += 4; x2 += 4; if (*(short*) x2 != *(short*) x1) return false; break; case 5: if (*(int*) x2 != *(int*) x1) return false; x1 += 4; x2 += 4; if (*x2 != *x1) return false; break; case 4: if (*(int*) x2 != *(int*) x1) return false; break; case 3: if (*(short*) x2 != *(short*) x1) return false; x1 += 2; x2 += 2; if (*x2 != *x1) return false; break; case 2: if (*(short*) x2 != *(short*) x1) return false; break; case 1: if (*x2 != *x1) return false; break; } return true; } }