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;
}
}