2010-04-02 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / class / System / System.Collections.Generic / SortedSet.cs
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
27 //
28
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;
38
39 // SortedSet is basically implemented as a reduction of SortedDictionary<K, V>
40
41 #if NET_4_0
42
43 namespace System.Collections.Generic {
44
45         [Serializable]
46         [DebuggerDisplay ("Count={Count}")]
47         [DebuggerTypeProxy (typeof (CollectionDebuggerView))]
48         public class SortedSet<T> : ISet<T>, ICollection, ISerializable, IDeserializationCallback
49         {
50                 class Node : RBTree.Node {
51
52                         public T item;
53
54                         public Node (T item)
55                         {
56                                 this.item = item;
57                         }
58
59                         public override void SwapValue (RBTree.Node other)
60                         {
61                                 var o = (Node) other;
62                                 var i = this.item;
63                                 this.item = o.item;
64                                 o.item = i;
65                         }
66                 }
67
68                 class NodeHelper : RBTree.INodeHelper<T> {
69
70                         static NodeHelper Default = new NodeHelper (Comparer<T>.Default);
71
72                         public IComparer<T> comparer;
73
74                         public int Compare (T item, RBTree.Node node)
75                         {
76                                 return comparer.Compare (item, ((Node) node).item);
77                         }
78
79                         public RBTree.Node CreateNode (T item)
80                         {
81                                 return new Node (item);
82                         }
83
84                         NodeHelper (IComparer<T> comparer)
85                         {
86                                 this.comparer = comparer;
87                         }
88
89                         public static NodeHelper GetHelper (IComparer<T> comparer)
90                         {
91                                 if (comparer == null || comparer == Comparer<T>.Default)
92                                         return Default;
93
94                                 return new NodeHelper (comparer);
95                         }
96                 }
97
98                 RBTree tree;
99                 NodeHelper helper;
100                 SerializationInfo si;
101
102                 public SortedSet ()
103                         : this (Comparer<T>.Default)
104                 {
105                 }
106
107                 public SortedSet (IEnumerable<T> collection)
108                         : this (collection, Comparer<T>.Default)
109                 {
110                 }
111
112                 public SortedSet (IEnumerable<T> collection, IComparer<T> comparer)
113                         : this (comparer)
114                 {
115                         if (collection == null)
116                                 throw new ArgumentNullException ("collection");
117
118                         foreach (var item in collection)
119                                 Add (item);
120                 }
121
122                 public SortedSet (IComparer<T> comparer)
123                 {
124                         this.helper = NodeHelper.GetHelper (comparer);
125                         this.tree = new RBTree (this.helper);
126                 }
127
128                 protected SortedSet (SerializationInfo info, StreamingContext context)
129                 {
130                         this.si = info;
131                 }
132
133                 public IComparer<T> Comparer {
134                         get { return helper.comparer; }
135                 }
136
137                 public int Count {
138                         get { return tree.Count; }
139                 }
140
141                 public T Max {
142                         get {
143                                 if (tree.Count == 0)
144                                         return default (T);
145
146                                 return ((Node) tree [tree.Count - 1]).item;
147                         }
148                 }
149
150                 public T Min {
151                         get {
152                                 if (tree.Count == 0)
153                                         return default (T);
154
155                                 return ((Node) tree [0]).item;
156                         }
157                 }
158
159                 public bool Add (T item)
160                 {
161                         return TryAdd (item);
162                 }
163
164                 internal virtual bool TryAdd (T item)
165                 {
166                         var node = new Node (item);
167                         return tree.Intern (item, node) == node;
168                 }
169
170                 public virtual void Clear ()
171                 {
172                         tree.Clear ();
173                 }
174
175                 public virtual bool Contains (T item)
176                 {
177                         return tree.Lookup (item) != null;
178                 }
179
180                 public void CopyTo (T [] array)
181                 {
182                         CopyTo (array, 0, Count);
183                 }
184
185                 public void CopyTo (T [] array, int index)
186                 {
187                         CopyTo (array, index, Count);
188                 }
189
190                 public void CopyTo (T [] array, int index, int count)
191                 {
192                         if (array == null)
193                                 throw new ArgumentNullException ("array");
194                         if (index < 0)
195                                 throw new ArgumentOutOfRangeException ("index");
196                         if (index > array.Length)
197                                 throw new ArgumentException ("index larger than largest valid index of array");
198                         if (array.Length - index < count)
199                                 throw new ArgumentException ("destination array cannot hold the requested elements");
200
201                         foreach (Node node in tree) {
202                                 if (count-- == 0)
203                                         break;
204
205                                 array [index++] = node.item;
206                         }
207                 }
208
209                 public bool Remove (T item)
210                 {
211                         return TryRemove (item);
212                 }
213
214                 internal virtual bool TryRemove (T item)
215                 {
216                         return tree.Remove (item) != null;
217                 }
218
219                 public int RemoveWhere (Predicate<T> match)
220                 {
221                         var array = ToArray ();
222
223                         int count = 0;
224                         foreach (var item in array) {
225                                 if (!match (item))
226                                         continue;
227
228                                 Remove (item);
229                                 count++;
230                         }
231
232                         return count;
233                 }
234
235                 public IEnumerable<T> Reverse ()
236                 {
237                         for (int i = tree.Count - 1; i >= 0; i--)
238                                 yield return ((Node) tree [i]).item;
239                 }
240
241                 T [] ToArray ()
242                 {
243                         var array = new T [this.Count];
244                         CopyTo (array);
245                         return array;
246                 }
247
248                 public Enumerator GetEnumerator ()
249                 {
250                         return new Enumerator (this);
251                 }
252
253                 IEnumerator<T> IEnumerable<T>.GetEnumerator ()
254                 {
255                         return new Enumerator (this);
256                 }
257
258                 IEnumerator IEnumerable.GetEnumerator ()
259                 {
260                         return new Enumerator (this);
261                 }
262
263                 public static IEqualityComparer<SortedSet<T>> CreateSetComparer ()
264                 {
265                         return CreateSetComparer (EqualityComparer<T>.Default);
266                 }
267
268                 [MonoTODO]
269                 public static IEqualityComparer<SortedSet<T>> CreateSetComparer (IEqualityComparer<T> memberEqualityComparer)
270                 {
271                         throw new NotImplementedException ();
272                 }
273
274                 [MonoTODO]
275                 protected virtual void GetObjectData (SerializationInfo info, StreamingContext context)
276                 {
277                         throw new NotImplementedException ();
278                 }
279
280                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
281                 {
282                         GetObjectData (info, context);
283                 }
284
285                 [MonoTODO]
286                 protected virtual void OnDeserialization (object sender)
287                 {
288                         if (si == null)
289                                 return;
290
291                         throw new NotImplementedException ();
292                 }
293
294                 void IDeserializationCallback.OnDeserialization (object sender)
295                 {
296                         OnDeserialization (sender);
297                 }
298
299                 [MonoTODO]
300                 public void ExceptWith (IEnumerable<T> other)
301                 {
302                         throw new NotImplementedException ();
303                 }
304
305                 [MonoTODO]
306                 public virtual SortedSet<T> GetViewBetween (T lowerValue, T upperValue)
307                 {
308                         throw new NotImplementedException ();
309                 }
310
311                 [MonoTODO]
312                 public virtual void IntersectWith (IEnumerable<T> other)
313                 {
314                         throw new NotImplementedException ();
315                 }
316
317                 [MonoTODO]
318                 public bool IsProperSubsetOf (IEnumerable<T> other)
319                 {
320                         throw new NotImplementedException ();
321                 }
322
323                 [MonoTODO]
324                 public bool IsProperSupersetOf (IEnumerable<T> other)
325                 {
326                         throw new NotImplementedException ();
327                 }
328
329                 [MonoTODO]
330                 public bool IsSubsetOf (IEnumerable<T> other)
331                 {
332                         throw new NotImplementedException ();
333                 }
334
335                 [MonoTODO]
336                 public bool IsSupersetOf (IEnumerable<T> other)
337                 {
338                         throw new NotImplementedException ();
339                 }
340
341                 [MonoTODO]
342                 public bool Overlaps (IEnumerable<T> other)
343                 {
344                         throw new NotImplementedException ();
345                 }
346
347                 [MonoTODO]
348                 public bool SetEquals (IEnumerable<T> other)
349                 {
350                         throw new NotImplementedException ();
351                 }
352
353                 [MonoTODO]
354                 public void SymmetricExceptWith (IEnumerable<T> other)
355                 {
356                         throw new NotImplementedException ();
357                 }
358
359                 [MonoTODO]
360                 public void UnionWith (IEnumerable<T> other)
361                 {
362                         throw new NotImplementedException ();
363                 }
364
365                 void ICollection<T>.Add (T item)
366                 {
367                         Add (item);
368                 }
369
370                 void ICollection<T>.CopyTo (T [] array, int index)
371                 {
372                         CopyTo (array, index, Count);
373                 }
374
375                 bool ICollection<T>.IsReadOnly {
376                         get { return false; }
377                 }
378
379                 void ICollection.CopyTo (Array array, int index)
380                 {
381                         if (Count == 0)
382                                 return;
383                         if (array == null)
384                                 throw new ArgumentNullException ("array");
385                         if (index < 0 || array.Length <= index)
386                                 throw new ArgumentOutOfRangeException ("index");
387                         if (array.Length - index < Count)
388                                 throw new ArgumentException ();
389
390                         foreach (Node node in tree)
391                                 array.SetValue (node.item, index++);
392                 }
393
394                 bool ICollection.IsSynchronized {
395                         get { return false; }
396                 }
397
398                 // TODO:Is this correct? If this is wrong,please fix.
399                 object ICollection.SyncRoot {
400                         get { return this; }
401                 }
402
403                 [Serializable]
404                 public struct Enumerator : IEnumerator<T>, IDisposable {
405
406                         RBTree.NodeEnumerator host;
407
408                         T current;
409
410                         internal Enumerator (SortedSet<T> set)
411                         {
412                                 host = set.tree.GetEnumerator ();
413                                 current = default (T);
414                         }
415
416                         public T Current {
417                                 get { return current; }
418                         }
419
420                         object IEnumerator.Current {
421                                 get {
422                                         host.check_current ();
423                                         return ((Node) host.Current).item;
424                                 }
425                         }
426
427                         public bool MoveNext ()
428                         {
429                                 if (!host.MoveNext ())
430                                         return false;
431
432                                 current = ((Node) host.Current).item;
433                                 return true;
434                         }
435
436                         public void Dispose ()
437                         {
438                                 host.Dispose ();
439                         }
440
441                         void IEnumerator.Reset ()
442                         {
443                                 host.Reset ();
444                         }
445                 }
446         }
447 }
448
449 #endif