36 using System.Collections;
37 using System.Collections.Generic;
38 using System.Diagnostics;
40 namespace SiliconStudio.Core.Collections
47 [DebuggerDisplay(
"Count = {Count}")]
50 private readonly
static int INITIAL_SIZE = 16;
52 private enum EnumeratorMode :
int { KEY_MODE = 0, VALUE_MODE, ENTRY_MODE }
55 private int modificationCount;
56 private KeyValuePair<TKey, TValue>[] table;
58 private int defaultCapacity;
64 : this(INITIAL_SIZE, null)
69 : this(capacity, null)
76 throw new ArgumentOutOfRangeException(
"initialCapacity");
81 defaultCapacity = INITIAL_SIZE;
82 Init(comparer, capacity,
true);
86 : this(INITIAL_SIZE, comparer)
91 : this(dictionary, null)
97 if (dictionary == null)
98 throw new ArgumentNullException(
"dictionary");
100 Init(comparer, dictionary.Count,
true);
102 foreach (KeyValuePair<TKey, TValue> kvp
in dictionary)
103 Add(kvp.Key, kvp.Value);
120 bool ICollection.IsSynchronized
128 Object ICollection.SyncRoot
138 bool IDictionary.IsFixedSize
146 bool IDictionary.IsReadOnly
154 public TValue
this[TKey key]
159 throw new ArgumentNullException(
"key");
164 return table[i].Value;
166 throw new KeyNotFoundException();
171 throw new ArgumentNullException(
"key");
173 PutImpl(key, value,
true);
177 object IDictionary.this[
object key]
184 return this[(TKey)key];
189 this[ToKey(key)] = ToValue(value);
202 int current = this.table.Length;
206 throw new ArgumentOutOfRangeException(
"capacity too small");
211 KeyValuePair<TKey, TValue>[] newTable =
new KeyValuePair<TKey, TValue>[defaultCapacity];
212 Array.Copy(table, newTable, inUse);
213 this.table = newTable;
216 else if (current > defaultCapacity && value < current) {
217 KeyValuePair<TKey, TValue> [] newTable =
new KeyValuePair<TKey, TValue> [defaultCapacity];
218 Array.Copy (table, newTable, inUse);
219 this.table = newTable;
222 else if (value > inUse)
224 KeyValuePair<TKey, TValue>[] newTable =
new KeyValuePair<TKey, TValue>[value];
225 Array.Copy(table, newTable, inUse);
226 this.table = newTable;
228 else if (value > current)
230 KeyValuePair<TKey, TValue>[] newTable =
new KeyValuePair<TKey, TValue>[value];
231 Array.Copy(table, newTable, current);
232 this.table = newTable;
237 public IList<TKey>
Keys
241 return new ListKeys(
this);
245 public IList<TValue> Values
249 return new ListValues(
this);
257 return new ListKeys(
this);
265 return new ListValues(
this);
305 public void Add(TKey key, TValue value)
308 throw new ArgumentNullException(
"key");
310 PutImpl(key, value,
false);
316 throw new ArgumentNullException(
"key");
318 return (Find(key) >= 0);
323 for (
int i = 0; i < inUse; i++)
325 KeyValuePair<TKey, TValue> current = this.table[i];
327 yield
return new KeyValuePair<TKey, TValue>(current.Key, current.Value);
334 throw new ArgumentNullException(
"key");
336 int i = IndexOfKey(key);
350 defaultCapacity = INITIAL_SIZE;
351 this.table =
new KeyValuePair<TKey, TValue>[defaultCapacity];
358 defaultCapacity = INITIAL_SIZE;
359 this.table =
new KeyValuePair<TKey, TValue>[defaultCapacity];
370 throw new ArgumentNullException();
373 throw new ArgumentOutOfRangeException();
375 if (arrayIndex >= array.Length)
376 throw new ArgumentNullException(
"arrayIndex is greater than or equal to array.Length");
377 if (Count > (array.Length - arrayIndex))
378 throw new ArgumentNullException(
"Not enough space in array from arrayIndex to end of array");
381 foreach (KeyValuePair<TKey, TValue> pair
in this)
387 Add(keyValuePair.Key, keyValuePair.Value);
392 int i = Find(keyValuePair.Key);
395 return Comparer<KeyValuePair<TKey, TValue>>.Default.Compare(table[i], keyValuePair) == 0;
402 int i = Find(keyValuePair.Key);
404 if (i >= 0 && (Comparer<KeyValuePair<TKey, TValue>>.Default.Compare(table[i], keyValuePair) == 0))
417 for (
int i = 0; i < inUse; i++)
419 KeyValuePair<TKey, TValue> current = this.table[i];
421 yield
return new KeyValuePair<TKey, TValue>(current.Key, current.Value);
427 IEnumerator IEnumerable.GetEnumerator()
429 return GetEnumerator();
434 void IDictionary.Add(
object key,
object value)
436 PutImpl(ToKey(key), ToValue(value),
false);
439 bool IDictionary.Contains(
object key)
442 throw new ArgumentNullException();
446 return (Find((TKey)key) >= 0);
449 IDictionaryEnumerator IDictionary.GetEnumerator()
451 return new Enumerator(
this, EnumeratorMode.ENTRY_MODE);
454 void IDictionary.Remove(
object key)
457 throw new ArgumentNullException(
"key");
460 int i = IndexOfKey((TKey)key);
461 if (i >= 0) RemoveAt(i);
466 void ICollection.CopyTo(
Array array,
int arrayIndex)
472 throw new ArgumentNullException();
475 throw new ArgumentOutOfRangeException();
478 throw new ArgumentException(
"array is multi-dimensional");
479 if (arrayIndex >= array.Length)
480 throw new ArgumentNullException(
"arrayIndex is greater than or equal to array.Length");
481 if (Count > (array.Length - arrayIndex))
482 throw new ArgumentNullException(
"Not enough space in array from arrayIndex to end of array");
484 IEnumerator<KeyValuePair<TKey, TValue>> it = GetEnumerator();
487 while (it.MoveNext())
489 array.SetValue(it.Current, i++);
499 KeyValuePair<TKey, TValue>[] table = this.table;
501 if (index >= 0 && index < cnt)
503 if (index != cnt - 1)
505 Array.Copy(table, index + 1, table, index, cnt - 1 - index);
509 table[index] =
default(KeyValuePair<TKey, TValue>);
516 throw new ArgumentOutOfRangeException(
"index out of range");
523 throw new ArgumentNullException(
"key");
532 throw new InvalidOperationException();
535 return (indx | (indx >> 31));
543 for (
int i = 0; i < inUse; i++)
545 KeyValuePair<TKey, TValue> current = this.table[i];
547 if (Equals(value, current.Value))
556 return IndexOfValue(value) >= 0;
561 if (inUse < table.Length * 0.9)
568 throw new ArgumentNullException(
"key");
574 value = table[i].Value;
579 value =
default(TValue);
588 private void EnsureCapacity(
int n,
int free)
590 KeyValuePair<TKey, TValue>[] table = this.table;
591 KeyValuePair<TKey, TValue>[] newTable = null;
593 bool gap = (free >= 0 && free < Count);
597 newTable =
new KeyValuePair<TKey, TValue>[n << 1];
600 if (newTable != null)
607 Array.Copy(table, 0, newTable, 0, copyLen);
609 copyLen = Count - free;
612 Array.Copy(table, free, newTable, free + 1, copyLen);
618 Array.Copy(table, newTable,
Count);
620 this.table = newTable;
624 Array.Copy(table, free, table, free + 1,
Count - free);
628 private void PutImpl(TKey key, TValue value,
bool overwrite)
631 throw new ArgumentNullException(
"null key");
633 KeyValuePair<TKey, TValue>[] table = this.table;
639 freeIndx = Find(key);
643 throw new InvalidOperationException();
649 throw new ArgumentException(
"element already exists");
651 table[freeIndx] =
new KeyValuePair<TKey, TValue>(key, value);
656 freeIndx = ~freeIndx;
658 if (freeIndx > Capacity + 1)
659 throw new Exception(
"SortedList::internal error (" + key +
", " + value +
") at [" + freeIndx +
"]");
662 EnsureCapacity(Count + 1, freeIndx);
665 table[freeIndx] =
new KeyValuePair<TKey, TValue>(key, value);
674 if (comparer == null)
675 comparer = Comparer<TKey>.Default;
676 this.comparer = comparer;
677 if (!forceSize && (capacity < defaultCapacity))
678 capacity = defaultCapacity;
679 this.table =
new KeyValuePair<TKey, TValue>[capacity];
681 this.modificationCount = 0;
684 private void CopyToArray(Array arr,
int i,
688 throw new ArgumentNullException(
"arr");
690 if (i < 0 || i + this.Count > arr.Length)
691 throw new ArgumentOutOfRangeException(
"i");
693 IEnumerator it =
new Enumerator(
this, mode);
695 while (it.MoveNext())
697 arr.SetValue(it.Current, i++);
701 private int Find(TKey key)
703 KeyValuePair<TKey, TValue>[] table = this.table;
706 if (len == 0)
return ~0;
711 while (left <= right)
713 int guess = (left + right) >> 1;
715 int cmp = comparer.Compare(table[guess].Key, key);
716 if (cmp == 0)
return guess;
718 if (cmp < 0) left = guess + 1;
719 else right = guess - 1;
725 private TKey ToKey(
object key)
728 throw new ArgumentNullException(
"key");
730 throw new ArgumentException(
"The value \"" + key +
"\" isn't of type \"" + typeof(TKey) +
"\" and can't be used in this generic collection.",
"key");
734 private TValue ToValue(
object value)
736 if (!(value is TValue))
737 throw new ArgumentException(
"The value \"" + value +
"\" isn't of type \"" + typeof(TValue) +
"\" and can't be used in this generic collection.",
"value");
738 return (TValue)value;
741 internal TKey KeyAt(
int index)
743 if (index >= 0 && index < Count)
744 return table[index].Key;
746 throw new ArgumentOutOfRangeException(
"Index out of range");
749 internal TValue ValueAt(
int index)
751 if (index >= 0 && index < Count)
752 return table[index].Value;
754 throw new ArgumentOutOfRangeException(
"Index out of range");
762 private sealed
class Enumerator : IDictionaryEnumerator, IEnumerator
765 private SortedList<TKey, TValue> host;
769 private EnumeratorMode mode;
771 private object currentKey;
772 private object currentValue;
774 bool invalid =
false;
776 private readonly
static string xstr =
"SortedList.Enumerator: snapshot out of sync.";
778 public Enumerator(SortedList<TKey, TValue> host, EnumeratorMode mode)
781 stamp = host.modificationCount;
787 public Enumerator(SortedList<TKey, TValue> host)
788 : this(host, EnumeratorMode.ENTRY_MODE)
794 if (host.modificationCount != stamp || invalid)
795 throw new InvalidOperationException(xstr);
802 public bool MoveNext()
804 if (host.modificationCount != stamp || invalid)
805 throw new InvalidOperationException(xstr);
807 KeyValuePair<TKey, TValue>[] table = host.table;
811 KeyValuePair<TKey, TValue> entry = table[pos];
813 currentKey = entry.Key;
814 currentValue = entry.Value;
823 public DictionaryEntry Entry
827 if (invalid || pos >=
size || pos == -1)
828 throw new InvalidOperationException(xstr);
830 return new DictionaryEntry(currentKey,
839 if (invalid || pos >=
size || pos == -1)
840 throw new InvalidOperationException(xstr);
849 if (invalid || pos >=
size || pos == -1)
850 throw new InvalidOperationException(xstr);
859 if (invalid || pos >=
size || pos == -1)
860 throw new InvalidOperationException(xstr);
864 case EnumeratorMode.KEY_MODE:
866 case EnumeratorMode.VALUE_MODE:
868 case EnumeratorMode.ENTRY_MODE:
872 throw new NotSupportedException(mode +
" is not a supported mode.");
879 public object Clone()
881 Enumerator e =
new Enumerator(host, mode);
885 e.currentKey = currentKey;
886 e.currentValue = currentValue;
892 struct KeyEnumerator : IEnumerator<TKey>, IDisposable
894 const int NOT_STARTED = -2;
898 const int FINISHED = -1;
900 SortedList<TKey, TValue> l;
904 internal KeyEnumerator(SortedList<TKey, TValue> l)
908 ver = l.modificationCount;
911 public void Dispose()
916 public bool MoveNext()
918 if (ver != l.modificationCount)
919 throw new InvalidOperationException(
"Collection was modified after the enumerator was instantiated.");
921 if (idx == NOT_STARTED)
924 return idx != FINISHED && --idx != FINISHED;
932 throw new InvalidOperationException();
934 return l.KeyAt(l.Count - 1 - idx);
938 void IEnumerator.Reset()
940 if (ver != l.modificationCount)
941 throw new InvalidOperationException(
"Collection was modified after the enumerator was instantiated.");
946 object IEnumerator.Current
948 get {
return Current; }
952 struct ValueEnumerator : IEnumerator<TValue>, IDisposable
954 const int NOT_STARTED = -2;
958 const int FINISHED = -1;
960 SortedList<TKey, TValue> l;
964 internal ValueEnumerator(SortedList<TKey, TValue> l)
968 ver = l.modificationCount;
971 public void Dispose()
976 public bool MoveNext()
978 if (ver != l.modificationCount)
979 throw new InvalidOperationException(
"Collection was modified after the enumerator was instantiated.");
981 if (idx == NOT_STARTED)
984 return idx != FINISHED && --idx != FINISHED;
987 public TValue Current
992 throw new InvalidOperationException();
994 return l.ValueAt(l.Count - 1 - idx);
998 void IEnumerator.Reset()
1000 if (ver != l.modificationCount)
1001 throw new InvalidOperationException(
"Collection was modified after the enumerator was instantiated.");
1006 object IEnumerator.Current
1008 get {
return Current; }
1015 private SortedList<TKey, TValue> host;
1017 public ListKeys(SortedList<TKey, TValue> host)
1020 throw new ArgumentNullException();
1027 public virtual void Add(TKey item)
1029 throw new NotSupportedException();
1032 public virtual bool Remove(TKey key)
1034 throw new NotSupportedException();
1037 public virtual void Clear()
1039 throw new NotSupportedException();
1042 public virtual void CopyTo(TKey[] array,
int arrayIndex)
1044 if (host.Count == 0)
1047 throw new ArgumentNullException(
"array");
1049 throw new ArgumentOutOfRangeException();
1050 if (arrayIndex >= array.Length)
1051 throw new ArgumentOutOfRangeException(
"arrayIndex is greater than or equal to array.Length");
1052 if (Count > (array.Length - arrayIndex))
1053 throw new ArgumentOutOfRangeException(
"Not enough space in array from arrayIndex to end of array");
1056 for (
int i = 0; i <
Count; ++i)
1057 array[j++] = host.KeyAt(i);
1060 public virtual bool Contains(TKey item)
1062 return host.IndexOfKey(item) > -1;
1068 public virtual int IndexOf(TKey item)
1070 return host.IndexOfKey(item);
1073 public virtual void Insert(
int index, TKey item)
1075 throw new NotSupportedException();
1078 public virtual void RemoveAt(
int index)
1080 throw new NotSupportedException();
1083 public virtual TKey
this[
int index]
1087 return host.KeyAt(index);
1091 throw new NotSupportedException(
"attempt to modify a key");
1099 public virtual IEnumerator<TKey> GetEnumerator()
1102 return new KeyEnumerator(host);
1109 public virtual int Count
1117 public virtual bool IsSynchronized
1125 public virtual bool IsReadOnly
1133 public virtual Object SyncRoot
1141 public virtual void CopyTo(Array array,
int arrayIndex)
1143 host.CopyToArray(array, arrayIndex, EnumeratorMode.KEY_MODE);
1150 IEnumerator IEnumerable.GetEnumerator()
1152 for (
int i = 0; i < host.Count; ++i)
1153 yield
return host.KeyAt(i);
1160 private SortedList<TKey, TValue> host;
1162 public ListValues(SortedList<TKey, TValue> host)
1165 throw new ArgumentNullException();
1172 public virtual void Add(TValue item)
1174 throw new NotSupportedException();
1177 public virtual bool Remove(TValue value)
1179 throw new NotSupportedException();
1182 public virtual void Clear()
1184 throw new NotSupportedException();
1187 public virtual void CopyTo(TValue[] array,
int arrayIndex)
1189 if (host.Count == 0)
1192 throw new ArgumentNullException(
"array");
1194 throw new ArgumentOutOfRangeException();
1195 if (arrayIndex >= array.Length)
1196 throw new ArgumentOutOfRangeException(
"arrayIndex is greater than or equal to array.Length");
1197 if (Count > (array.Length - arrayIndex))
1198 throw new ArgumentOutOfRangeException(
"Not enough space in array from arrayIndex to end of array");
1201 for (
int i = 0; i <
Count; ++i)
1202 array[j++] = host.ValueAt(i);
1205 public virtual bool Contains(TValue item)
1207 return host.IndexOfValue(item) > -1;
1213 public virtual int IndexOf(TValue item)
1215 return host.IndexOfValue(item);
1218 public virtual void Insert(
int index, TValue item)
1220 throw new NotSupportedException();
1223 public virtual void RemoveAt(
int index)
1225 throw new NotSupportedException();
1228 public virtual TValue
this[
int index]
1232 return host.ValueAt(index);
1236 throw new NotSupportedException(
"attempt to modify a key");
1244 public virtual IEnumerator<TValue> GetEnumerator()
1247 return new ValueEnumerator(host);
1254 public virtual int Count
1262 public virtual bool IsSynchronized
1270 public virtual bool IsReadOnly
1278 public virtual Object SyncRoot
1286 public virtual void CopyTo(Array array,
int arrayIndex)
1288 host.CopyToArray(array, arrayIndex, EnumeratorMode.VALUE_MODE);
1295 IEnumerator IEnumerable.GetEnumerator()
1297 for (
int i = 0; i < host.Count; ++i)
1298 yield
return host.ValueAt(i);
bool ContainsKey(TKey key)
void Add(TKey key, TValue value)
IEnumerator< KeyValuePair< TKey, TValue > > GetEnumerator()
SortedList(IComparer< TKey > comparer)
SiliconStudio.Paradox.Input.Keys Keys
One bounding volume completely contains another.
The clone mixin to clone the current mixins where the clone is emitted.
int IndexOfValue(TValue value)
SortedList(int capacity, IComparer< TKey > comparer)
bool ContainsValue(TValue value)
The remove mixin to remove a mixin from current mixins.
SortedList(IDictionary< TKey, TValue > dictionary, IComparer< TKey > comparer)
bool TryGetValue(TKey key, out TValue value)
The device failed due to a badly formed command. This is a run-time issue; The application should des...
_In_ size_t _In_ size_t size
SortedList(IDictionary< TKey, TValue > dictionary)