From dc298fd61a786faca22059626943e3b4ea35ae05 Mon Sep 17 00:00:00 2001 From: NathanKell Date: Wed, 29 Nov 2023 23:20:37 -0800 Subject: [PATCH] Add IReadOnlyCollectionDictionary for read-only access to collection-dictionaries/sortedlists --- Source/ROUtils/DataTypes/DictionaryHelpers.cs | 5 ++ .../ROUtils/DataTypes/PersistentDictionary.cs | 48 +++++++++++++++++-- .../ROUtils/DataTypes/PersistentSortedList.cs | 46 ++++++++++++++++-- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/Source/ROUtils/DataTypes/DictionaryHelpers.cs b/Source/ROUtils/DataTypes/DictionaryHelpers.cs index 17597ea..c594655 100644 --- a/Source/ROUtils/DataTypes/DictionaryHelpers.cs +++ b/Source/ROUtils/DataTypes/DictionaryHelpers.cs @@ -5,6 +5,11 @@ namespace ROUtils.DataTypes { + public interface IReadOnlyCollectionDictionary : IReadOnlyDictionary where TCollection : ICollection, new() + { + public CollectionDictionaryAllValues AllValues { get; } + } + public abstract class DictionaryPersistence : PersistenceHelper, IConfigNode { protected static readonly Type _KeyType = typeof(TKey); diff --git a/Source/ROUtils/DataTypes/PersistentDictionary.cs b/Source/ROUtils/DataTypes/PersistentDictionary.cs index e8c834a..89d6b55 100644 --- a/Source/ROUtils/DataTypes/PersistentDictionary.cs +++ b/Source/ROUtils/DataTypes/PersistentDictionary.cs @@ -156,7 +156,7 @@ public bool Remove(TKey key, TValue value) } } - public class PersistentDictionaryBothObjects : PersistentDictionaryBothObjects, IConfigNode where TKey : IConfigNode where TCollection : ICollection, IConfigNode, new() + public class PersistentDictionaryBothObjects : PersistentDictionaryBothObjects, IReadOnlyCollectionDictionary where TKey : IConfigNode where TCollection : ICollection, IConfigNode, new() { private CollectionDictionaryAllValues _allValues; public CollectionDictionaryAllValues AllValues => _allValues; @@ -194,7 +194,7 @@ public bool Remove(TKey key, TValue value) /// /// /// - public class PersistentDictionaryNodeValueKeyed : PersistentDictionaryNodeValueKeyed, IConfigNode where TCollection : ICollection, IConfigNode, new() + public class PersistentDictionaryNodeValueKeyed : PersistentDictionaryNodeValueKeyed, IReadOnlyCollectionDictionary where TCollection : ICollection, IConfigNode, new() { private CollectionDictionaryAllValues _allValues; public CollectionDictionaryAllValues AllValues => _allValues; @@ -234,7 +234,7 @@ public bool Remove(TKey key, TValue value) /// /// /// - public class PersistentDictionaryValueTypeKey : PersistentDictionaryValueTypeKey where TCollection : ICollection, IConfigNode, new() + public class PersistentDictionaryValueTypeKey : PersistentDictionaryValueTypeKey, IReadOnlyCollectionDictionary where TCollection : ICollection, IConfigNode, new() { private CollectionDictionaryAllValues _allValues; public CollectionDictionaryAllValues AllValues => _allValues; @@ -273,7 +273,7 @@ public bool Remove(TKey key, TValue value) /// /// /// - public class PersistentDictionaryValueTypes : PersistentDictionaryValueTypeKey, IConfigNode where TCollection : ICollection, IConfigNode, new() + public class PersistentDictionaryValueTypes : PersistentDictionaryValueTypeKey, IReadOnlyCollectionDictionary where TCollection : ICollection, IConfigNode, new() { private CollectionDictionaryAllValues _allValues; public CollectionDictionaryAllValues AllValues => _allValues; @@ -305,4 +305,44 @@ public bool Remove(TKey key, TValue value) return true; } } + + // Reimplementation of KSP's ListDictionary - the non-persistent form of Collection-dictionaries as above. + public class CollectionDictionary : Dictionary, IReadOnlyCollectionDictionary where TCollection : ICollection, new() + { + private CollectionDictionaryAllValues _allValues; + public CollectionDictionaryAllValues AllValues => _allValues; + + public CollectionDictionary() : base() { _allValues = new CollectionDictionaryAllValues(this); } + + public CollectionDictionary(int capacity) : base(capacity) { _allValues = new CollectionDictionaryAllValues(this); } + public CollectionDictionary(IEqualityComparer comparer) : base(comparer) { _allValues = new CollectionDictionaryAllValues(this); } + public CollectionDictionary(IDictionary dictionary) : base(dictionary) { _allValues = new CollectionDictionaryAllValues(this); } + public CollectionDictionary(int capacity, IEqualityComparer comparer) : base(capacity, comparer) { _allValues = new CollectionDictionaryAllValues(this); } + public CollectionDictionary(IDictionary dictionary, IEqualityComparer comparer) : base(dictionary, comparer) { _allValues = new CollectionDictionaryAllValues(this); } + + public void Add(TKey key, TValue value) + { + if (!TryGetValue(key, out var coll)) + { + coll = new TCollection(); + Add(key, coll); + } + + coll.Add(value); + } + + public bool Remove(TKey key, TValue value) + { + if (!TryGetValue(key, out var coll)) + return false; + + if (!coll.Remove(value)) + return false; + + if (coll.Count == 0) + Remove(key); + + return true; + } + } } diff --git a/Source/ROUtils/DataTypes/PersistentSortedList.cs b/Source/ROUtils/DataTypes/PersistentSortedList.cs index bed667a..30c21f2 100644 --- a/Source/ROUtils/DataTypes/PersistentSortedList.cs +++ b/Source/ROUtils/DataTypes/PersistentSortedList.cs @@ -55,7 +55,7 @@ public class PersistentSortedListValueTypes : PersistentSortedList /// /// /// - public class PersistentSortedListNodeValueKeyed : PersistentSortedListNodeValueKeyed, IConfigNode where TCollection : ICollection, IConfigNode, new() + public class PersistentSortedListNodeValueKeyed : PersistentSortedListNodeValueKeyed, IReadOnlyCollectionDictionary where TCollection : ICollection, IConfigNode, new() { private CollectionDictionaryAllValues _allValues; public CollectionDictionaryAllValues AllValues => _allValues; @@ -95,7 +95,7 @@ public bool Remove(TKey key, TValue value) /// /// /// - public class PersistentSortedListValueTypeKey : PersistentSortedListValueTypeKey where TCollection : ICollection, IConfigNode, new() + public class PersistentSortedListValueTypeKey : PersistentSortedListValueTypeKey, IReadOnlyCollectionDictionary where TCollection : ICollection, IConfigNode, new() { private CollectionDictionaryAllValues _allValues; public CollectionDictionaryAllValues AllValues => _allValues; @@ -134,7 +134,7 @@ public bool Remove(TKey key, TValue value) /// /// /// - public class PersistentSortedListValueTypes : PersistentSortedListValueTypeKey, IConfigNode where TCollection : ICollection, IConfigNode, new() + public class PersistentSortedListValueTypes : PersistentSortedListValueTypeKey, IReadOnlyCollectionDictionary where TCollection : ICollection, IConfigNode, new() { private CollectionDictionaryAllValues _allValues; public CollectionDictionaryAllValues AllValues => _allValues; @@ -166,4 +166,44 @@ public bool Remove(TKey key, TValue value) return true; } } + + // Reimplementation of KSP's ListDictionary as SortedList - the non-persistent form of Collection-SortedLists as above. + public class CollectionSortedList : SortedList, IReadOnlyCollectionDictionary where TCollection : ICollection, new() + { + private CollectionDictionaryAllValues _allValues; + public CollectionDictionaryAllValues AllValues => _allValues; + + public CollectionSortedList() : base() { _allValues = new CollectionDictionaryAllValues(this); } + + public CollectionSortedList(int capacity) : base(capacity) { _allValues = new CollectionDictionaryAllValues(this); } + public CollectionSortedList(IComparer comparer) : base(comparer) { _allValues = new CollectionDictionaryAllValues(this); } + public CollectionSortedList(IDictionary dictionary) : base(dictionary) { _allValues = new CollectionDictionaryAllValues(this); } + public CollectionSortedList(int capacity, IComparer comparer) : base(capacity, comparer) { _allValues = new CollectionDictionaryAllValues(this); } + public CollectionSortedList(IDictionary dictionary, IComparer comparer) : base(dictionary, comparer) { _allValues = new CollectionDictionaryAllValues(this); } + + public void Add(TKey key, TValue value) + { + if (!TryGetValue(key, out var coll)) + { + coll = new TCollection(); + Add(key, coll); + } + + coll.Add(value); + } + + public bool Remove(TKey key, TValue value) + { + if (!TryGetValue(key, out var coll)) + return false; + + if (!coll.Remove(value)) + return false; + + if (coll.Count == 0) + Remove(key); + + return true; + } + } }