AcDictionary.cs

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

Leave a Reply

Your email address will not be published. Required fields are marked *