16 #region Using directives
27 internal class ObjectMap
31 private bool m_readonly;
32 private MapProvider m_mapProvider;
34 private const int MAXINDEX = 255;
35 private const int GROWTH = 32;
36 private const int MINSIZE = 32;
37 private const int MAXARRAYCOUNT = 12;
39 private const int INVALIDKEY = Int32.MaxValue;
50 m_mapProvider =
new SortedMapProvider(MINSIZE);
55 #region Public members.
62 get {
return m_mapProvider.m_count; }
70 get {
return m_readonly; }
73 if (m_readonly != value)
75 SetMapProvider(value);
84 public object this[
int key]
86 get {
return m_mapProvider[key]; }
87 set { m_mapProvider.Add(key, value); }
95 public int GetKey(
int index)
97 return m_mapProvider.GetEntry(index).Key;
104 public void Remove(
int key)
106 m_mapProvider.Remove(key);
115 public void Add(
int key,
object value)
117 m_mapProvider.Add(key, value);
122 #region Private members
124 private void SetMapProvider(
bool readOnly)
126 int count = m_mapProvider.m_count;
127 MapProvider provider = m_mapProvider;
130 SortedMapProvider pr = m_mapProvider as SortedMapProvider;
131 if (pr.m_lastKey <= MAXINDEX)
133 provider =
new IndexMapProvider();
135 else if (count <= MAXARRAYCOUNT)
137 provider =
new ArrayMapProvider(m_mapProvider.m_count);
142 if (! (provider is SortedMapProvider))
144 provider =
new SortedMapProvider(m_mapProvider.m_count);
147 if (provider != m_mapProvider)
149 for (
int i = 0; i <
count; i++)
151 Entry entry = m_mapProvider.GetEntry(i);
152 provider.Add(entry.Key, entry.Value);
154 m_mapProvider = provider;
160 #region Entry struct definition
165 internal object Value;
167 internal Entry(
int key,
object value)
176 private abstract class MapProvider
178 internal int m_count;
180 internal abstract object this[
int key]
185 internal abstract Entry GetEntry(
int index);
187 internal abstract void Add(
int key,
object value);
189 internal virtual void Remove(
int key)
191 throw new InvalidOperationException();
195 private class SortedMapProvider : MapProvider
197 internal Entry[] m_entries;
199 internal int m_lastKey;
201 internal SortedMapProvider(
int capacity)
203 m_entries =
new Entry[capacity];
206 internal override object this[
int key]
211 int maxIndex = m_count - 1;
212 if (maxIndex >= 0 && key <= m_lastKey)
216 int midIndex = (maxIndex + minIndex) / 2;
217 if (key <= m_entries[midIndex].Key)
223 minIndex = midIndex + 1;
225 }
while (minIndex < maxIndex);
226 if (key == m_entries[minIndex].Key)
228 return m_entries[minIndex].Value;
235 internal override Entry GetEntry(
int index)
237 return m_entries[index];
240 internal override void Add(
int key,
object value)
243 int index = FindInsertIndex(key, out found);
246 m_entries[index].Value = value;
249 if (m_count >= m_entries.Length)
251 Entry[] entries =
new Entry[m_entries.Length + GROWTH];
252 Array.Copy(m_entries, 0, entries, 0, m_entries.Length);
257 Array.Copy(m_entries, index, m_entries, index + 1, m_count - index);
263 m_entries[index].Key = key;
264 m_entries[index].Value = value;
268 internal override void Remove(
int key)
270 int index = FindIndex(key);
273 int tailSize = (m_count - 1) - index;
276 Array.Copy(m_entries, index + 1, m_entries, index, tailSize);
278 else if (m_count > 1)
280 m_lastKey = m_entries[m_count - 2].Key;
284 m_lastKey = INVALIDKEY;
287 m_entries[m_count].Key = INVALIDKEY;
288 m_entries[m_count].Value = null;
292 private int FindIndex(
int key)
295 if (m_count > 0 && key <= m_lastKey)
297 int maxIndex = m_count - 1;
300 int midIndex = (maxIndex + minIndex) / 2;
301 if (key <= m_entries[midIndex].Key)
307 minIndex = midIndex + 1;
309 }
while (minIndex < maxIndex);
310 if (key == m_entries[minIndex].Key)
318 private int FindInsertIndex(
int key, out
bool found)
321 if (m_count > 0 && key <= m_lastKey)
323 int maxIndex = m_count - 1;
326 int midIndex = (maxIndex + minIndex) / 2;
327 if (key <= m_entries[midIndex].Key)
333 minIndex = midIndex + 1;
335 }
while (minIndex < maxIndex);
336 found = (key == m_entries[minIndex].Key);
344 private class IndexMapProvider : MapProvider
346 private object[] m_array;
348 internal IndexMapProvider()
350 m_array =
new object[MAXINDEX + 1];
351 for (
int i = m_array.Length; --i >= 0; )
353 m_array[i] = Unassigned.Value;
357 internal override object this[
int key]
361 if (key >= m_array.Length || key < 0)
369 internal override Entry GetEntry(
int index)
372 for (
int i = 0; i < m_array.Length; i++)
374 object value = m_array[i];
375 if (value != Unassigned.Value)
381 return new Entry(i, value);
387 internal override void Add(
int key,
object value)
389 m_array[key] = value;
394 private class ArrayMapProvider : MapProvider
396 private Entry[] m_entries;
398 internal ArrayMapProvider(
int capacity)
400 m_entries =
new Entry[capacity];
403 internal override object this[
int key]
407 for (
int i = m_count; --i >= 0;)
409 Entry entry = m_entries[i];
410 int entryKey = entry.Key;
415 else if (entryKey == key)
419 else if (entryKey < key)
428 internal override Entry GetEntry(
int index)
430 return m_entries[index];
433 internal override void Add(
int key,
object value)
435 m_entries[m_count].Key = key;
436 m_entries[m_count].Value = value;
441 private class Unassigned
443 internal static Unassigned
Value =
new Unassigned();
Only valid for a property that will be used only as a "read only" property.
The remove mixin to remove a mixin from current mixins.