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 [MonoTODO("This should implement IList and IEnumerable too")]
17 public abstract class Array : ICloneable, ICollection
30 int length = this.GetLength (0);
32 for (int i = 1; i < this.Rank; i++) {
33 length *= this.GetLength (i);
44 return this.GetRank ();
48 // InternalCall Methods
50 [MethodImplAttribute(MethodImplOptions.InternalCall)]
51 public extern int GetRank ();
53 [MethodImplAttribute(MethodImplOptions.InternalCall)]
54 public extern int GetLength (int dimension);
56 [MethodImplAttribute(MethodImplOptions.InternalCall)]
57 public extern int GetLowerBound (int dimension);
59 [MethodImplAttribute(MethodImplOptions.InternalCall)]
60 public extern object GetValue (int[] idxs);
62 [MethodImplAttribute(MethodImplOptions.InternalCall)]
63 public extern void SetValue (object value, int[] idxs);
65 [MethodImplAttribute(MethodImplOptions.InternalCall)]
66 internal extern static Array CreateInstanceImpl(Type elementType, int[] lengths, int [] bounds);
69 public virtual int Count {
76 public virtual bool IsSynchronized {
84 public virtual object SyncRoot {
91 public virtual bool IsFixedSize
98 public virtual bool IsReadOnly
106 public virtual IEnumerator GetEnumerator ()
112 public int GetUpperBound (int dimension)
114 return GetLowerBound (dimension) +
115 GetLength (dimension) - 1;
118 public object GetValue (int idx)
120 int[] ind = new int [1];
124 return GetValue (ind);
127 public object GetValue (int idx1, int idx2)
129 int[] ind = new int [2];
134 return GetValue (ind);
137 public object GetValue (int idx1, int idx2, int idx3)
139 int[] ind = new int [3];
145 return GetValue (ind);
148 public void SetValue (object value, int idx)
150 int[] ind = new int [1];
154 SetValue (value, ind);
157 public void SetValue (object value, int idx1, int idx2)
159 int[] ind = new int [2];
164 SetValue (value, ind);
167 public void SetValue (object value, int idx1, int idx2, int idx3)
169 int[] ind = new int [3];
175 SetValue (value, ind);
178 public static Array CreateInstance(Type elementType, int length)
180 int[] lengths = new int [1];
183 lengths [0] = length;
185 return CreateInstanceImpl (elementType, lengths, bounds);
188 public static Array CreateInstance(Type elementType, int l1, int l2)
190 int[] lengths = new int [2];
196 return CreateInstanceImpl (elementType, lengths, bounds);
199 public static Array CreateInstance(Type elementType, int l1, int l2, int l3)
201 int[] lengths = new int [3];
208 return CreateInstanceImpl (elementType, lengths, bounds);
211 public static Array CreateInstance(Type elementType, int[] lengths)
215 return CreateInstanceImpl (elementType, lengths, bounds);
218 public static Array CreateInstance(Type elementType, int[] lengths, int [] bounds)
221 throw new ArgumentNullException("bounds");
223 return CreateInstanceImpl (elementType, lengths, bounds);
227 public static int BinarySearch (Array array, object value)
230 throw new ArgumentNullException ();
232 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
236 public static int BinarySearch (Array array, object value, IComparer comparer)
239 throw new ArgumentNullException ();
241 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
245 public static int BinarySearch (Array array, int index, int length, object value)
248 throw new ArgumentNullException ();
250 return BinarySearch (array, index, length, value, null);
253 public static int BinarySearch (Array array, int index,
254 int length, object value,
258 throw new ArgumentNullException ();
261 throw new RankException ();
263 if (index < array.GetLowerBound (0) || length < 0)
264 throw new ArgumentOutOfRangeException ();
266 if (index + length > array.GetUpperBound (0) + 1)
267 throw new ArgumentException ();
269 if (comparer == null && !(value is IComparable))
270 throw new ArgumentException ();
272 // FIXME: Throw an ArgumentException if comparer
273 // is null and value is not of the same type as the
274 // elements of array.
276 // FIXME: This is implementing linear search. While it should do a binary one
277 // FIXME: Should not throw exception when values are null
279 for (int i = 0; i < length; i++)
283 if (comparer == null && !(array.GetValue(index + i) is IComparable))
284 throw new ArgumentException ();
286 if (comparer == null)
287 result = (value as IComparable).CompareTo(array.GetValue(index + i));
289 result = comparer.Compare(value, array.GetValue(index + i));
297 return ~(index + length);
300 public static void Clear (Array array, int index, int length)
303 throw new ArgumentNullException ();
306 throw new RankException ();
308 if (index < array.GetLowerBound (0) || length < 0 ||
309 index + length > array.GetUpperBound (0) + 1)
310 throw new ArgumentOutOfRangeException ();
312 for (int i = 0; i < length; i++)
314 array.SetValue(null, index + i);
318 [MethodImplAttribute(MethodImplOptions.InternalCall)]
319 public virtual extern object Clone ();
321 public static void Copy (Array source, Array dest, int length)
323 if (source == null || dest == null)
324 throw new ArgumentNullException ();
326 // I don't know how to handle this ?
327 if (source.Rank > 1 || dest.Rank > 1)
328 throw new RankException ();
330 Copy (source, source.GetLowerBound (0), dest, dest.GetLowerBound (0), length);
333 public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
335 if (source == null || dest == null)
336 throw new ArgumentNullException ();
339 throw new ArgumentOutOfRangeException ();
341 if (source == null || dest == null)
342 throw new ArgumentNullException ();
344 if (source_idx < source.GetLowerBound (0) ||
345 source_idx + length > source.GetUpperBound (0) + 1||
346 dest_idx < dest.GetLowerBound (0) || dest_idx + length > dest.GetUpperBound (0) + 1)
347 throw new ArgumentException ();
349 if (source.Rank != dest.Rank)
350 throw new RankException ();
352 // I don't know how to handle this ?
353 if (source.Rank > 1 || dest.Rank > 1)
354 throw new RankException ();
356 for (int i = 0; i < length; i++)
358 int srcindex = source.GetLowerBound (0) + i + source_idx;
359 int dstindex = dest.GetLowerBound (0) + i + dest_idx;
361 Object newval = source.GetValue(srcindex);
363 dest.SetValue(newval, dstindex);
368 public static int IndexOf (Array array, object value)
371 throw new ArgumentNullException ();
373 return IndexOf (array, value, 0, array.Length);
376 public static int IndexOf (Array array, object value, int index)
379 throw new ArgumentNullException ();
381 return IndexOf (array, value, index, array.Length - index);
384 public static int IndexOf (Array array, object value, int index, int length)
387 throw new ArgumentNullException ();
390 throw new RankException ();
392 if (length < 0 || index < array.GetLowerBound (0) ||
393 index+length-1 > array.GetUpperBound (0))
394 throw new ArgumentOutOfRangeException ();
396 for (int i = 0; i < length; i++)
398 if (array.GetValue(index + i).Equals(value))
402 return array.GetLowerBound (0) - 1;
405 public static int LastIndexOf (Array array, object value)
408 throw new ArgumentNullException ();
410 return LastIndexOf (array, value, array.Length-1);
413 public static int LastIndexOf (Array array, object value, int index)
416 throw new ArgumentNullException ();
418 return LastIndexOf (array, value, index, index-array.GetLowerBound(0)+1);
421 public static int LastIndexOf (Array array, object value, int index, int length)
424 throw new ArgumentNullException ();
427 throw new RankException ();
429 if (length < 0 || index-length+1 < array.GetLowerBound (0) ||
430 index > array.GetUpperBound (0))
431 throw new ArgumentOutOfRangeException ();
433 for (int i = index; i >= index-length+1; i--)
435 if (array.GetValue(i).Equals(value))
439 return array.GetLowerBound (0) - 1;
442 public static void Reverse (Array array)
445 throw new ArgumentNullException ();
447 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
450 public static void Reverse (Array array, int index, int length)
453 throw new ArgumentNullException ();
456 throw new RankException ();
458 if (index < array.GetLowerBound (0) || length < 0)
459 throw new ArgumentOutOfRangeException ();
461 if (index + length > array.GetUpperBound (0) + 1)
462 throw new ArgumentException ();
464 for (int i = 0; i < length/2; i++)
468 tmp = array.GetValue (index + i);
469 array.SetValue(array.GetValue (index + length - i - 1), index + i);
470 array.SetValue(tmp, index + length - i - 1);
474 public static void Sort (Array array)
477 throw new ArgumentNullException ();
479 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
482 public static void Sort (Array keys, Array items)
485 throw new ArgumentNullException ();
487 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
490 public static void Sort (Array array, IComparer comparer)
493 throw new ArgumentNullException ();
495 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
498 public static void Sort (Array array, int index, int length)
500 Sort (array, null, index, length, null);
503 public static void Sort (Array keys, Array items, IComparer comparer)
506 throw new ArgumentNullException ();
508 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
511 public static void Sort (Array keys, Array items, int index, int length)
513 Sort (keys, items, index, length, null);
516 public static void Sort (Array array, int index, int length, IComparer comparer)
518 Sort (array, null, index, length, comparer);
521 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
524 int high0 = index + length - 1;
526 qsort (keys, items, index, index + length - 1, comparer);
529 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
536 throw new ArgumentNullException ();
538 if (keys.Rank > 1 || (items != null && items.Rank > 1))
539 throw new RankException ();
544 pivot = (low + high) / 2;
546 if (compare (keys.GetValue (low), keys.GetValue (pivot), comparer) > 0)
547 swap (keys, items, low, pivot);
549 if (compare (keys.GetValue (pivot), keys.GetValue (high), comparer) > 0)
550 swap (keys, items, pivot, high);
555 while (low < high && compare (keys.GetValue (low), keys.GetValue (pivot), comparer) < 0)
557 while (low < high && compare (keys.GetValue (pivot), keys.GetValue (high), comparer) < 0)
562 swap (keys, items, low, high);
568 qsort (keys, items, low0, low - 1, comparer);
569 qsort (keys, items, high + 1, high0, comparer);
572 private static void swap (Array keys, Array items, int i, int j)
576 tmp = keys.GetValue (i);
577 keys.SetValue (keys.GetValue (j), i);
578 keys.SetValue (tmp, j);
582 tmp = items.GetValue (i);
583 items.SetValue (items.GetValue (j), i);
584 items.SetValue (tmp, j);
588 private static int compare (object value1, object value2, IComparer comparer)
590 if (comparer == null)
591 return ((IComparable) value1).CompareTo(value2);
593 return comparer.Compare(value1, value2);
596 public virtual void CopyTo (Array array, int index)
599 throw new ArgumentNullException ();
601 // The order of these exception checks may look strange,
602 // but that's how the microsoft runtime does it.
604 throw new RankException ();
605 if (index + this.GetLength(0) > array.GetLength(0))
606 throw new ArgumentException ();
608 throw new RankException ();
610 throw new ArgumentOutOfRangeException ();
612 Copy (this, this.GetLowerBound(0), array, index, this.GetLength (0));