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
75 public bool IsSynchronized {
82 public object SyncRoot {
89 public virtual IEnumerator GetEnumerator ()
95 public int GetUpperBound (int dimension)
97 return GetLowerBound (dimension) +
98 GetLength (dimension);
101 public object GetValue (int idx)
103 int[] ind = new int [1];
107 return GetValue (ind);
110 public object GetValue (int idx1, int idx2)
112 int[] ind = new int [2];
117 return GetValue (ind);
120 public object GetValue (int idx1, int idx2, int idx3)
122 int[] ind = new int [3];
128 return GetValue (ind);
131 public void SetValue (object value, int idx)
133 int[] ind = new int [1];
137 SetValue (value, ind);
140 public void SetValue (object value, int idx1, int idx2)
142 int[] ind = new int [2];
147 SetValue (value, ind);
150 public void SetValue (object value, int idx1, int idx2, int idx3)
152 int[] ind = new int [3];
158 SetValue (value, ind);
161 public static Array CreateInstance(Type elementType, int length)
163 int[] lengths = new int [1];
166 lengths [0] = length;
168 return CreateInstance (elementType, lengths, bounds);
171 public static Array CreateInstance(Type elementType, int l1, int l2)
173 int[] lengths = new int [2];
179 return CreateInstance (elementType, lengths, bounds);
182 public static Array CreateInstance(Type elementType, int l1, int l2, int l3)
184 int[] lengths = new int [3];
191 return CreateInstance (elementType, lengths, bounds);
194 public static Array CreateInstance(Type elementType, int[] lengths)
198 return CreateInstance (elementType, lengths, bounds);
202 public static int BinarySearch (Array array, object value)
204 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
208 public static int BinarySearch (Array array, object value, IComparer comparer)
210 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
214 public static int BinarySearch (Array array, int index, int length, object value)
216 return BinarySearch (array, index, length, value, null);
219 public static int BinarySearch (Array array, int index,
220 int length, object value,
224 throw new ArgumentNullException ();
227 throw new RankException ();
229 if (index < array.GetLowerBound (0) || length < 0)
230 throw new ArgumentOutOfRangeException ();
232 if (index + length > array.GetUpperBound (0))
233 throw new ArgumentException ();
235 if (comparer == null && !(value is IComparable))
236 throw new ArgumentException ();
238 // FIXME: Throw an ArgumentException if comparer
239 // is null and value is not of the same type as the
240 // elements of array.
242 for (int i = 0; i < length; i++)
246 if (comparer == null && !(array.GetValue(index + i) is IComparable))
247 throw new ArgumentException ();
249 if (comparer == null)
250 result = (value as IComparable).CompareTo(array.GetValue(index + i));
252 result = comparer.Compare(value, array.GetValue(index + i));
260 return ~(index + length);
263 public static void Clear (Array array, int index, int length)
266 throw new ArgumentNullException ();
269 throw new RankException ();
271 if (index < array.GetLowerBound (0) || length < 0 ||
272 index + length > array.GetUpperBound (0))
273 throw new ArgumentOutOfRangeException ();
275 for (int i = 0; i < length; i++)
277 if (array.GetValue(index + i) is bool)
278 array.SetValue(false, index + i);
279 else if (array.GetValue(index + i) is ValueType)
280 array.SetValue(0, index + i);
282 array.SetValue(null, index + i);
286 public virtual object Clone ()
288 // Array is abstract -- Array a = new Array();
289 Array a = (Array)this.Clone();
291 // I don't know how to handle this ?
293 throw new RankException ();
295 for (int i = 0; i < this.GetLength (0); i++)
297 int index = this.GetLowerBound (0) + i;
299 a.SetValue(this.GetValue(index), index);
305 public static void Copy (Array source, Array dest, int length)
307 // I don't know how to handle this ?
308 if (source.Rank > 1 || dest.Rank > 1)
309 throw new RankException ();
311 Copy (source, source.GetLowerBound (0), dest, dest.GetLowerBound (0), length);
314 public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
316 // I don't know how to handle this ?
317 if (source.Rank > 1 || dest.Rank > 1)
318 throw new RankException ();
321 throw new ArgumentOutOfRangeException ();
323 if (source == null || dest == null)
324 throw new ArgumentNullException ();
326 if (source_idx < source.GetLowerBound (0) ||
327 source_idx + length > source.GetUpperBound (0) ||
328 dest_idx < dest.GetLowerBound (0) || dest_idx + length > dest.GetUpperBound (0))
329 throw new ArgumentException ();
331 if (source.Rank != dest.Rank)
332 throw new RankException ();
334 for (int i = 0; i < length; i++)
336 int index = source.GetLowerBound (0) + i + source_idx;
338 dest.SetValue(source.GetValue(index), dest_idx + i + dest.GetLowerBound (0));
343 public static int IndexOf (Array array, object value)
345 return IndexOf (array, value, 0, array.Length);
348 public static int IndexOf (Array array, object value, int index)
350 return IndexOf (array, value, index, array.Length - index);
353 public static int IndexOf (Array array, object value, int index, int length)
356 throw new ArgumentNullException ();
358 if (length < 0 || index < array.GetLowerBound (0) ||
359 index > array.GetUpperBound (0))
360 throw new ArgumentOutOfRangeException ();
362 for (int i = 0; i < length; i++)
364 if (array.GetValue(index + i) == value)
368 return array.GetLowerBound (0) - 1;
371 public static int LastIndexOf (Array array, object value)
373 return LastIndexOf (array, value, 0, array.Length);
376 public static int LastIndexOf (Array array, object value, int index)
378 return LastIndexOf (array, value, index, array.Length - index);
381 public static int LastIndexOf (Array array, object value, int index, int length)
384 throw new ArgumentNullException ();
386 if (length < 0 || index < array.GetLowerBound (0) ||
387 index > array.GetUpperBound (0))
388 throw new ArgumentOutOfRangeException ();
390 for (int i = length - 1; i >= 0; i--)
392 if (array.GetValue(index + i) == value)
396 return array.GetLowerBound (0) - 1;
399 public static void Reverse (Array array)
401 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
404 public static void Reverse (Array array, int index, int length)
407 throw new ArgumentNullException ();
410 throw new RankException ();
412 if (index < array.GetLowerBound (0) || length < 0)
413 throw new ArgumentOutOfRangeException ();
415 if (index + length > array.GetUpperBound (0))
416 throw new ArgumentException ();
418 for (int i = 0; i < length/2; i++)
422 tmp = array.GetValue (index + i);
423 array.SetValue(array.GetValue (index + length - i - 1), index + i);
424 array.SetValue(tmp, index + length - i - 1);
428 public static void Sort (Array array)
430 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
433 public static void Sort (Array keys, Array items)
435 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
438 public static void Sort (Array array, IComparer comparer)
440 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
443 public static void Sort (Array array, int index, int length)
445 Sort (array, null, index, length, null);
448 public static void Sort (Array keys, Array items, IComparer comparer)
450 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
453 public static void Sort (Array keys, Array items, int index, int length)
455 Sort (keys, items, index, length, null);
458 public static void Sort (Array array, int index, int length, IComparer comparer)
460 Sort (array, null, index, length, comparer);
463 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
466 int high0 = index + length - 1;
468 qsort (keys, items, index, index + length - 1, comparer);
471 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
477 if (keys.Rank > 1 || (items != null && items.Rank > 1))
478 throw new RankException ();
483 pivot = (low + high) / 2;
485 if (compare (keys.GetValue (low), keys.GetValue (pivot), comparer) > 0)
486 swap (keys, items, low, pivot);
488 if (compare (keys.GetValue (pivot), keys.GetValue (high), comparer) > 0)
489 swap (keys, items, pivot, high);
494 while (low < high && compare (keys.GetValue (low), keys.GetValue (pivot), comparer) < 0)
496 while (low < high && compare (keys.GetValue (pivot), keys.GetValue (high), comparer) < 0)
501 swap (keys, items, low, high);
507 qsort (keys, items, low0, low - 1, comparer);
508 qsort (keys, items, high + 1, high0, comparer);
511 private static void swap (Array keys, Array items, int i, int j)
515 tmp = keys.GetValue (i);
516 keys.SetValue (keys.GetValue (j), i);
517 keys.SetValue (tmp, j);
521 tmp = items.GetValue (i);
522 items.SetValue (items.GetValue (j), i);
523 items.SetValue (tmp, j);
527 private static int compare (object value1, object value2, IComparer comparer)
529 if (comparer == null)
530 return ((IComparable) value1).CompareTo(value2);
532 return comparer.Compare(value1, value2);
535 public virtual void CopyTo (Array array, int index)
537 Copy (this, this.GetLowerBound(0), array, index, this.GetUpperBound (0));