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 [MethodImplAttribute(MethodImplOptions.InternalCall)]
290 public virtual extern object Clone ();
292 public static void Copy (Array source, Array dest, int length)
294 // I don't know how to handle this ?
295 if (source.Rank > 1 || dest.Rank > 1)
296 throw new RankException ();
298 Copy (source, source.GetLowerBound (0), dest, dest.GetLowerBound (0), length);
301 public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
303 // I don't know how to handle this ?
304 if (source.Rank > 1 || dest.Rank > 1)
305 throw new RankException ();
308 throw new ArgumentOutOfRangeException ();
310 if (source == null || dest == null)
311 throw new ArgumentNullException ();
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 ();
318 if (source.Rank != dest.Rank)
319 throw new RankException ();
321 for (int i = 0; i < length; i++)
323 int index = source.GetLowerBound (0) + i + source_idx;
325 dest.SetValue(source.GetValue(index), dest_idx + i + dest.GetLowerBound (0));
330 public static int IndexOf (Array array, object value)
332 return IndexOf (array, value, 0, array.Length);
335 public static int IndexOf (Array array, object value, int index)
337 return IndexOf (array, value, index, array.Length - index);
340 public static int IndexOf (Array array, object value, int index, int length)
343 throw new ArgumentNullException ();
345 if (length < 0 || index < array.GetLowerBound (0) ||
346 index > array.GetUpperBound (0))
347 throw new ArgumentOutOfRangeException ();
349 for (int i = 0; i < length; i++)
351 if (array.GetValue(index + i) == value)
355 return array.GetLowerBound (0) - 1;
358 public static int LastIndexOf (Array array, object value)
360 return LastIndexOf (array, value, 0, array.Length);
363 public static int LastIndexOf (Array array, object value, int index)
365 return LastIndexOf (array, value, index, array.Length - index);
368 public static int LastIndexOf (Array array, object value, int index, int length)
371 throw new ArgumentNullException ();
373 if (length < 0 || index < array.GetLowerBound (0) ||
374 index > array.GetUpperBound (0))
375 throw new ArgumentOutOfRangeException ();
377 for (int i = length - 1; i >= 0; i--)
379 if (array.GetValue(index + i) == value)
383 return array.GetLowerBound (0) - 1;
386 public static void Reverse (Array array)
388 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
391 public static void Reverse (Array array, int index, int length)
394 throw new ArgumentNullException ();
397 throw new RankException ();
399 if (index < array.GetLowerBound (0) || length < 0)
400 throw new ArgumentOutOfRangeException ();
402 if (index + length > array.GetUpperBound (0))
403 throw new ArgumentException ();
405 for (int i = 0; i < length/2; i++)
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);
415 public static void Sort (Array array)
417 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
420 public static void Sort (Array keys, Array items)
422 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
425 public static void Sort (Array array, IComparer comparer)
427 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
430 public static void Sort (Array array, int index, int length)
432 Sort (array, null, index, length, null);
435 public static void Sort (Array keys, Array items, IComparer comparer)
437 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
440 public static void Sort (Array keys, Array items, int index, int length)
442 Sort (keys, items, index, length, null);
445 public static void Sort (Array array, int index, int length, IComparer comparer)
447 Sort (array, null, index, length, comparer);
450 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
453 int high0 = index + length - 1;
455 qsort (keys, items, index, index + length - 1, comparer);
458 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
464 if (keys.Rank > 1 || (items != null && items.Rank > 1))
465 throw new RankException ();
470 pivot = (low + high) / 2;
472 if (compare (keys.GetValue (low), keys.GetValue (pivot), comparer) > 0)
473 swap (keys, items, low, pivot);
475 if (compare (keys.GetValue (pivot), keys.GetValue (high), comparer) > 0)
476 swap (keys, items, pivot, high);
481 while (low < high && compare (keys.GetValue (low), keys.GetValue (pivot), comparer) < 0)
483 while (low < high && compare (keys.GetValue (pivot), keys.GetValue (high), comparer) < 0)
488 swap (keys, items, low, high);
494 qsort (keys, items, low0, low - 1, comparer);
495 qsort (keys, items, high + 1, high0, comparer);
498 private static void swap (Array keys, Array items, int i, int j)
502 tmp = keys.GetValue (i);
503 keys.SetValue (keys.GetValue (j), i);
504 keys.SetValue (tmp, j);
508 tmp = items.GetValue (i);
509 items.SetValue (items.GetValue (j), i);
510 items.SetValue (tmp, j);
514 private static int compare (object value1, object value2, IComparer comparer)
516 if (comparer == null)
517 return ((IComparable) value1).CompareTo(value2);
519 return comparer.Compare(value1, value2);
522 public virtual void CopyTo (Array array, int index)
524 Copy (this, this.GetLowerBound(0), array, index, this.GetUpperBound (0));