Mon Feb 11 19:48:58 CET 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / corlib / System / Array.cs
1 //
2 // System.Array.cs
3 //
4 // Author:
5 //   Joe Shaw (joe@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System.Collections;
11 using System.Runtime.CompilerServices;
12
13 namespace System
14 {
15
16         public abstract class Array : ICloneable, ICollection
17         {
18                 // Constructor          
19                 protected Array ()
20                 {
21                         /* empty */
22                 }
23                 
24                 // Properties
25                 public int Length 
26                 {
27                         get 
28                         {
29                                 int length = this.GetLength (0);
30
31                                 for (int i = 1; i < this.Rank; i++) {
32                                         length *= this.GetLength (i); 
33                                 }
34                                 
35                                 return length;
36                         }
37                 }
38
39                 public int Rank 
40                 {
41                         get
42                         {
43                                 return this.GetRank ();
44                         }
45                 }
46
47                 // InternalCall Methods
48                 
49                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
50                 public extern int GetRank ();
51
52                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
53                 public extern int GetLength (int dimension);
54
55                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
56                 public extern int GetLowerBound (int dimension);
57
58                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
59                 public extern object GetValue (int[] idxs);
60
61                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
62                 public extern void SetValue (object value, int[] idxs);
63                 
64                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
65                 public extern static Array CreateInstance(Type elementType, int[] lengths, int [] bounds);
66
67                 // Methods Implementations
68
69                 public int Count {
70                         get {
71                                 return Length;
72                         }
73                 }
74
75                 [MonoTODO]
76                 public bool IsSynchronized {
77                         get {
78                                 // FIXME?
79                                 return false;
80                         }
81                 }
82
83                 [MonoTODO]
84                 public object SyncRoot {
85                         get {
86                                 // FIXME
87                                 return null;
88                         }
89                 }
90
91                 [MonoTODO]
92                 public virtual IEnumerator GetEnumerator ()
93                 {
94                         // FIXME
95                         return null;
96                 }
97
98                 public int GetUpperBound (int dimension)
99                 {
100                         return GetLowerBound (dimension) +
101                                 GetLength (dimension);
102                 }
103
104                 public object GetValue (int idx)
105                 {
106                         int[] ind = new int [1];
107
108                         ind [0] = idx;
109
110                         return GetValue (ind);
111                 }
112
113                 public object GetValue (int idx1, int idx2)
114                 {
115                         int[] ind = new int [2];
116
117                         ind [0] = idx1;
118                         ind [1] = idx2;
119
120                         return GetValue (ind);
121                 }
122
123                 public object GetValue (int idx1, int idx2, int idx3)
124                 {
125                         int[] ind = new int [3];
126
127                         ind [0] = idx1;
128                         ind [1] = idx2;
129                         ind [2] = idx3;
130
131                         return GetValue (ind);
132                 }
133
134                 public void SetValue (object value, int idx)
135                 {
136                         int[] ind = new int [1];
137
138                         ind [0] = idx;
139
140                         SetValue (value, ind);
141                 }
142                 
143                 public void SetValue (object value, int idx1, int idx2)
144                 {
145                         int[] ind = new int [2];
146
147                         ind [0] = idx1;
148                         ind [1] = idx2;
149
150                         SetValue (value, ind);
151                 }
152
153                 public void SetValue (object value, int idx1, int idx2, int idx3)
154                 {
155                         int[] ind = new int [3];
156
157                         ind [0] = idx1;
158                         ind [1] = idx2;
159                         ind [2] = idx3;
160
161                         SetValue (value, ind);
162                 }
163
164                 public static Array CreateInstance(Type elementType, int length)
165                 {
166                         int[] lengths = new int [1];
167                         int[] bounds = null;
168                         
169                         lengths [0] = length;
170                         
171                         return CreateInstance (elementType, lengths, bounds);
172                 }
173                 
174                 public static Array CreateInstance(Type elementType, int l1, int l2)
175                 {
176                         int[] lengths = new int [2];
177                         int[] bounds = null;
178                         
179                         lengths [0] = l1;
180                         lengths [1] = l2;
181                         
182                         return CreateInstance (elementType, lengths, bounds);
183                 }
184
185                 public static Array CreateInstance(Type elementType, int l1, int l2, int l3)
186                 {
187                         int[] lengths = new int [3];
188                         int[] bounds = null;
189                         
190                         lengths [0] = l1;
191                         lengths [1] = l2;
192                         lengths [2] = l3;
193                 
194                         return CreateInstance (elementType, lengths, bounds);
195                 }
196
197                 public static Array CreateInstance(Type elementType, int[] lengths)
198                 {
199                         int[] bounds = null;
200                         
201                         return CreateInstance (elementType, lengths, bounds);
202                 }
203
204                 
205                 public static int BinarySearch (Array array, object value)
206                 {
207                         return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
208                                              value, null);
209                 }
210
211                 public static int BinarySearch (Array array, object value, IComparer comparer)
212                 {
213                         return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
214                                              value, comparer);
215                 }
216
217                 public static int BinarySearch (Array array, int index, int length, object value)
218                 {
219                         return BinarySearch (array, index, length, value, null);
220                 }
221
222                 public static int BinarySearch (Array array, int index,
223                                                 int length, object value,
224                                                 IComparer comparer)
225                 {
226                         if (array == null)
227                                 throw new ArgumentNullException ();
228
229                         if (array.Rank > 1)
230                                 throw new RankException ();
231
232                         if (index < array.GetLowerBound (0) || length < 0)
233                                 throw new ArgumentOutOfRangeException ();
234
235                         if (index + length > array.GetUpperBound (0))
236                                 throw new ArgumentException ();
237
238                         if (comparer == null && !(value is IComparable))
239                                 throw new ArgumentException ();
240
241                         // FIXME: Throw an ArgumentException if comparer
242                         // is null and value is not of the same type as the
243                         // elements of array.
244
245                         for (int i = 0; i < length; i++) 
246                         {
247                                 int result;
248
249                                 if (comparer == null && !(array.GetValue(index + i) is IComparable))
250                                         throw new ArgumentException ();
251
252                                 if (comparer == null)
253                                         result = (value as IComparable).CompareTo(array.GetValue(index + i));
254                                 else
255                                         result = comparer.Compare(value, array.GetValue(index + i));
256
257                                 if (result == 0)
258                                         return index + i;
259                                 else if (result < 0)
260                                         return ~(index + i);
261                         }
262
263                         return ~(index + length);
264                 }
265
266                 public static void Clear (Array array, int index, int length)
267                 {
268                         if (array == null)
269                                 throw new ArgumentNullException ();
270
271                         if (array.Rank > 1)
272                                 throw new RankException ();
273
274                         if (index < array.GetLowerBound (0) || length < 0 ||
275                                 index + length > array.GetUpperBound (0))
276                                 throw new ArgumentOutOfRangeException ();
277
278                         for (int i = 0; i < length; i++) 
279                         {
280                                 if (array.GetValue(index + i) is bool)
281                                         array.SetValue(false, index + i);
282                                 else if (array.GetValue(index + i) is ValueType)
283                                         array.SetValue(0, index + i);
284                                 else
285                                         array.SetValue(null, index + i);
286                         }
287                 }
288
289                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
290                 public virtual extern object Clone ();
291
292                 public static void Copy (Array source, Array dest, int length)
293                 {
294                         // I don't know how to handle this ?
295                         if (source.Rank > 1 || dest.Rank > 1)
296                                 throw new RankException ();
297
298                         Copy (source, source.GetLowerBound (0), dest, dest.GetLowerBound (0), length);                  
299                 }
300
301                 public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
302                 {
303                         // I don't know how to handle this ?
304                         if (source.Rank > 1 || dest.Rank > 1)
305                                 throw new RankException ();
306
307                         if (length < 0)
308                                 throw new ArgumentOutOfRangeException ();
309
310                         if (source == null || dest == null)
311                                 throw new ArgumentNullException ();
312
313                         if (source_idx < source.GetLowerBound (0) ||
314                             source_idx + length > source.GetUpperBound (0) ||
315                             dest_idx < dest.GetLowerBound (0) || dest_idx + length > dest.GetUpperBound (0))
316                                 throw new ArgumentException ();
317
318                         if (source.Rank != dest.Rank)
319                                 throw new RankException ();
320
321                         for (int i = 0; i < length; i++) 
322                         {
323                                 int index = source.GetLowerBound (0) + i + source_idx;
324
325                                 dest.SetValue(source.GetValue(index), dest_idx + i + dest.GetLowerBound (0));
326                         }
327                         
328                 }
329                 
330                 public static int IndexOf (Array array, object value)
331                 {
332                         return IndexOf (array, value, 0, array.Length);
333                 }
334
335                 public static int IndexOf (Array array, object value, int index)
336                 {
337                         return IndexOf (array, value, index, array.Length - index);
338                 }
339                 
340                 public static int IndexOf (Array array, object value, int index, int length)
341                 {
342                         if (array == null)
343                                 throw new ArgumentNullException ();
344         
345                         if (length < 0 || index < array.GetLowerBound (0) ||
346                             index > array.GetUpperBound (0))
347                                 throw new ArgumentOutOfRangeException ();
348
349                         for (int i = 0; i < length; i++)
350                         {
351                                 if (array.GetValue(index + i) == value)
352                                         return index + i;
353                         }
354
355                         return array.GetLowerBound (0) - 1;
356                 }
357
358                 public static int LastIndexOf (Array array, object value)
359                 {
360                         return LastIndexOf (array, value, 0, array.Length);
361                 }
362
363                 public static int LastIndexOf (Array array, object value, int index)
364                 {
365                         return LastIndexOf (array, value, index, array.Length - index);
366                 }
367                 
368                 public static int LastIndexOf (Array array, object value, int index, int length)
369                 {
370                         if (array == null)
371                                 throw new ArgumentNullException ();
372         
373                         if (length < 0 || index < array.GetLowerBound (0) ||
374                             index > array.GetUpperBound (0))
375                                 throw new ArgumentOutOfRangeException ();
376
377                         for (int i = length - 1; i >= 0; i--)
378                         {
379                                 if (array.GetValue(index + i) == value)
380                                         return index + i;
381                         }
382
383                         return array.GetLowerBound (0) - 1;
384                 }
385
386                 public static void Reverse (Array array)
387                 {
388                         Reverse (array, array.GetLowerBound (0), array.GetLength (0));
389                 }
390
391                 public static void Reverse (Array array, int index, int length)
392                 {
393                         if (array == null)
394                                 throw new ArgumentNullException ();
395
396                         if (array.Rank > 1)
397                                 throw new RankException ();
398
399                         if (index < array.GetLowerBound (0) || length < 0)
400                                 throw new ArgumentOutOfRangeException ();
401
402                         if (index + length > array.GetUpperBound (0))
403                                 throw new ArgumentException ();
404
405                         for (int i = 0; i < length/2; i++)
406                         {
407                                 object tmp;
408
409                                 tmp = array.GetValue (index + i);
410                                 array.SetValue(array.GetValue (index + length - i - 1), index + i);
411                                 array.SetValue(tmp, index + length - i - 1);
412                         }
413                 }               
414                 
415                 public static void Sort (Array array)
416                 {
417                         Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
418                 }
419
420                 public static void Sort (Array keys, Array items)
421                 {
422                         Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
423                 }
424
425                 public static void Sort (Array array, IComparer comparer)
426                 {
427                         Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
428                 }
429
430                 public static void Sort (Array array, int index, int length)
431                 {
432                         Sort (array, null, index, length, null);
433                 }
434
435                 public static void Sort (Array keys, Array items, IComparer comparer)
436                 {
437                         Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
438                 }
439
440                 public static void Sort (Array keys, Array items, int index, int length)
441                 {
442                         Sort (keys, items, index, length, null);
443                 }
444
445                 public static void Sort (Array array, int index, int length, IComparer comparer)
446                 {
447                         Sort (array, null, index, length, comparer);
448                 }
449
450                 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
451                 {
452                         int low0 = index;
453                         int high0 = index + length - 1;
454
455                         qsort (keys, items, index, index + length - 1, comparer);
456                 }
457
458                 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
459                 {
460                         int pivot;
461                         int low = low0;
462                         int high = high0;
463                         
464                         if (keys.Rank > 1 || (items != null && items.Rank > 1))
465                                 throw new RankException ();
466
467                         if (low >= high)
468                                 return;
469
470                         pivot = (low + high) / 2;
471
472                         if (compare (keys.GetValue (low), keys.GetValue (pivot), comparer) > 0)
473                                 swap (keys, items, low, pivot);
474                         
475                         if (compare (keys.GetValue (pivot), keys.GetValue (high), comparer) > 0)
476                                 swap (keys, items, pivot, high);
477
478                         while (low < high)
479                         {
480                                 // Move the walls in
481                                 while (low < high && compare (keys.GetValue (low), keys.GetValue (pivot), comparer) < 0)
482                                         low++;
483                                 while (low < high && compare (keys.GetValue (pivot), keys.GetValue (high), comparer) < 0)
484                                         high--;
485
486                                 if (low < high)
487                                 {
488                                         swap (keys, items, low, high);
489                                         low++;
490                                         high--;
491                                 }
492                         }
493
494                         qsort (keys, items, low0, low - 1, comparer);
495                         qsort (keys, items, high + 1, high0, comparer);
496                 }
497
498                 private static void swap (Array keys, Array items, int i, int j)
499                 {
500                         object tmp;
501
502                         tmp = keys.GetValue (i);
503                         keys.SetValue (keys.GetValue (j), i);
504                         keys.SetValue (tmp, j);
505
506                         if (items != null)
507                         {
508                                 tmp = items.GetValue (i);
509                                 items.SetValue (items.GetValue (j), i);
510                                 items.SetValue (tmp, j);
511                         }
512                 }
513
514                 private static int compare (object value1, object value2, IComparer comparer)
515                 {
516                         if (comparer == null)
517                                 return ((IComparable) value1).CompareTo(value2);
518                         else
519                                 return comparer.Compare(value1, value2);
520                 }
521         
522                 public virtual void CopyTo (Array array, int index)
523                 {
524                         Copy (this, this.GetLowerBound(0), array, index, this.GetUpperBound (0));
525                 }
526         }
527 }