//----------------------------------------------------------------------- // // Copyright (c) 2018 Sirenix IVS // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //----------------------------------------------------------------------- namespace VRC.Udon.Serialization.OdinSerializer.Utilities { using System; using System.Collections.Generic; /// /// Not yet documented. /// [Serializable] public class DoubleLookupDictionary : Dictionary> { private readonly IEqualityComparer secondKeyComparer; public DoubleLookupDictionary() { this.secondKeyComparer = EqualityComparer.Default; } public DoubleLookupDictionary(IEqualityComparer firstKeyComparer, IEqualityComparer secondKeyComparer) : base(firstKeyComparer) { this.secondKeyComparer = secondKeyComparer; } /// /// Not yet documented. /// public new Dictionary this[TFirstKey firstKey] { get { Dictionary innerDict; if (!this.TryGetValue(firstKey, out innerDict)) { innerDict = new Dictionary(this.secondKeyComparer); this.Add(firstKey, innerDict); } return innerDict; } } /// /// Not yet documented. /// public int InnerCount(TFirstKey firstKey) { Dictionary innerDict; if (this.TryGetValue(firstKey, out innerDict)) { return innerDict.Count; } return 0; } /// /// Not yet documented. /// public int TotalInnerCount() { int count = 0; if (this.Count > 0) { foreach (var innerDict in this.Values) { count += innerDict.Count; } } return count; } /// /// Not yet documented. /// public bool ContainsKeys(TFirstKey firstKey, TSecondKey secondKey) { Dictionary innerDict; return this.TryGetValue(firstKey, out innerDict) && innerDict.ContainsKey(secondKey); } /// /// Not yet documented. /// public bool TryGetInnerValue(TFirstKey firstKey, TSecondKey secondKey, out TValue value) { Dictionary innerDict; if (this.TryGetValue(firstKey, out innerDict) && innerDict.TryGetValue(secondKey, out value)) { return true; } value = default(TValue); return false; } /// /// Not yet documented. /// public TValue AddInner(TFirstKey firstKey, TSecondKey secondKey, TValue value) { if (this.ContainsKeys(firstKey, secondKey)) { throw new ArgumentException("An element with the same keys already exists in the " + this.GetType().GetNiceName() + "."); } return this[firstKey][secondKey] = value; } /// /// Not yet documented. /// public bool RemoveInner(TFirstKey firstKey, TSecondKey secondKey) { Dictionary innerDict; if (this.TryGetValue(firstKey, out innerDict)) { bool removed = innerDict.Remove(secondKey); if (innerDict.Count == 0) { this.Remove(firstKey); } return removed; } return false; } /// /// Not yet documented. /// public void RemoveWhere(Func predicate) { List toRemoveBufferFirstKey = new List(); List toRemoveBufferSecondKey = new List(); foreach (var outerDictionary in this.GFIterator()) { foreach (var innerKeyPair in outerDictionary.Value.GFIterator()) { if (predicate(innerKeyPair.Value)) { toRemoveBufferFirstKey.Add(outerDictionary.Key); toRemoveBufferSecondKey.Add(innerKeyPair.Key); } } } for (int i = 0; i < toRemoveBufferFirstKey.Count; i++) { this.RemoveInner(toRemoveBufferFirstKey[i], toRemoveBufferSecondKey[i]); } } } }