2010-04-02 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System / System.Collections.Generic / SortedSet.cs
blobe0eaa670b2221f336b9741566b3738dc63342dab
1 //
2 // SortedSet.cs
3 //
4 // Authors:
5 // Jb Evain <jbevain@novell.com>
6 //
7 // Copyright (C) 2010 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System;
30 using System.Collections;
31 using System.Collections.Generic;
32 using System.Linq;
33 using System.Runtime.Serialization;
34 using System.Runtime.InteropServices;
35 using System.Security;
36 using System.Security.Permissions;
37 using System.Diagnostics;
39 // SortedSet is basically implemented as a reduction of SortedDictionary<K, V>
41 #if NET_4_0
43 namespace System.Collections.Generic {
45 [Serializable]
46 [DebuggerDisplay ("Count={Count}")]
47 [DebuggerTypeProxy (typeof (CollectionDebuggerView))]
48 public class SortedSet<T> : ISet<T>, ICollection, ISerializable, IDeserializationCallback
50 class Node : RBTree.Node {
52 public T item;
54 public Node (T item)
56 this.item = item;
59 public override void SwapValue (RBTree.Node other)
61 var o = (Node) other;
62 var i = this.item;
63 this.item = o.item;
64 o.item = i;
68 class NodeHelper : RBTree.INodeHelper<T> {
70 static NodeHelper Default = new NodeHelper (Comparer<T>.Default);
72 public IComparer<T> comparer;
74 public int Compare (T item, RBTree.Node node)
76 return comparer.Compare (item, ((Node) node).item);
79 public RBTree.Node CreateNode (T item)
81 return new Node (item);
84 NodeHelper (IComparer<T> comparer)
86 this.comparer = comparer;
89 public static NodeHelper GetHelper (IComparer<T> comparer)
91 if (comparer == null || comparer == Comparer<T>.Default)
92 return Default;
94 return new NodeHelper (comparer);
98 RBTree tree;
99 NodeHelper helper;
100 SerializationInfo si;
102 public SortedSet ()
103 : this (Comparer<T>.Default)
107 public SortedSet (IEnumerable<T> collection)
108 : this (collection, Comparer<T>.Default)
112 public SortedSet (IEnumerable<T> collection, IComparer<T> comparer)
113 : this (comparer)
115 if (collection == null)
116 throw new ArgumentNullException ("collection");
118 foreach (var item in collection)
119 Add (item);
122 public SortedSet (IComparer<T> comparer)
124 this.helper = NodeHelper.GetHelper (comparer);
125 this.tree = new RBTree (this.helper);
128 protected SortedSet (SerializationInfo info, StreamingContext context)
130 this.si = info;
133 public IComparer<T> Comparer {
134 get { return helper.comparer; }
137 public int Count {
138 get { return tree.Count; }
141 public T Max {
142 get { return GetMax (); }
145 public T Min {
146 get { return GetMin (); }
149 internal virtual T GetMax ()
151 if (tree.Count == 0)
152 return default (T);
154 return GetItem (tree.Count - 1);
157 internal virtual T GetMin ()
159 if (tree.Count == 0)
160 return default (T);
162 return GetItem (0);
165 T GetItem (int index)
167 return ((Node) tree [index]).item;
170 public bool Add (T item)
172 return TryAdd (item);
175 internal virtual bool TryAdd (T item)
177 var node = new Node (item);
178 return tree.Intern (item, node) == node;
181 public virtual void Clear ()
183 tree.Clear ();
186 public virtual bool Contains (T item)
188 return tree.Lookup (item) != null;
191 public void CopyTo (T [] array)
193 CopyTo (array, 0, Count);
196 public void CopyTo (T [] array, int index)
198 CopyTo (array, index, Count);
201 public void CopyTo (T [] array, int index, int count)
203 if (array == null)
204 throw new ArgumentNullException ("array");
205 if (index < 0)
206 throw new ArgumentOutOfRangeException ("index");
207 if (index > array.Length)
208 throw new ArgumentException ("index larger than largest valid index of array");
209 if (array.Length - index < count)
210 throw new ArgumentException ("destination array cannot hold the requested elements");
212 foreach (Node node in tree) {
213 if (count-- == 0)
214 break;
216 array [index++] = node.item;
220 public bool Remove (T item)
222 return TryRemove (item);
225 internal virtual bool TryRemove (T item)
227 return tree.Remove (item) != null;
230 public int RemoveWhere (Predicate<T> match)
232 var array = ToArray ();
234 int count = 0;
235 foreach (var item in array) {
236 if (!match (item))
237 continue;
239 Remove (item);
240 count++;
243 return count;
246 public IEnumerable<T> Reverse ()
248 for (int i = tree.Count - 1; i >= 0; i--)
249 yield return GetItem (i);
252 T [] ToArray ()
254 var array = new T [this.Count];
255 CopyTo (array);
256 return array;
259 public Enumerator GetEnumerator ()
261 return new Enumerator (this);
264 IEnumerator<T> IEnumerable<T>.GetEnumerator ()
266 return new Enumerator (this);
269 IEnumerator IEnumerable.GetEnumerator ()
271 return new Enumerator (this);
274 public static IEqualityComparer<SortedSet<T>> CreateSetComparer ()
276 return CreateSetComparer (EqualityComparer<T>.Default);
279 [MonoTODO]
280 public static IEqualityComparer<SortedSet<T>> CreateSetComparer (IEqualityComparer<T> memberEqualityComparer)
282 throw new NotImplementedException ();
285 [MonoTODO]
286 protected virtual void GetObjectData (SerializationInfo info, StreamingContext context)
288 throw new NotImplementedException ();
291 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
293 GetObjectData (info, context);
296 [MonoTODO]
297 protected virtual void OnDeserialization (object sender)
299 if (si == null)
300 return;
302 throw new NotImplementedException ();
305 void IDeserializationCallback.OnDeserialization (object sender)
307 OnDeserialization (sender);
310 [MonoTODO]
311 public void ExceptWith (IEnumerable<T> other)
313 throw new NotImplementedException ();
316 public virtual SortedSet<T> GetViewBetween (T lowerValue, T upperValue)
318 if (Comparer.Compare (lowerValue, upperValue) > 0)
319 throw new ArgumentException ("The lowerValue is bigger than upperValue");
321 return new SortedSubSet (this, lowerValue, upperValue);
324 [MonoTODO]
325 public virtual void IntersectWith (IEnumerable<T> other)
327 throw new NotImplementedException ();
330 [MonoTODO]
331 public bool IsProperSubsetOf (IEnumerable<T> other)
333 throw new NotImplementedException ();
336 [MonoTODO]
337 public bool IsProperSupersetOf (IEnumerable<T> other)
339 throw new NotImplementedException ();
342 [MonoTODO]
343 public bool IsSubsetOf (IEnumerable<T> other)
345 throw new NotImplementedException ();
348 [MonoTODO]
349 public bool IsSupersetOf (IEnumerable<T> other)
351 throw new NotImplementedException ();
354 [MonoTODO]
355 public bool Overlaps (IEnumerable<T> other)
357 throw new NotImplementedException ();
360 [MonoTODO]
361 public bool SetEquals (IEnumerable<T> other)
363 throw new NotImplementedException ();
366 [MonoTODO]
367 public void SymmetricExceptWith (IEnumerable<T> other)
369 throw new NotImplementedException ();
372 [MonoTODO]
373 public void UnionWith (IEnumerable<T> other)
375 throw new NotImplementedException ();
378 void ICollection<T>.Add (T item)
380 Add (item);
383 void ICollection<T>.CopyTo (T [] array, int index)
385 CopyTo (array, index, Count);
388 bool ICollection<T>.IsReadOnly {
389 get { return false; }
392 void ICollection.CopyTo (Array array, int index)
394 if (Count == 0)
395 return;
396 if (array == null)
397 throw new ArgumentNullException ("array");
398 if (index < 0 || array.Length <= index)
399 throw new ArgumentOutOfRangeException ("index");
400 if (array.Length - index < Count)
401 throw new ArgumentException ();
403 foreach (Node node in tree)
404 array.SetValue (node.item, index++);
407 bool ICollection.IsSynchronized {
408 get { return false; }
411 // TODO:Is this correct? If this is wrong,please fix.
412 object ICollection.SyncRoot {
413 get { return this; }
416 [Serializable]
417 public struct Enumerator : IEnumerator<T>, IDisposable {
419 RBTree.NodeEnumerator host;
421 T current;
423 internal Enumerator (SortedSet<T> set)
425 host = set.tree.GetEnumerator ();
426 current = default (T);
429 public T Current {
430 get { return current; }
433 object IEnumerator.Current {
434 get {
435 host.check_current ();
436 return ((Node) host.Current).item;
440 public bool MoveNext ()
442 if (!host.MoveNext ())
443 return false;
445 current = ((Node) host.Current).item;
446 return true;
449 public void Dispose ()
451 host.Dispose ();
454 void IEnumerator.Reset ()
456 host.Reset ();
460 [Serializable]
461 sealed class SortedSubSet : SortedSet<T>, IEnumerable<T>, IEnumerable {
463 SortedSet<T> set;
464 T lower;
465 T upper;
467 public SortedSubSet (SortedSet<T> set, T lower, T upper)
468 : base (set.Comparer)
470 this.set = set;
471 this.lower = lower;
472 this.upper = upper;
475 internal override T GetMin ()
477 for (int i = 0; i < set.tree.Count; i++) {
478 var item = set.GetItem (i);
479 if (InRange (item))
480 return item;
483 return default (T);
486 internal override T GetMax ()
488 for (int i = set.tree.Count - 1; i >= 0; i--) {
489 var item = set.GetItem (i);
490 if (InRange (item))
491 return item;
494 return default (T);
497 internal override bool TryAdd (T item)
499 if (!InRange (item))
500 throw new ArgumentOutOfRangeException ("item");
502 return set.TryAdd (item);
505 internal override bool TryRemove (T item)
507 if (!InRange (item))
508 return false;
510 return set.TryRemove (item);
513 public override bool Contains (T item)
515 if (!InRange (item))
516 return false;
518 return set.Contains (item);
521 public override void Clear ()
523 set.RemoveWhere (InRange);
526 bool InRange (T item)
528 return Comparer.Compare (item, lower) >= 0
529 && Comparer.Compare (item, upper) <= 0;
532 public override SortedSet<T> GetViewBetween (T lowerValue, T upperValue)
534 if (Comparer.Compare (lowerValue, upperValue) > 0)
535 throw new ArgumentException ("The lowerValue is bigger than upperValue");
536 if (!InRange (lowerValue))
537 throw new ArgumentOutOfRangeException ("lowerValue");
538 if (!InRange (upperValue))
539 throw new ArgumentOutOfRangeException ("upperValue");
541 return new SortedSubSet (set, lowerValue, upperValue);
544 public IEnumerator<T> GetEnumerator ()
546 var yielding = false;
548 foreach (Node node in set.tree) {
549 var item = node.item;
551 if (InRange (item)) {
552 yield return item;
553 yielding = true;
554 } else if (yielding)
555 yield break;
559 IEnumerator<T> IEnumerable<T>.GetEnumerator ()
561 return GetEnumerator ();
564 IEnumerator IEnumerable.GetEnumerator ()
566 return GetEnumerator ();
572 #endif