/* * Copyright (C) 2012-2018 CypherCore * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System.Linq; namespace System.Collections.Generic { public sealed class MultiMap : IMultiMap, IDictionary { public MultiMap() { } public MultiMap(IEnumerable> initialData) { foreach (var item in initialData) { Add(item); } } public void Add(TKey key, TValue value) { if (!_interalStorage.ContainsKey(key)) _interalStorage.Add(key, new List()); _interalStorage[key].Add(value); } public void AddRange(TKey key, IEnumerable valueList) { if (!_interalStorage.ContainsKey(key)) { _interalStorage.Add(key, new List()); } foreach (TValue value in valueList) { _interalStorage[key].Add(value); } } public void Add(KeyValuePair item) { if (!_interalStorage.ContainsKey(item.Key)) { _interalStorage.Add(item.Key, new List()); } _interalStorage[item.Key].Add(item.Value); } public bool Remove(TKey key) { return _interalStorage.Remove(key); } public bool Remove(KeyValuePair item) { if (!ContainsKey(item.Key)) return false; bool val = _interalStorage[item.Key].Remove(item.Value); if (!val) return false; if (_interalStorage[item.Key].Empty()) _interalStorage.Remove(item.Key); return true; } public bool Remove(TKey key, TValue value) { if (!ContainsKey(key)) return false; bool val = _interalStorage[key].Remove(value); if (!val) return false; if (_interalStorage[key].Empty()) _interalStorage.Remove(key); return true; } public bool ContainsKey(TKey key) { return _interalStorage.ContainsKey(key); } public bool Contains(KeyValuePair item) { List valueList; if (_interalStorage.TryGetValue(item.Key, out valueList)) return valueList.Contains(item.Value); return false; } public bool Contains(TKey key, TValue item) { if (!_interalStorage.ContainsKey(key)) return false; return _interalStorage[key].Contains(item); } public List LookupByKey(TKey key) { if (_interalStorage.ContainsKey(key)) return _interalStorage[key]; return new List(); } public List LookupByKey(object key) { TKey newkey = (TKey)Convert.ChangeType(key, typeof(TKey)); if (_interalStorage.ContainsKey(newkey)) return _interalStorage[newkey]; return new List(); } bool IDictionary.TryGetValue(TKey key, out TValue value) { if (!_interalStorage.ContainsKey(key)) { value = default(TValue); return false; } value = _interalStorage[key].Last(); return true; } TValue IDictionary.this[TKey key] { get { return _interalStorage[key].LastOrDefault(); } set { Add(key, value); } } public List this[TKey key] { get { if (!_interalStorage.ContainsKey(key)) return new List(); return _interalStorage[key]; } set { if (!_interalStorage.ContainsKey(key)) _interalStorage.Add(key, value); else _interalStorage[key] = value; } } public ICollection Keys { get { return _interalStorage.Keys; } } public ICollection Values { get { List retVal = new List(); foreach (var item in _interalStorage) { retVal.AddRange(item.Value); } return retVal; } } public List> KeyValueList { get { List> retVal = new List>(); foreach (var pair in _interalStorage) { foreach (var value in pair.Value) retVal.Add(new KeyValuePair(pair.Key, value)); } return retVal; } } public void Clear() { _interalStorage.Clear(); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); if (arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, "argument 'arrayIndex' cannot be negative"); if (arrayIndex >= array.Length || Count > array.Length - arrayIndex) array = new KeyValuePair[Count]; int index = arrayIndex; foreach (KeyValuePair pair in this) array[index++] = new KeyValuePair(pair.Key, pair.Value); } public int Count { get { int count = 0; foreach (var item in _interalStorage) { count += item.Value.Count; } return count; } } int ICollection>.Count { get { return _interalStorage.Count; } } bool ICollection>.IsReadOnly { get { return false; } } public IEnumerator> GetEnumerator() { return new MultiMapEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new MultiMapEnumerator(this); } private Dictionary> _interalStorage = new Dictionary>(); } public sealed class SortedMultiMap : IMultiMap, IDictionary { public SortedMultiMap() { } public SortedMultiMap(IEnumerable> initialData) { foreach (var item in initialData) { Add(item); } } public void Add(TKey key, TValue value) { if (!_interalStorage.ContainsKey(key)) _interalStorage.Add(key, new List()); _interalStorage[key].Add(value); } public void AddRange(TKey key, IEnumerable valueList) { if (!_interalStorage.ContainsKey(key)) { _interalStorage.Add(key, new List()); } foreach (TValue value in valueList) { _interalStorage[key].Add(value); } } public void Add(KeyValuePair item) { if (!_interalStorage.ContainsKey(item.Key)) { _interalStorage.Add(item.Key, new List()); } _interalStorage[item.Key].Add(item.Value); } public bool Remove(TKey key) { return _interalStorage.Remove(key); } public bool Remove(KeyValuePair item) { if (!ContainsKey(item.Key)) return false; bool val = _interalStorage[item.Key].Remove(item.Value); if (!val) return false; if (_interalStorage[item.Key].Empty()) _interalStorage.Remove(item.Key); return true; } public bool Remove(TKey key, TValue value) { if (!ContainsKey(key)) return false; bool val = _interalStorage[key].Remove(value); if (!val) return false; if (_interalStorage[key].Empty()) _interalStorage.Remove(key); return true; } public bool ContainsKey(TKey key) { return _interalStorage.ContainsKey(key); } public bool Contains(KeyValuePair item) { List valueList; if (_interalStorage.TryGetValue(item.Key, out valueList)) return valueList.Contains(item.Value); return false; } public bool Contains(TKey key, TValue item) { if (!_interalStorage.ContainsKey(key)) return false; return _interalStorage[key].Contains(item); } public List LookupByKey(TKey key) { if (_interalStorage.ContainsKey(key)) return _interalStorage[key]; return new List(); } public List LookupByKey(object key) { TKey newkey = (TKey)Convert.ChangeType(key, typeof(TKey)); if (_interalStorage.ContainsKey(newkey)) return _interalStorage[newkey]; return new List(); } bool IDictionary.TryGetValue(TKey key, out TValue value) { if (!_interalStorage.ContainsKey(key)) { value = default(TValue); return false; } value = _interalStorage[key].Last(); return true; } TValue IDictionary.this[TKey key] { get { return _interalStorage[key].LastOrDefault(); } set { Add(key, value); } } public List this[TKey key] { get { if (!_interalStorage.ContainsKey(key)) return new List(); return _interalStorage[key]; } set { if (!_interalStorage.ContainsKey(key)) _interalStorage.Add(key, value); else _interalStorage[key] = value; } } public ICollection Keys { get { return _interalStorage.Keys; } } public ICollection Values { get { List retVal = new List(); foreach (var item in _interalStorage) { retVal.AddRange(item.Value); } return retVal; } } public List> KeyValueList { get { List> retVal = new List>(); foreach (var pair in _interalStorage) { foreach (var value in pair.Value) retVal.Add(new KeyValuePair(pair.Key, value)); } return retVal; } } public void Clear() { _interalStorage.Clear(); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); if (arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, "argument 'arrayIndex' cannot be negative"); if (arrayIndex >= array.Length || Count > array.Length - arrayIndex) array = new KeyValuePair[Count]; int index = arrayIndex; foreach (KeyValuePair pair in this) array[index++] = new KeyValuePair(pair.Key, pair.Value); } public int Count { get { int count = 0; foreach (var item in _interalStorage) { count += item.Value.Count; } return count; } } int ICollection>.Count { get { return _interalStorage.Count; } } bool ICollection>.IsReadOnly { get { return false; } } public IEnumerator> GetEnumerator() { return new SortedMultiMapEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new SortedMultiMapEnumerator(this); } private SortedDictionary> _interalStorage = new SortedDictionary>(); } }