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 (int) tree.Count; }
139                 }
140
141                 [MonoTODO]
142                 public T Max {
143                         get { throw new NotImplementedException (); }
144                 }
145
146                 [MonoTODO]
147                 public T Min {
148                         get { throw new NotImplementedException (); }
149                 }
150
151                 public bool Add (T item)
152                 {
153                         var node = new Node (item);
154                         return tree.Intern (item, node) == node;
155                 }
156
157                 public virtual void Clear ()
158                 {
159                         tree.Clear ();
160                 }
161
162                 public virtual bool Contains (T item)
163                 {
164                         return tree.Lookup (item) != null;
165                 }
166
167                 public void CopyTo (T [] array)
168                 {
169                         CopyTo (array, 0, Count);
170                 }
171
172                 public void CopyTo (T [] array, int index)
173                 {
174                         CopyTo (array, index, Count);
175                 }
176
177                 public void CopyTo (T [] array, int index, int count)
178                 {
179                         if (array == null)
180                                 throw new ArgumentNullException ("array");
181                         if (index < 0)
182                                 throw new ArgumentOutOfRangeException ("index");
183                         if (index > array.Length)
184                                 throw new ArgumentException ("index larger than largest valid index of array");
185                         if (array.Length - index < count)
186                                 throw new ArgumentException ("destination array cannot hold the requested elements");
187
188                         foreach (Node node in tree) {
189                                 if (count-- == 0)
190                                         break;
191
192                                 array [index++] = node.item;
193                         }
194                 }
195
196                 public bool Remove (T item)
197                 {
198                         return tree.Remove (item) != null;
199                 }
200
201                 public int RemoveWhere (Predicate<T> match)
202                 {
203                         var array = ToArray ();
204
205                         int count = 0;
206                         foreach (var item in array) {
207                                 if (!match (item))
208                                         continue;
209
210                                 Remove (item);
211                                 count++;
212                         }
213
214                         return count;
215                 }
216
217                 public IEnumerable<T> Reverse ()
218                 {
219                         var reversed = ToArray ();
220                         Array.Reverse (reversed);
221                         return reversed;
222                 }
223
224                 T [] ToArray ()
225                 {
226                         var array = new T [this.Count];
227                         CopyTo (array);
228                         return array;
229                 }
230
231                 public Enumerator GetEnumerator ()
232                 {
233                         return new Enumerator (this);
234                 }
235
236                 IEnumerator<T> IEnumerable<T>.GetEnumerator ()
237                 {
238                         return new Enumerator (this);
239                 }
240
241                 IEnumerator IEnumerable.GetEnumerator ()
242                 {
243                         return new Enumerator (this);
244                 }
245
246                 public static IEqualityComparer<SortedSet<T>> CreateSetComparer ()
247                 {
248                         return CreateSetComparer (EqualityComparer<T>.Default);
249                 }
250
251                 [MonoTODO]
252                 public static IEqualityComparer<SortedSet<T>> CreateSetComparer (IEqualityComparer<T> memberEqualityComparer)
253                 {
254                         throw new NotImplementedException ();
255                 }
256
257                 [MonoTODO]
258                 protected virtual void GetObjectData (SerializationInfo info, StreamingContext context)
259                 {
260                         throw new NotImplementedException ();
261                 }
262
263                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
264                 {
265                         GetObjectData (info, context);
266                 }
267
268                 [MonoTODO]
269                 protected virtual void OnDeserialization (object sender)
270                 {
271                         if (si == null)
272                                 return;
273
274                         throw new NotImplementedException ();
275                 }
276
277                 void IDeserializationCallback.OnDeserialization (object sender)
278                 {
279                         OnDeserialization (sender);
280                 }
281
282                 [MonoTODO]
283                 public void ExceptWith (IEnumerable<T> other)
284                 {
285                         throw new NotImplementedException ();
286                 }
287
288                 [MonoTODO]
289                 public virtual SortedSet<T> GetViewBetween (T lowerValue, T upperValue)
290                 {
291                         throw new NotImplementedException ();
292                 }
293
294                 [MonoTODO]
295                 public virtual void IntersectWith (IEnumerable<T> other)
296                 {
297                         throw new NotImplementedException ();
298                 }
299
300                 [MonoTODO]
301                 public bool IsProperSubsetOf (IEnumerable<T> other)
302                 {
303                         throw new NotImplementedException ();
304                 }
305
306                 [MonoTODO]
307                 public bool IsProperSupersetOf (IEnumerable<T> other)
308                 {
309                         throw new NotImplementedException ();
310                 }
311
312                 [MonoTODO]
313                 public bool IsSubsetOf (IEnumerable<T> other)
314                 {
315                         throw new NotImplementedException ();
316                 }
317
318                 [MonoTODO]
319                 public bool IsSupersetOf (IEnumerable<T> other)
320                 {
321                         throw new NotImplementedException ();
322                 }
323
324                 [MonoTODO]
325                 public bool Overlaps (IEnumerable<T> other)
326                 {
327                         throw new NotImplementedException ();
328                 }
329
330                 [MonoTODO]
331                 public bool SetEquals (IEnumerable<T> other)
332                 {
333                         throw new NotImplementedException ();
334                 }
335
336                 [MonoTODO]
337                 public void SymmetricExceptWith (IEnumerable<T> other)
338                 {
339                         throw new NotImplementedException ();
340                 }
341
342                 [MonoTODO]
343                 public void UnionWith (IEnumerable<T> other)
344                 {
345                         throw new NotImplementedException ();
346                 }
347
348                 void ICollection<T>.Add (T item)
349                 {
350                         Add (item);
351                 }
352
353                 void ICollection<T>.CopyTo (T [] array, int index)
354                 {
355                         CopyTo (array, index, Count);
356                 }
357
358                 bool ICollection<T>.IsReadOnly {
359                         get { return false; }
360                 }
361
362                 void ICollection.CopyTo (Array array, int index)
363                 {
364                         if (Count == 0)
365                                 return;
366                         if (array == null)
367                                 throw new ArgumentNullException ("array");
368                         if (index < 0 || array.Length <= index)
369                                 throw new ArgumentOutOfRangeException ("index");
370                         if (array.Length - index < Count)
371                                 throw new ArgumentException ();
372
373                         foreach (Node node in tree)
374                                 array.SetValue (node.item, index++);
375                 }
376
377                 bool ICollection.IsSynchronized {
378                         get { return false; }
379                 }
380
381                 // TODO:Is this correct? If this is wrong,please fix.
382                 object ICollection.SyncRoot {
383                         get { return this; }
384                 }
385
386                 [Serializable]
387                 public struct Enumerator : IEnumerator<T>, IDisposable {
388
389                         RBTree.NodeEnumerator host;
390
391                         T current;
392
393                         internal Enumerator (SortedSet<T> set)
394                         {
395                                 host = set.tree.GetEnumerator ();
396                                 current = default (T);
397                         }
398
399                         public T Current {
400                                 get { return current; }
401                         }
402
403                         object IEnumerator.Current {
404                                 get {
405                                         host.check_current ();
406                                         return ((Node) host.Current).item;
407                                 }
408                         }
409
410                         public bool MoveNext ()
411                         {
412                                 if (!host.MoveNext ())
413                                         return false;
414
415                                 current = ((Node) host.Current).item;
416                                 return true;
417                         }
418
419                         public void Dispose ()
420                         {
421                                 host.Dispose ();
422                         }
423
424                         void IEnumerator.Reset ()
425                         {
426                                 host.Reset ();
427                         }
428                 }
429         }
430 }
431
432 #endif