Able
Askowl Base Library Enabler
Map.cs
1 // Copyright 2018 (C) paul@marrington.net http://www.askowl.net/unity-packages
2 
3 namespace Askowl {
4  using System;
5  using System.Collections;
6  using System.Collections.Generic;
7 
8  /// <a href="http://bit.ly/2NUH9Io">A dictionary wrapper</a>
9  // ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
10  public class Map : IDisposable {
11  private readonly Dictionary<object, object> map = new Dictionary<object, object>();
12 
13  private readonly ArrayList keys = new ArrayList();
14 
15  /// <a href=""></a> //#TBD#//
16  public static Map Instance => Cache<Map>.Instance;
17 
18  internal Map CreateItem() => new Map {cached = true};
19 
20  /// <a href="http://bit.ly/2NUH9Io">Remove an entry, optionally calling Dispose()</a>
21  // ReSharper disable once UnusedMethodReturnValue.Global
22  public Map Remove(object key, bool dispose = true) {
23  if ((key == null) || !map.ContainsKey(key)) return this;
24 
25  keys.Remove(key);
26  if (dispose) (map[key] as IDisposable)?.Dispose();
27  map.Remove(key);
28 
29  return this;
30  }
31 
32  /// <a href="http://bit.ly/2OrPYc5">Retrieve the value for the first key entered/sorted</a>
33  public object First => Count > 0 ? keys[index.Start()] : null;
34 
35  /// <a href="http://bit.ly/2OrPYc5">Retrieve the value for the second key entered/sorted</a>
36  public object Next => index.Reached(Count - 1) ? null : keys[index.Next()];
37 
38  private readonly CounterFifo index = CounterFifo.Instance;
39 
40  /// <a href="http://bit.ly/2Oq9wOe">Get a key by index based where 0 is the oldest/sorted</a>
41  public object this[int i] => keys[i];
42 
43  /// <a href="http://bit.ly/2Orh4QH">Array of keys in entry/sorted order</a>
44  public object[] Keys => keys.ToArray();
45 
46  /// <a href="http://bit.ly/2RezFOy">Sort keys ascending alphabetic</a>
47  public Map Sort() {
48  keys.Sort();
49  return this;
50  }
51 
52  /// <a href="http://bit.ly/2RezFOy">Sort keys using a comparator</a>
53  public Map Sort(Comparison<object> comparison) {
54  keys.Sort(Comparer<object>.Create(comparison));
55  return this;
56  }
57 
58  /// <a href="http://bit.ly/2RhchzZ">Prepare retrieval given a known key</a>
59  public Map this[object key] {
60  get {
61  Value = default;
62  Found = map.TryGetValue(Key = key, out Value);
63  return this;
64  }
65  }
66 
67  /// <a href="http://bit.ly/2Oq9DcC">Add a map or set entry</a>
68  public Map Add(object key, object value = null) {
69  if (key == null) return this;
70 
71  if (!map.ContainsKey(key)) keys.Add(key);
72  map[Key = key] = Value = value;
73  return this;
74  }
75 
76  /// <a href="http://bit.ly/2Rj0Rfg">Number of entries in the map</a>
77  public int Count => keys.Count;
78 
79  /// <a href="http://bit.ly/2Oq9qWS">Was the last search successful?</a>
80  public bool Found;
81 
82  /// <a href="http://bit.ly/2Rin6lu">Last key searched for</a>
83  public object Key;
84 
85  /// <a href="http://bit.ly/2Os3Wed">Last value found (null for failure)</a>
86  public object Value;
87 
88  /// <a href="http://bit.ly/2NUH9Io">Remove all entries - calling Dispose() on each one</a>
89  public virtual void Dispose() {
90  if (cached) { Cache<Map>.Dispose(this); } else { DeactivateItem(this); }
91  }
92 
93  internal static void DeactivateItem(Map item) {
94  for (var i = 0; i < item.Count; i++) (item.map[item.keys[i]] as IDisposable)?.Dispose();
95  item.keys.Clear();
96  item.map.Clear();
97  item.index.Dispose();
98  }
99 
100  /// <a href=""></a> //#TBD#//
101  public void Clear() {
102  keys.Clear();
103  map.Clear();
104  }
105 
106  /// <a href=""></a> //#TBD#//
107  public Dictionary<string, Tv> ToDictionary<Tv>() where Tv : class {
108  using (this) {
109  var dictionary = new Dictionary<string, Tv>();
110 
111  for (var key = First; key != null; key = Next) dictionary[key.ToString()] = this[key].Value as Tv;
112  return dictionary;
113  }
114  }
115 
116  /// <inheritdoc />
117  public override string ToString() {
118  (builder ?? (builder = new List<string>())).Clear();
119 
120  for (var key = First; key != null; key = Next) builder.Add($"{key}={this[key].Value}");
121 
122  return string.Join(separator: ", ", value: builder.ToArray());
123  }
124 
125  private List<string> builder;
126  private bool cached;
127  }
128 }
Definition: Clock.cs:3
Instance caching
Definition: Cache.cs:9
int Count
Number of entries in the map
Definition: Map.cs:77
static Map Instance
//#TBD#//
Definition: Map.cs:16
object Key
Last key searched for
Definition: Map.cs:83
A dictionary wrapper
Definition: Map.cs:10
A stack of counters for garbage-free iterations
Definition: CounterStack.cs:8
bool Found
Was the last search successful?
Definition: Map.cs:80
Map Add(object key, object value=null)
Add a map or set entry
Definition: Map.cs:68
object [] Keys
Array of keys in entry/sorted order
Definition: Map.cs:44
object First
Retrieve the value for the first key entered/sorted
Definition: Map.cs:33
override void Dispose()
Send back to recycling
object Next
Retrieve the value for the second key entered/sorted
Definition: Map.cs:36
void Clear()
//#TBD#//
Definition: Map.cs:101
Map Sort(Comparison< object > comparison)
Sort keys using a comparator
Definition: Map.cs:53
Map Remove(object key, bool dispose=true)
Remove an entry, optionally calling Dispose()
Definition: Map.cs:22
override string ToString()
Definition: Map.cs:117
Map Sort()
Sort keys ascending alphabetic
Definition: Map.cs:47
virtual void Dispose()
Remove all entries - calling Dispose() on each one
Definition: Map.cs:89
static new CounterFifo Instance
Retrieve a new (cached) instance
Definition: CounterStack.cs:10
Dictionary< string, Tv > ToDictionary< Tv >()
//#TBD#//
Definition: Map.cs:107
object Value
Last value found (null for failure)
Definition: Map.cs:86