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)
229 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
233 public static int BinarySearch (Array array, object value, IComparer comparer)
235 return BinarySearch (array, array.GetLowerBound (0), array.GetLength (0),
239 public static int BinarySearch (Array array, int index, int length, object value)
241 return BinarySearch (array, index, length, value, null);
244 public static int BinarySearch (Array array, int index,
245 int length, object value,
249 throw new ArgumentNullException ();
252 throw new RankException ();
254 if (index < array.GetLowerBound (0) || length < 0)
255 throw new ArgumentOutOfRangeException ();
257 if (index + length > array.GetUpperBound (0) + 1)
258 throw new ArgumentException ();
260 if (comparer == null && !(value is IComparable))
261 throw new ArgumentException ();
263 // FIXME: Throw an ArgumentException if comparer
264 // is null and value is not of the same type as the
265 // elements of array.
267 // FIXME: This is implementing linear search. While it should do a binary one
268 // FIXME: Should not throw exception when values are null
270 for (int i = 0; i < length; i++)
274 if (comparer == null && !(array.GetValue(index + i) is IComparable))
275 throw new ArgumentException ();
277 if (comparer == null)
278 result = (value as IComparable).CompareTo(array.GetValue(index + i));
280 result = comparer.Compare(value, array.GetValue(index + i));
288 return ~(index + length);
291 public static void Clear (Array array, int index, int length)
294 throw new ArgumentNullException ();
297 throw new RankException ();
299 if (index < array.GetLowerBound (0) || length < 0 ||
300 index + length > array.GetUpperBound (0) + 1)
301 throw new ArgumentOutOfRangeException ();
303 for (int i = 0; i < length; i++)
305 array.SetValue(null, index + i);
309 [MethodImplAttribute(MethodImplOptions.InternalCall)]
310 public virtual extern object Clone ();
312 public static void Copy (Array source, Array dest, int length)
314 // I don't know how to handle this ?
315 if (source.Rank > 1 || dest.Rank > 1)
316 throw new RankException ();
318 Copy (source, source.GetLowerBound (0), dest, dest.GetLowerBound (0), length);
321 public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
323 // I don't know how to handle this ?
324 if (source.Rank > 1 || dest.Rank > 1)
325 throw new RankException ();
328 throw new ArgumentOutOfRangeException ();
330 if (source == null || dest == null)
331 throw new ArgumentNullException ();
333 if (source_idx < source.GetLowerBound (0) ||
334 source_idx + length > source.GetUpperBound (0) + 1||
335 dest_idx < dest.GetLowerBound (0) || dest_idx + length > dest.GetUpperBound (0) + 1)
336 throw new ArgumentException ();
338 if (source.Rank != dest.Rank)
339 throw new RankException ();
341 for (int i = 0; i < length; i++)
343 int index = source.GetLowerBound (0) + i + source_idx;
345 dest.SetValue(source.GetValue(index), dest_idx + i + dest.GetLowerBound (0));
350 public static int IndexOf (Array array, object value)
352 return IndexOf (array, value, 0, array.Length);
355 public static int IndexOf (Array array, object value, int index)
357 return IndexOf (array, value, index, array.Length - index);
360 public static int IndexOf (Array array, object value, int index, int length)
363 throw new ArgumentNullException ();
365 if (length < 0 || index < array.GetLowerBound (0) ||
366 index > array.GetUpperBound (0))
367 throw new ArgumentOutOfRangeException ();
369 for (int i = 0; i < length; i++)
371 if (array.GetValue(index + i).Equals(value))
375 return array.GetLowerBound (0) - 1;
378 public static int LastIndexOf (Array array, object value)
380 return LastIndexOf (array, value, 0, array.Length);
383 public static int LastIndexOf (Array array, object value, int index)
385 return LastIndexOf (array, value, index, array.Length - index);
388 public static int LastIndexOf (Array array, object value, int index, int length)
391 throw new ArgumentNullException ();
393 if (length < 0 || index < array.GetLowerBound (0) ||
394 index > array.GetUpperBound (0))
395 throw new ArgumentOutOfRangeException ();
397 for (int i = length - 1; i >= 0; i--)
399 if (array.GetValue(index + i).Equals(value))
403 return array.GetLowerBound (0) - 1;
406 public static void Reverse (Array array)
408 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
411 public static void Reverse (Array array, int index, int length)
414 throw new ArgumentNullException ();
417 throw new RankException ();
419 if (index < array.GetLowerBound (0) || length < 0)
420 throw new ArgumentOutOfRangeException ();
422 if (index + length > array.GetUpperBound (0) + 1)
423 throw new ArgumentException ();
425 for (int i = 0; i < length/2; i++)
429 tmp = array.GetValue (index + i);
430 array.SetValue(array.GetValue (index + length - i - 1), index + i);
431 array.SetValue(tmp, index + length - i - 1);
435 public static void Sort (Array array)
437 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
440 public static void Sort (Array keys, Array items)
442 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
445 public static void Sort (Array array, IComparer comparer)
447 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
450 public static void Sort (Array array, int index, int length)
452 Sort (array, null, index, length, null);
455 public static void Sort (Array keys, Array items, IComparer comparer)
457 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
460 public static void Sort (Array keys, Array items, int index, int length)
462 Sort (keys, items, index, length, null);
465 public static void Sort (Array array, int index, int length, IComparer comparer)
467 Sort (array, null, index, length, comparer);
470 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
473 int high0 = index + length - 1;
475 qsort (keys, items, index, index + length - 1, comparer);
478 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
484 if (keys.Rank > 1 || (items != null && items.Rank > 1))
485 throw new RankException ();
490 pivot = (low + high) / 2;
492 if (compare (keys.GetValue (low), keys.GetValue (pivot), comparer) > 0)
493 swap (keys, items, low, pivot);
495 if (compare (keys.GetValue (pivot), keys.GetValue (high), comparer) > 0)
496 swap (keys, items, pivot, high);
501 while (low < high && compare (keys.GetValue (low), keys.GetValue (pivot), comparer) < 0)
503 while (low < high && compare (keys.GetValue (pivot), keys.GetValue (high), comparer) < 0)
508 swap (keys, items, low, high);
514 qsort (keys, items, low0, low - 1, comparer);
515 qsort (keys, items, high + 1, high0, comparer);
518 private static void swap (Array keys, Array items, int i, int j)
522 tmp = keys.GetValue (i);
523 keys.SetValue (keys.GetValue (j), i);
524 keys.SetValue (tmp, j);
528 tmp = items.GetValue (i);
529 items.SetValue (items.GetValue (j), i);
530 items.SetValue (tmp, j);
534 private static int compare (object value1, object value2, IComparer comparer)
536 if (comparer == null)
537 return ((IComparable) value1).CompareTo(value2);
539 return comparer.Compare(value1, value2);
542 public virtual void CopyTo (Array array, int index)
544 Copy (this, this.GetLowerBound(0), array, index, this.GetUpperBound (0));