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
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
69 public int GetUpperBound (int dimension)
71 return GetLowerBound (dimension) +
72 GetLength (dimension);
75 public object GetValue (int idx)
77 int[] ind = new int [1];
81 return GetValue (ind);
84 public object GetValue (int idx1, int idx2)
86 int[] ind = new int [2];
91 return GetValue (ind);
94 public object GetValue (int idx1, int idx2, int idx3)
96 int[] ind = new int [3];
102 return GetValue (ind);
105 public void SetValue (object value, int idx)
107 int[] ind = new int [1];
111 SetValue (value, ind);
114 public void SetValue (object value, int idx1, int idx2)
116 int[] ind = new int [2];
121 SetValue (value, ind);
124 public void SetValue (object value, int idx1, int idx2, int idx3)
126 int[] ind = new int [3];
132 SetValue (value, ind);
135 public static Array CreateInstance(Type elementType, int length)
137 int[] lengths = new int [1];
140 lengths [0] = length;
142 return CreateInstance (elementType, lengths, bounds);
145 public static Array CreateInstance(Type elementType, int l1, int l2)
147 int[] lengths = new int [2];
153 return CreateInstance (elementType, lengths, bounds);
156 public static Array CreateInstance(Type elementType, int l1, int l2, int l3)
158 int[] lengths = new int [3];
165 return CreateInstance (elementType, lengths, bounds);
168 public static Array CreateInstance(Type elementType, int[] lengths)
172 return CreateInstance (elementType, lengths, bounds);
176 public static int BinarySearch (Array array, object value)
178 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
182 public static int BinarySearch (Array array, object value, IComparer comparer)
184 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
188 public static int BinarySearch (Array array, int index, int length, object value)
190 return BinarySearch (array, index, length, value, null);
193 public static int BinarySearch (Array array, int index,
194 int length, object value,
198 throw new ArgumentNullException ();
201 throw new RankException ();
203 if (index < array.GetLowerBound (0) || length < 0)
204 throw new ArgumentOutOfRangeException ();
206 if (index + length > array.GetUpperBound (0))
207 throw new ArgumentException ();
209 if (comparer == null && !(value is IComparable))
210 throw new ArgumentException ();
212 // FIXME: Throw an ArgumentException if comparer
213 // is null and value is not of the same type as the
214 // elements of array.
216 for (int i = 0; i < length; i++)
220 if (comparer == null && !(array.GetValue(index + i) is IComparable))
221 throw new ArgumentException ();
223 if (comparer == null)
224 result = (value as IComparable).CompareTo(array.GetValue(index + i));
226 result = comparer.Compare(value, array.GetValue(index + i));
234 return ~(index + length);
237 public static void Clear (Array array, int index, int length)
240 throw new ArgumentNullException ();
243 throw new RankException ();
245 if (index < array.GetLowerBound (0) || length < 0 ||
246 index + length > array.GetUpperBound (0))
247 throw new ArgumentOutOfRangeException ();
249 for (int i = 0; i < length; i++)
251 if (array.GetValue(index + i) is bool)
252 array.SetValue(false, index + i);
253 else if (array.GetValue(index + i) is ValueType)
254 array.SetValue(0, index + i);
256 array.SetValue(null, index + i);
260 public virtual object Clone ()
262 // Array is abstract -- Array a = new Array();
263 Array a = (Array)this.Clone();
265 // I don't know how to handle this ?
267 throw new RankException ();
269 for (int i = 0; i < this.GetLength (0); i++)
271 int index = this.GetLowerBound (0) + i;
273 a.SetValue(this.GetValue(index), index);
279 public static void Copy (Array source, Array dest, int length)
281 // I don't know how to handle this ?
282 if (source.Rank > 1 || dest.Rank > 1)
283 throw new RankException ();
285 Copy (source, source.GetLowerBound (0), dest, dest.GetLowerBound (0), length);
288 public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
290 // I don't know how to handle this ?
291 if (source.Rank > 1 || dest.Rank > 1)
292 throw new RankException ();
295 throw new ArgumentOutOfRangeException ();
297 if (source == null || dest == null)
298 throw new ArgumentNullException ();
300 if (source_idx < source.GetLowerBound (0) ||
301 source_idx + length > source.GetUpperBound (0) ||
302 dest_idx < dest.GetLowerBound (0) || dest_idx + length > dest.GetUpperBound (0))
303 throw new ArgumentException ();
305 if (source.Rank != dest.Rank)
306 throw new RankException ();
308 for (int i = 0; i < length; i++)
310 int index = source.GetLowerBound (0) + i;
312 dest.SetValue(source.GetValue(index), index);
317 public static int IndexOf (Array array, object value)
319 return IndexOf (array, value, 0, array.Length);
322 public static int IndexOf (Array array, object value, int index)
324 return IndexOf (array, value, index, array.Length - index);
327 public static int IndexOf (Array array, object value, int index, int length)
330 throw new ArgumentNullException ();
332 if (length < 0 || index < array.GetLowerBound (0) ||
333 index > array.GetUpperBound (0))
334 throw new ArgumentOutOfRangeException ();
336 for (int i = 0; i < length; i++)
338 if (array.GetValue(index + i) == value)
342 return array.GetLowerBound (0) - 1;
345 public static int LastIndexOf (Array array, object value)
347 return LastIndexOf (array, value, 0, array.Length);
350 public static int LastIndexOf (Array array, object value, int index)
352 return LastIndexOf (array, value, index, array.Length - index);
355 public static int LastIndexOf (Array array, object value, int index, int length)
358 throw new ArgumentNullException ();
360 if (length < 0 || index < array.GetLowerBound (0) ||
361 index > array.GetUpperBound (0))
362 throw new ArgumentOutOfRangeException ();
364 for (int i = length - 1; i >= 0; i--)
366 if (array.GetValue(index + i) == value)
370 return array.GetLowerBound (0) - 1;
373 public static void Reverse (Array array)
375 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
378 public static void Reverse (Array array, int index, int length)
381 throw new ArgumentNullException ();
384 throw new RankException ();
386 if (index < array.GetLowerBound (0) || length < 0)
387 throw new ArgumentOutOfRangeException ();
389 if (index + length > array.GetUpperBound (0))
390 throw new ArgumentException ();
392 for (int i = 0; i < length/2; i++)
396 tmp = array.GetValue (index + i);
397 array.SetValue(array.GetValue (index + length - i - 1), index + i);
398 array.SetValue(tmp, index + length - i - 1);
402 public static void Sort (Array array)
404 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
407 public static void Sort (Array keys, Array items)
409 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
412 public static void Sort (Array array, IComparer comparer)
414 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
417 public static void Sort (Array array, int index, int length)
419 Sort (array, null, index, length, null);
422 public static void Sort (Array keys, Array items, IComparer comparer)
424 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
427 public static void Sort (Array keys, Array items, int index, int length)
429 Sort (keys, items, index, length, null);
432 public static void Sort (Array array, int index, int length, IComparer comparer)
434 Sort (array, null, index, length, comparer);
437 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
440 int high0 = index + length - 1;
442 qsort (keys, items, index, index + length - 1, comparer);
445 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
451 if (keys.Rank > 1 || items.Rank > 1)
452 throw new RankException ();
457 pivot = (low + high) / 2;
459 if (compare (keys.GetValue (low), keys.GetValue (pivot), comparer) > 0)
460 swap (keys, items, low, pivot);
462 if (compare (keys.GetValue (pivot), keys.GetValue (high), comparer) > 0)
463 swap (keys, items, pivot, high);
468 while (low < high && compare (keys.GetValue (low), keys.GetValue (pivot), comparer) < 0)
470 while (low < high && compare (keys.GetValue (pivot), keys.GetValue (high), comparer) < 0)
475 swap (keys, items, low, high);
481 qsort (keys, items, low0, low - 1, comparer);
482 qsort (keys, items, high + 1, high0, comparer);
485 private static void swap (Array keys, Array items, int i, int j)
489 tmp = keys.GetValue (i);
490 keys.SetValue (keys.GetValue (j), i);
491 keys.SetValue (tmp, j);
495 tmp = items.GetValue (i);
496 items.SetValue (items.GetValue (j), i);
497 items.SetValue (tmp, j);
501 private static int compare (object value1, object value2, IComparer comparer)
503 if (comparer == null)
504 return ((IComparable) value1).CompareTo(value2);
506 return comparer.Compare(value1, value2);