diff --git a/SrcMod/Valve.NET/Vkv/VkvTreeNode.cs b/SrcMod/Valve.NET/Vkv/VkvTreeNode.cs index 6073922..c45a39b 100644 --- a/SrcMod/Valve.NET/Vkv/VkvTreeNode.cs +++ b/SrcMod/Valve.NET/Vkv/VkvTreeNode.cs @@ -1,27 +1,63 @@ namespace Valve.Vkv; -public class VkvTreeNode : VkvNode, IEnumerable> +public class VkvTreeNode : VkvNode, IEnumerable> { public int SubNodeCount => p_subNodes.Count; - private readonly Dictionary p_subNodes; + // These should never get out of sync, or bad things will happen. + private readonly List p_subNodeKeys; + private readonly List p_subNodes; public VkvTreeNode(Dictionary? subNodes = null) : base() { - p_subNodes = subNodes ?? new(); + p_subNodeKeys = new(); + p_subNodes = new(); + + if (subNodes is not null) + { + for (int i = 0; i < subNodes.Count; i++) + { + string key = subNodes.Keys.ElementAt(i); + VkvNode? value = subNodes.Values.ElementAt(i); + + if (value is not null) + { + p_subNodeKeys.Add(key); + p_subNodes.Add(value); + } + } + } } public VkvNode? this[string key] { get { - if (p_subNodes.TryGetValue(key, out VkvNode? value)) return value; - else return null; + int index = p_subNodeKeys.IndexOf(key); + + if (index == -1) return null; + else return p_subNodes[index]; } set { - if (p_subNodes.ContainsKey(key)) p_subNodes[key] = value; - else p_subNodes.Add(key, value); + int index = p_subNodeKeys.IndexOf(key); + + if (index == -1) + { + if (value is null) return; + + p_subNodeKeys.Add(key); + p_subNodes.Add(value); + } + else + { + if (value is null) + { + p_subNodeKeys.RemoveAt(index); + p_subNodes.RemoveAt(index); + } + else p_subNodes[index] = value; + } } } public VkvNode? this[int index] @@ -29,17 +65,62 @@ public class VkvTreeNode : VkvNode, IEnumerable> get { if (p_subNodes.Count >= index || index < 0) return null; - return p_subNodes.Values.ElementAt(index); + return p_subNodes[index]; } set { if (p_subNodes.Count >= index || index < 0) throw new IndexOutOfRangeException(); - p_subNodes[p_subNodes.Keys.ElementAt(index)] = value; + + if (value is null) + { + p_subNodeKeys.RemoveAt(index); + p_subNodes.RemoveAt(index); + } + else p_subNodes[index] = value; + } + } + public KeyValuePair? this[Func, bool> predicate] + { + get + { + for (int i = 0; i < SubNodeCount; i++) + { + KeyValuePair pair = new(p_subNodeKeys[i], p_subNodes[i]); + if (predicate(i, pair)) return pair; + } + return null; + } + set + { + for (int i = 0; i < SubNodeCount; i++) + { + KeyValuePair pair = new(p_subNodeKeys[i], p_subNodes[i]); + if (predicate(i, pair)) + { + if (value.HasValue) + { + p_subNodeKeys[i] = value.Value.Key; + p_subNodes[i] = value.Value.Value; + } + else + { + p_subNodeKeys.RemoveAt(i); + p_subNodes.RemoveAt(i); + i--; + } + } + } } } - public void Add(string key, VkvNode? value) => this[key] = value; + public void Add(string key, VkvNode value) => this[key] = value; IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public IEnumerator> GetEnumerator() => p_subNodes.GetEnumerator(); + public IEnumerator> GetEnumerator() + { + for (int i = 0; i < SubNodeCount; i++) + { + yield return new(p_subNodeKeys[i], p_subNodes[i]); + } + } }