5 // Joe Shaw (joe@ximian.com)
7 // (C) 2001 Ximian, Inc. http://www.ximian.com
10 using System.Collections;
11 using System.Runtime.CompilerServices;
16 public abstract class Array : ICloneable, ICollection
29 int length = this.GetLength (0);
31 for (int i = 1; i < this.Rank; i++) {
32 length *= this.GetLength (i);
43 return this.GetRank ();
47 // InternalCall Methods
49 [MethodImplAttribute(MethodImplOptions.InternalCall)]
50 public extern int GetRank ();
52 [MethodImplAttribute(MethodImplOptions.InternalCall)]
53 public extern int GetLength (int dimension);
55 [MethodImplAttribute(MethodImplOptions.InternalCall)]
56 public extern int GetLowerBound (int dimension);
58 [MethodImplAttribute(MethodImplOptions.InternalCall)]
59 public extern object GetValue (int[] idxs);
61 [MethodImplAttribute(MethodImplOptions.InternalCall)]
62 public extern void SetValue (object value, int[] idxs);
64 [MethodImplAttribute(MethodImplOptions.InternalCall)]
65 public extern static Array CreateInstance(Type elementType, int[] lengths, int [] bounds);
67 // Methods Implementations
76 public bool IsSynchronized {
84 public object SyncRoot {
92 public virtual IEnumerator GetEnumerator ()
98 public int GetUpperBound (int dimension)
100 return GetLowerBound (dimension) +
101 GetLength (dimension);
104 public object GetValue (int idx)
106 int[] ind = new int [1];
110 return GetValue (ind);
113 public object GetValue (int idx1, int idx2)
115 int[] ind = new int [2];
120 return GetValue (ind);
123 public object GetValue (int idx1, int idx2, int idx3)
125 int[] ind = new int [3];
131 return GetValue (ind);
134 public void SetValue (object value, int idx)
136 int[] ind = new int [1];
140 SetValue (value, ind);
143 public void SetValue (object value, int idx1, int idx2)
145 int[] ind = new int [2];
150 SetValue (value, ind);
153 public void SetValue (object value, int idx1, int idx2, int idx3)
155 int[] ind = new int [3];
161 SetValue (value, ind);
164 public static Array CreateInstance(Type elementType, int length)
166 int[] lengths = new int [1];
169 lengths [0] = length;
171 return CreateInstance (elementType, lengths, bounds);
174 public static Array CreateInstance(Type elementType, int l1, int l2)
176 int[] lengths = new int [2];
182 return CreateInstance (elementType, lengths, bounds);
185 public static Array CreateInstance(Type elementType, int l1, int l2, int l3)
187 int[] lengths = new int [3];
194 return CreateInstance (elementType, lengths, bounds);
197 public static Array CreateInstance(Type elementType, int[] lengths)
201 return CreateInstance (elementType, lengths, bounds);
205 public static int BinarySearch (Array array, object value)
207 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
211 public static int BinarySearch (Array array, object value, IComparer comparer)
213 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
217 public static int BinarySearch (Array array, int index, int length, object value)
219 return BinarySearch (array, index, length, value, null);
222 public static int BinarySearch (Array array, int index,
223 int length, object value,
227 throw new ArgumentNullException ();
230 throw new RankException ();
232 if (index < array.GetLowerBound (0) || length < 0)
233 throw new ArgumentOutOfRangeException ();
235 if (index + length > array.GetUpperBound (0))
236 throw new ArgumentException ();
238 if (comparer == null && !(value is IComparable))
239 throw new ArgumentException ();
241 // FIXME: Throw an ArgumentException if comparer
242 // is null and value is not of the same type as the
243 // elements of array.
245 for (int i = 0; i < length; i++)
249 if (comparer == null && !(array.GetValue(index + i) is IComparable))
250 throw new ArgumentException ();
252 if (comparer == null)
253 result = (value as IComparable).CompareTo(array.GetValue(index + i));
255 result = comparer.Compare(value, array.GetValue(index + i));
263 return ~(index + length);
266 public static void Clear (Array array, int index, int length)
269 throw new ArgumentNullException ();
272 throw new RankException ();
274 if (index < array.GetLowerBound (0) || length < 0 ||
275 index + length > array.GetUpperBound (0))
276 throw new ArgumentOutOfRangeException ();
278 for (int i = 0; i < length; i++)
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);
285 array.SetValue(null, index + i);
289 public virtual object Clone ()
291 // Array is abstract -- Array a = new Array();
292 Array a = (Array)this.Clone();
294 // I don't know how to handle this ?
296 throw new RankException ();
298 for (int i = 0; i < this.GetLength (0); i++)
300 int index = this.GetLowerBound (0) + i;
302 a.SetValue(this.GetValue(index), index);
308 public static void Copy (Array source, Array dest, int length)
310 // I don't know how to handle this ?
311 if (source.Rank > 1 || dest.Rank > 1)
312 throw new RankException ();
314 Copy (source, source.GetLowerBound (0), dest, dest.GetLowerBound (0), length);
317 public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
319 // I don't know how to handle this ?
320 if (source.Rank > 1 || dest.Rank > 1)
321 throw new RankException ();
324 throw new ArgumentOutOfRangeException ();
326 if (source == null || dest == null)
327 throw new ArgumentNullException ();
329 if (source_idx < source.GetLowerBound (0) ||
330 source_idx + length > source.GetUpperBound (0) ||
331 dest_idx < dest.GetLowerBound (0) || dest_idx + length > dest.GetUpperBound (0))
332 throw new ArgumentException ();
334 if (source.Rank != dest.Rank)
335 throw new RankException ();
337 for (int i = 0; i < length; i++)
339 int index = source.GetLowerBound (0) + i + source_idx;
341 dest.SetValue(source.GetValue(index), dest_idx + i + dest.GetLowerBound (0));
346 public static int IndexOf (Array array, object value)
348 return IndexOf (array, value, 0, array.Length);
351 public static int IndexOf (Array array, object value, int index)
353 return IndexOf (array, value, index, array.Length - index);
356 public static int IndexOf (Array array, object value, int index, int length)
359 throw new ArgumentNullException ();
361 if (length < 0 || index < array.GetLowerBound (0) ||
362 index > array.GetUpperBound (0))
363 throw new ArgumentOutOfRangeException ();
365 for (int i = 0; i < length; i++)
367 if (array.GetValue(index + i) == value)
371 return array.GetLowerBound (0) - 1;
374 public static int LastIndexOf (Array array, object value)
376 return LastIndexOf (array, value, 0, array.Length);
379 public static int LastIndexOf (Array array, object value, int index)
381 return LastIndexOf (array, value, index, array.Length - index);
384 public static int LastIndexOf (Array array, object value, int index, int length)
387 throw new ArgumentNullException ();
389 if (length < 0 || index < array.GetLowerBound (0) ||
390 index > array.GetUpperBound (0))
391 throw new ArgumentOutOfRangeException ();
393 for (int i = length - 1; i >= 0; i--)
395 if (array.GetValue(index + i) == value)
399 return array.GetLowerBound (0) - 1;
402 public static void Reverse (Array array)
404 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
407 public static void Reverse (Array array, int index, int length)
410 throw new ArgumentNullException ();
413 throw new RankException ();
415 if (index < array.GetLowerBound (0) || length < 0)
416 throw new ArgumentOutOfRangeException ();
418 if (index + length > array.GetUpperBound (0))
419 throw new ArgumentException ();
421 for (int i = 0; i < length/2; i++)
425 tmp = array.GetValue (index + i);
426 array.SetValue(array.GetValue (index + length - i - 1), index + i);
427 array.SetValue(tmp, index + length - i - 1);
431 public static void Sort (Array array)
433 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
436 public static void Sort (Array keys, Array items)
438 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
441 public static void Sort (Array array, IComparer comparer)
443 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
446 public static void Sort (Array array, int index, int length)
448 Sort (array, null, index, length, null);
451 public static void Sort (Array keys, Array items, IComparer comparer)
453 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
456 public static void Sort (Array keys, Array items, int index, int length)
458 Sort (keys, items, index, length, null);
461 public static void Sort (Array array, int index, int length, IComparer comparer)
463 Sort (array, null, index, length, comparer);
466 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
469 int high0 = index + length - 1;
471 qsort (keys, items, index, index + length - 1, comparer);
474 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
480 if (keys.Rank > 1 || (items != null && items.Rank > 1))
481 throw new RankException ();
486 pivot = (low + high) / 2;
488 if (compare (keys.GetValue (low), keys.GetValue (pivot), comparer) > 0)
489 swap (keys, items, low, pivot);
491 if (compare (keys.GetValue (pivot), keys.GetValue (high), comparer) > 0)
492 swap (keys, items, pivot, high);
497 while (low < high && compare (keys.GetValue (low), keys.GetValue (pivot), comparer) < 0)
499 while (low < high && compare (keys.GetValue (pivot), keys.GetValue (high), comparer) < 0)
504 swap (keys, items, low, high);
510 qsort (keys, items, low0, low - 1, comparer);
511 qsort (keys, items, high + 1, high0, comparer);
514 private static void swap (Array keys, Array items, int i, int j)
518 tmp = keys.GetValue (i);
519 keys.SetValue (keys.GetValue (j), i);
520 keys.SetValue (tmp, j);
524 tmp = items.GetValue (i);
525 items.SetValue (items.GetValue (j), i);
526 items.SetValue (tmp, j);
530 private static int compare (object value1, object value2, IComparer comparer)
532 if (comparer == null)
533 return ((IComparable) value1).CompareTo(value2);
535 return comparer.Compare(value1, value2);
538 public virtual void CopyTo (Array array, int index)
540 Copy (this, this.GetLowerBound(0), array, index, this.GetUpperBound (0));