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