diff --git a/Toolkit.Foundation/Cache.cs b/Toolkit.Foundation/Cache.cs index 4db2762..4d70bb8 100644 --- a/Toolkit.Foundation/Cache.cs +++ b/Toolkit.Foundation/Cache.cs @@ -1,49 +1,61 @@ using System.Collections; -using System.Collections.Immutable; -using System.Reactive.Disposables; namespace Toolkit.Foundation; -public class Cache(IDisposer disposer, - IComparer? comparer = default) : +public class Cache(IComparer? comparer = default) : ICache { - private readonly List cache = []; + private readonly List items = []; - public int IndexOf(TValue value) => - cache.IndexOf(value); + public IEnumerable Items => + items; - public void Add(TValue value) + public TValue this[int index] => + items[index]; + + public void Add(TValue item) { - if (value is null) + int index = items.BinarySearch(item, comparer); + if (index < 0) { - return; + index = ~index; } - - disposer.Add(value, Disposable.Create(() => Remove(value))); - cache.Add(value); - cache.Sort(comparer); + items.Insert(index, item); } - public bool TryGetValue(TValue key, out TValue? value) + public void Clear() => items.Clear(); + + public IEnumerator GetEnumerator() => + items.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator(); + + public int IndexOf(TValue item) => + items.BinarySearch(item, comparer); + + public bool Remove(TValue item) { - if (cache.FirstOrDefault(x => x is not null && x.Equals(key)) is TValue returningValue) + int index = items.BinarySearch(item, comparer); + if (index >= 0) { - value = returningValue; + items.RemoveAt(index); return true; } - - value = default; return false; } - public void Clear() => cache.Clear(); + public bool TryGetValue(TValue key, out TValue? item) + { + int index = items.BinarySearch(key, comparer); + if (index >= 0) + { + item = items[index]; + return true; + } - public IEnumerator GetEnumerator() => cache.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public bool Remove(TValue value) => cache.Remove(value); + item = default; + return false; + } } public class Cache(IComparer comparer) : @@ -53,34 +65,92 @@ public class Cache(IComparer comparer) : where TValue : notnull { - private readonly SortedList cache = new(comparer); - - public void Add(TKey key, - TValue value) + private readonly List> items = []; + public TValue? this[TKey key] { - cache.TryAdd(key, value); + get + { + int index = items.BinarySearch(new KeyValuePair(key, default), + new KeyValuePairComparer(comparer)); + + if (index >= 0) + { + return items[index].Value; + } + + return default; + } + set + { + int index = items.BinarySearch(new KeyValuePair(key, default), + new KeyValuePairComparer(comparer)); + + if (index >= 0) + { + items[index] = new KeyValuePair(key, value); + } + else + { + items.Insert(~index, new KeyValuePair(key, value)); + } + } } - public void Clear() => cache.Clear(); + public void Add(TKey key, TValue value) + { + int index = items.BinarySearch(new KeyValuePair(key, default), + new KeyValuePairComparer(comparer)); - public bool ContainsKey(TKey key) => cache.ContainsKey(key); + if (index < 0) + { + index = ~index; + } - public int IndexOf(TKey key) => cache.IndexOfKey(key); + items.Insert(index, new KeyValuePair(key, value)); + } + public void Clear() => items.Clear(); - public IEnumerator> GetEnumerator() => cache.GetEnumerator(); + public IEnumerator> GetEnumerator() => + items.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => + GetEnumerator(); - public bool Remove(TKey key) => cache.Remove(key, out _); + public int IndexOf(TKey key) => + items.FindIndex(kvp => comparer.Compare(kvp.Key, key) == 0); + + public bool Remove(TKey key) + { + int index = items.FindIndex(kvp => comparer.Compare(kvp.Key, key) == 0); + if (index >= 0) + { + items.RemoveAt(index); + return true; + } + return false; + } public bool TryGetValue(TKey key, out TValue? value) { - if (cache.TryGetValue(key, out value)) + int index = items.BinarySearch(new KeyValuePair(key, default(TValue)), + new KeyValuePairComparer(comparer)); + + if (index >= 0) { + value = items[index].Value; return true; } value = default; return false; } + + private class KeyValuePairComparer(IComparer comparer) : + IComparer> + { + private readonly IComparer comparer = comparer ?? Comparer.Default; + + public int Compare(KeyValuePair x, KeyValuePair y) => + comparer.Compare(x.Key, y.Key); + } } \ No newline at end of file diff --git a/Toolkit.Foundation/ICache.cs b/Toolkit.Foundation/ICache.cs index ae7bedb..669a9a1 100644 --- a/Toolkit.Foundation/ICache.cs +++ b/Toolkit.Foundation/ICache.cs @@ -7,11 +7,11 @@ public interface ICache : void Clear(); + bool TryGetValue(TValue key, out TValue? item); + int IndexOf(TValue value); bool Remove(TValue value); - - bool TryGetValue(TValue key, out TValue? value); } public interface ICache : @@ -25,8 +25,6 @@ public interface ICache : void Clear(); - bool ContainsKey(TKey key); - int IndexOf(TKey key); bool Remove(TKey key); diff --git a/Toolkit.Foundation/TrackedProperty.cs b/Toolkit.Foundation/TrackedProperty.cs index f14a62c..1e22dac 100644 --- a/Toolkit.Foundation/TrackedProperty.cs +++ b/Toolkit.Foundation/TrackedProperty.cs @@ -7,4 +7,4 @@ public class TrackedProperty(T initial, public void Commit() => initial = commit(); public void Revert() => revert(initial); -} +} \ No newline at end of file