2 // System.Collections.Generic.SortedDictionary
5 // Raja R Harinath <rharinath@novell.com>
7 // Authors of previous (superseded) version:
8 // Kazuki Oikawa (kazuki@panicode.com)
9 // Atsushi Enomoto (atsushi@ximian.com)
13 // Copyright (C) 2007, Novell, Inc.
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System.Collections;
39 namespace System.Collections.Generic
42 public class SortedDictionary<TKey,TValue> : IDictionary<TKey,TValue>, ICollection<KeyValuePair<TKey,TValue>>, IEnumerable<KeyValuePair<TKey,TValue>>, IDictionary, ICollection, IEnumerable
44 class Node : RBTree.Node {
48 public Node (TKey key)
53 public Node (TKey key, TValue value)
59 public override void SwapValue (RBTree.Node other)
61 Node o = (Node) other;
62 TKey k = key; key = o.key; o.key = k;
63 TValue v = value; value = o.value; o.value = v;
66 public KeyValuePair<TKey, TValue> AsKV ()
68 return new KeyValuePair<TKey, TValue> (key, value);
71 public DictionaryEntry AsDE ()
73 return new DictionaryEntry (key, value);
77 class NodeHelper : RBTree.INodeHelper<TKey> {
78 public IComparer<TKey> cmp;
80 public int Compare (TKey key, RBTree.Node node)
82 return cmp.Compare (key, ((Node) node).key);
85 public RBTree.Node CreateNode (TKey key)
87 return new Node (key);
90 private NodeHelper (IComparer<TKey> cmp)
94 static NodeHelper Default = new NodeHelper (Comparer<TKey>.Default);
95 public static NodeHelper GetHelper (IComparer<TKey> cmp)
97 if (cmp == null || cmp == Comparer<TKey>.Default)
99 return new NodeHelper (cmp);
107 public SortedDictionary () : this ((IComparer<TKey>) null)
111 public SortedDictionary (IComparer<TKey> comparer)
113 hlp = NodeHelper.GetHelper (comparer);
114 tree = new RBTree (hlp);
117 public SortedDictionary (IDictionary<TKey,TValue> dic) : this (dic, null)
121 public SortedDictionary (IDictionary<TKey,TValue> dic, IComparer<TKey> comparer) : this (comparer)
124 throw new ArgumentNullException ();
125 foreach (KeyValuePair<TKey, TValue> entry in dic)
126 Add (entry.Key, entry.Value);
130 #region PublicProperty
132 public IComparer<TKey> Comparer {
133 get { return hlp.cmp; }
137 get { return (int) tree.Count; }
140 public TValue this [TKey key] {
142 Node n = (Node) tree.Lookup (key);
144 throw new KeyNotFoundException ();
149 throw new ArgumentNullException ("key");
150 Node n = (Node) tree.Intern (key, null);
155 public KeyCollection Keys {
156 get { return new KeyCollection (this); }
159 public ValueCollection Values {
160 get { return new ValueCollection (this); }
166 public void Add (TKey key, TValue value)
169 throw new ArgumentNullException ("key");
171 RBTree.Node n = new Node (key, value);
172 if (tree.Intern (key, n) != n)
173 throw new ArgumentException ("key already present in dictionary", "key");
181 public bool ContainsKey (TKey key)
183 return tree.Lookup (key) != null;
186 public bool ContainsValue (TValue value)
188 IEqualityComparer<TValue> vcmp = EqualityComparer<TValue>.Default;
189 foreach (Node n in tree)
190 if (vcmp.Equals (value, n.value))
195 public void CopyTo (KeyValuePair<TKey,TValue>[] array, int arrayIndex)
198 throw new ArgumentNullException ();
199 if (arrayIndex < 0 || array.Length <= arrayIndex)
200 throw new ArgumentOutOfRangeException ();
201 if (array.Length - arrayIndex < Count)
202 throw new ArgumentException ();
204 foreach (Node n in tree)
205 array [arrayIndex ++] = n.AsKV ();
208 public Enumerator GetEnumerator ()
210 return new Enumerator (this);
213 public bool Remove (TKey key)
215 return tree.Remove (key) != null;
218 public bool TryGetValue (TKey key, out TValue value)
220 Node n = (Node) tree.Lookup (key);
221 value = n == null ? default (TValue) : n.value;
227 #region PrivateMethod
228 TKey ToKey (object key)
231 throw new ArgumentNullException ("key");
233 throw new ArgumentException (String.Format ("Key \"{0}\" cannot be converted to the key type {1}.", key, typeof (TKey)));
237 TValue ToValue (object value)
239 if (!(value is TValue) && (value != null || typeof (TValue).IsValueType))
240 throw new ArgumentException (String.Format ("Value \"{0}\" cannot be converted to the value type {1}.", value, typeof (TValue)));
241 return (TValue) value;
245 #region IDictionary<TKey,TValue> Member
247 ICollection<TKey> IDictionary<TKey,TValue>.Keys {
248 get { return new KeyCollection (this); }
251 ICollection<TValue> IDictionary<TKey,TValue>.Values {
252 get { return new ValueCollection (this); }
257 #region ICollection<KeyValuePair<TKey,TValue>> Member
259 void ICollection<KeyValuePair<TKey,TValue>>.Add (KeyValuePair<TKey,TValue> item)
261 Add (item.Key, item.Value);
264 bool ICollection<KeyValuePair<TKey,TValue>>.Contains (KeyValuePair<TKey,TValue> item)
267 return TryGetValue (item.Key, out value) &&
268 EqualityComparer<TValue>.Default.Equals (item.Value, value);
271 bool ICollection<KeyValuePair<TKey,TValue>>.IsReadOnly {
272 get { return false; }
275 bool ICollection<KeyValuePair<TKey,TValue>>.Remove (KeyValuePair<TKey,TValue> item)
278 return TryGetValue (item.Key, out value) &&
279 EqualityComparer<TValue>.Default.Equals (item.Value, value) &&
285 #region IDictionary Member
287 void IDictionary.Add (object key, object value)
289 Add (ToKey (key), ToValue (value));
292 bool IDictionary.Contains (object key)
294 return ContainsKey (ToKey (key));
297 IDictionaryEnumerator IDictionary.GetEnumerator ()
299 return new Enumerator (this);
302 bool IDictionary.IsFixedSize {
303 get { return false; }
306 bool IDictionary.IsReadOnly {
307 get { return false; }
310 ICollection IDictionary.Keys {
311 get { return new KeyCollection (this); }
314 void IDictionary.Remove (object key)
316 Remove (ToKey (key));
319 ICollection IDictionary.Values {
320 get { return new ValueCollection (this); }
323 object IDictionary.this [object key] {
324 get { return this [ToKey (key)]; }
325 set { this [ToKey (key)] = ToValue (value); }
330 #region ICollection Member
332 void ICollection.CopyTo (Array array, int index)
335 throw new ArgumentNullException ();
336 if (index < 0 || array.Length <= index)
337 throw new ArgumentOutOfRangeException ();
338 if (array.Length - index < Count)
339 throw new ArgumentException ();
341 foreach (Node n in tree)
342 array.SetValue (n.AsDE (), index++);
345 bool ICollection.IsSynchronized {
346 get { return false; }
349 // TODO:Is this correct? If this is wrong,please fix.
350 object ICollection.SyncRoot {
356 #region IEnumerable Member
358 IEnumerator IEnumerable.GetEnumerator ()
360 return new Enumerator (this);
365 #region IEnumerable<TKey> Member
367 IEnumerator<KeyValuePair<TKey,TValue>> IEnumerable<KeyValuePair<TKey,TValue>>.GetEnumerator ()
369 return new Enumerator (this);
375 public sealed class ValueCollection : ICollection<TValue>,
376 IEnumerable<TValue>, ICollection, IEnumerable
378 SortedDictionary<TKey,TValue> _dic;
380 public ValueCollection (SortedDictionary<TKey,TValue> dic)
385 void ICollection<TValue>.Add (TValue item)
387 throw new NotSupportedException ();
390 void ICollection<TValue>.Clear ()
392 throw new NotSupportedException ();
395 bool ICollection<TValue>.Contains (TValue item)
397 return _dic.ContainsValue (item);
400 public void CopyTo (TValue [] array, int arrayIndex)
403 throw new ArgumentNullException ();
404 if (arrayIndex < 0 || array.Length <= arrayIndex)
405 throw new ArgumentOutOfRangeException ();
406 if (array.Length - arrayIndex < Count)
407 throw new ArgumentException ();
408 foreach (Node n in _dic.tree)
409 array [arrayIndex++] = n.value;
413 get { return _dic.Count; }
416 bool ICollection<TValue>.IsReadOnly {
420 bool ICollection<TValue>.Remove (TValue item)
422 throw new NotSupportedException ();
425 IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator ()
427 return GetEnumerator ();
430 public Enumerator GetEnumerator ()
432 return new Enumerator (_dic);
435 void ICollection.CopyTo (Array array, int index)
438 throw new ArgumentNullException ();
439 if (index < 0 || array.Length <= index)
440 throw new ArgumentOutOfRangeException ();
441 if (array.Length - index < Count)
442 throw new ArgumentException ();
443 foreach (Node n in _dic.tree)
444 array.SetValue (n.value, index++);
447 bool ICollection.IsSynchronized {
448 get { return false; }
451 object ICollection.SyncRoot {
455 IEnumerator IEnumerable.GetEnumerator ()
457 return new Enumerator (_dic);
460 public struct Enumerator : IEnumerator<TValue>,IEnumerator, IDisposable
462 RBTree.NodeEnumerator host;
464 internal Enumerator (SortedDictionary<TKey,TValue> dic)
466 host = dic.tree.GetEnumerator ();
469 public TValue Current {
470 get { return ((Node) host.Current).value; }
473 public bool MoveNext ()
475 return host.MoveNext ();
478 public void Dispose ()
483 object IEnumerator.Current {
484 get { return Current; }
487 void IEnumerator.Reset ()
495 public sealed class KeyCollection : ICollection<TKey>,
496 IEnumerable<TKey>, ICollection, IEnumerable
498 SortedDictionary<TKey,TValue> _dic;
500 public KeyCollection (SortedDictionary<TKey,TValue> dic)
505 void ICollection<TKey>.Add (TKey item)
507 throw new NotSupportedException ();
510 void ICollection<TKey>.Clear ()
512 throw new NotSupportedException ();
515 bool ICollection<TKey>.Contains (TKey item)
517 return _dic.ContainsKey (item);
520 IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator ()
522 return GetEnumerator ();
525 public void CopyTo (TKey [] array, int arrayIndex)
528 throw new ArgumentNullException ();
529 if (arrayIndex < 0 || array.Length <= arrayIndex)
530 throw new ArgumentOutOfRangeException ();
531 if (array.Length - arrayIndex < Count)
532 throw new ArgumentException ();
533 foreach (Node n in _dic.tree)
534 array [arrayIndex++] = n.key;
538 get { return _dic.Count; }
541 bool ICollection<TKey>.IsReadOnly {
545 bool ICollection<TKey>.Remove (TKey item)
547 throw new NotSupportedException ();
550 public Enumerator GetEnumerator ()
552 return new Enumerator (_dic);
555 void ICollection.CopyTo (Array array, int index)
558 throw new ArgumentNullException ();
559 if (index < 0 || array.Length <= index)
560 throw new ArgumentOutOfRangeException ();
561 if (array.Length - index < Count)
562 throw new ArgumentException ();
563 foreach (Node n in _dic.tree)
564 array.SetValue (n.key, index++);
567 bool ICollection.IsSynchronized {
568 get { return false; }
571 object ICollection.SyncRoot {
575 IEnumerator IEnumerable.GetEnumerator ()
577 return new Enumerator (_dic);
580 public struct Enumerator : IEnumerator<TKey>, IEnumerator, IDisposable
582 RBTree.NodeEnumerator host;
584 internal Enumerator (SortedDictionary<TKey,TValue> dic)
586 host = dic.tree.GetEnumerator ();
589 public TKey Current {
590 get { return ((Node) host.Current).key; }
593 public bool MoveNext ()
595 return host.MoveNext ();
598 public void Dispose ()
603 object IEnumerator.Current {
604 get { return Current; }
607 void IEnumerator.Reset ()
614 public struct Enumerator : IEnumerator<KeyValuePair<TKey,TValue>>, IDisposable, IDictionaryEnumerator, IEnumerator
616 RBTree.NodeEnumerator host;
618 internal Enumerator (SortedDictionary<TKey,TValue> dic)
620 host = dic.tree.GetEnumerator ();
623 public KeyValuePair<TKey,TValue> Current {
624 get { return ((Node) host.Current).AsKV (); }
627 public bool MoveNext ()
629 return host.MoveNext ();
632 public void Dispose ()
637 DictionaryEntry IDictionaryEnumerator.Entry {
638 get { return ((Node) host.Current).AsDE (); }
641 object IDictionaryEnumerator.Key {
642 get { return ((Node) host.Current).key; }
645 object IDictionaryEnumerator.Value {
646 get { return ((Node) host.Current).value; }
649 object IEnumerator.Current {
650 get { return ((Node) host.Current).AsDE (); }
653 void IEnumerator.Reset ()