(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / corlib / System / Array.cs
blobea37a7a1e1d07d41d66902814687ed427e77419a
1 //
2 // System.Array.cs
3 //
4 // Authors:
5 // Joe Shaw (joe@ximian.com)
6 // Martin Baulig (martin@gnome.org)
7 // Dietmar Maurer (dietmar@ximian.com)
8 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
9 //
10 // (C) 2001-2003 Ximian, Inc. http://www.ximian.com
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 //
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 //
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39 #if NET_2_0
40 using System.Collections.Generic;
41 #endif
42 namespace System
44 [Serializable]
45 [MonoTODO ("We are doing way to many double/triple exception checks for the overloaded functions")]
46 [MonoTODO ("Sort overloads parameter checks are VERY inconsistent")]
47 public abstract class Array : ICloneable, ICollection, IList, IEnumerable
49 // Constructor
50 private Array ()
54 // Properties
55 public int Length {
56 get {
57 int length = this.GetLength (0);
59 for (int i = 1; i < this.Rank; i++) {
60 length *= this.GetLength (i);
62 return length;
66 #if NET_1_1
67 [ComVisible (false)]
68 public long LongLength {
69 get { return Length; }
71 #endif
73 public int Rank {
74 get {
75 return this.GetRank ();
79 // IList interface
80 object IList.this [int index] {
81 get {
82 if (unchecked ((uint) index) >= unchecked ((uint) Length))
83 throw new ArgumentOutOfRangeException ("index");
84 return GetValueImpl (index);
86 set {
87 if (unchecked ((uint) index) >= unchecked ((uint) Length))
88 throw new ArgumentOutOfRangeException ("index");
89 SetValueImpl (value, index);
93 int IList.Add (object value)
95 throw new NotSupportedException ();
98 void IList.Clear ()
100 Array.Clear (this, this.GetLowerBound (0), this.Length);
103 bool IList.Contains (object value)
105 if (this.Rank > 1)
106 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
108 int length = this.Length;
109 for (int i = 0; i < length; i++) {
110 if (Object.Equals (value, this.GetValueImpl (i)))
111 return true;
113 return false;
116 int IList.IndexOf (object value)
118 if (this.Rank > 1)
119 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
121 int length = this.Length;
122 for (int i = 0; i < length; i++) {
123 if (Object.Equals (value, this.GetValueImpl (i)))
124 // array index may not be zero-based.
125 // use lower bound
126 return i + this.GetLowerBound (0);
129 int retVal;
130 unchecked {
131 // lower bound may be MinValue
132 retVal = this.GetLowerBound (0) - 1;
135 return retVal;
138 void IList.Insert (int index, object value)
140 throw new NotSupportedException ();
143 void IList.Remove (object value)
145 throw new NotSupportedException ();
148 void IList.RemoveAt (int index)
150 throw new NotSupportedException ();
153 // InternalCall Methods
154 [MethodImplAttribute (MethodImplOptions.InternalCall)]
155 private extern int GetRank ();
157 [MethodImplAttribute (MethodImplOptions.InternalCall)]
158 public extern int GetLength (int dimension);
160 #if NET_1_1
161 [ComVisible (false)]
162 public long GetLongLength (int dimension)
164 return GetLength (dimension);
166 #endif
168 [MethodImplAttribute (MethodImplOptions.InternalCall)]
169 public extern int GetLowerBound (int dimension);
171 [MethodImplAttribute (MethodImplOptions.InternalCall)]
172 public extern object GetValue (int[] indices);
174 [MethodImplAttribute (MethodImplOptions.InternalCall)]
175 public extern void SetValue (object value, int[] indices);
177 // CAUTION! No bounds checking!
178 [MethodImplAttribute (MethodImplOptions.InternalCall)]
179 internal extern object GetValueImpl (int pos);
181 // CAUTION! No bounds checking!
182 [MethodImplAttribute (MethodImplOptions.InternalCall)]
183 internal extern void SetValueImpl (object value, int pos);
185 [MethodImplAttribute (MethodImplOptions.InternalCall)]
186 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
188 [MethodImplAttribute (MethodImplOptions.InternalCall)]
189 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
191 // Properties
192 int ICollection.Count {
193 get {
194 return Length;
198 public virtual bool IsSynchronized {
199 get {
200 return false;
204 public virtual object SyncRoot {
205 get {
206 return this;
210 public virtual bool IsFixedSize {
211 get {
212 return true;
216 public virtual bool IsReadOnly {
217 get {
218 return false;
222 public virtual IEnumerator GetEnumerator ()
224 return new SimpleEnumerator (this);
227 public int GetUpperBound (int dimension)
229 return GetLowerBound (dimension) + GetLength (dimension) - 1;
232 public object GetValue (int index)
234 if (Rank != 1)
235 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
236 if (index < GetLowerBound (0) || index > GetUpperBound (0))
237 throw new IndexOutOfRangeException (Locale.GetText (
238 "Index has to be between upper and lower bound of the array."));
240 return GetValueImpl (index - GetLowerBound (0));
243 public object GetValue (int index1, int index2)
245 int[] ind = {index1, index2};
246 return GetValue (ind);
249 public object GetValue (int index1, int index2, int index3)
251 int[] ind = {index1, index2, index3};
252 return GetValue (ind);
255 #if NET_1_1
256 [ComVisible (false)]
257 public object GetValue (long index)
259 if (index < 0 || index > Int32.MaxValue)
260 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
261 "Value must be >= 0 and <= Int32.MaxValue."));
263 return GetValue ((int) index);
266 [ComVisible (false)]
267 public object GetValue (long index1, long index2)
269 if (index1 < 0 || index1 > Int32.MaxValue)
270 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
271 "Value must be >= 0 and <= Int32.MaxValue."));
273 if (index2 < 0 || index2 > Int32.MaxValue)
274 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
275 "Value must be >= 0 and <= Int32.MaxValue."));
277 return GetValue ((int) index1, (int) index2);
280 [ComVisible (false)]
281 public object GetValue (long index1, long index2, long index3)
283 if (index1 < 0 || index1 > Int32.MaxValue)
284 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
285 "Value must be >= 0 and <= Int32.MaxValue."));
287 if (index2 < 0 || index2 > Int32.MaxValue)
288 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
289 "Value must be >= 0 and <= Int32.MaxValue."));
291 if (index3 < 0 || index3 > Int32.MaxValue)
292 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
293 "Value must be >= 0 and <= Int32.MaxValue."));
295 return GetValue ((int) index1, (int) index2, (int) index3);
298 [ComVisible (false)]
299 public void SetValue (object value, long index)
301 if (index < 0 || index > Int32.MaxValue)
302 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
303 "Value must be >= 0 and <= Int32.MaxValue."));
305 SetValue (value, (int) index);
308 [ComVisible (false)]
309 public void SetValue (object value, long index1, long index2)
311 if (index1 < 0 || index1 > Int32.MaxValue)
312 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
313 "Value must be >= 0 and <= Int32.MaxValue."));
315 if (index2 < 0 || index2 > Int32.MaxValue)
316 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
317 "Value must be >= 0 and <= Int32.MaxValue."));
319 int[] ind = {(int) index1, (int) index2};
320 SetValue (value, ind);
323 [ComVisible (false)]
324 public void SetValue (object value, long index1, long index2, long index3)
326 if (index1 < 0 || index1 > Int32.MaxValue)
327 throw new ArgumentOutOfRangeException ("index1", Locale.GetText (
328 "Value must be >= 0 and <= Int32.MaxValue."));
330 if (index2 < 0 || index2 > Int32.MaxValue)
331 throw new ArgumentOutOfRangeException ("index2", Locale.GetText (
332 "Value must be >= 0 and <= Int32.MaxValue."));
334 if (index3 < 0 || index3 > Int32.MaxValue)
335 throw new ArgumentOutOfRangeException ("index3", Locale.GetText (
336 "Value must be >= 0 and <= Int32.MaxValue."));
338 int[] ind = {(int) index1, (int) index2, (int) index3};
339 SetValue (value, ind);
341 #endif
343 // // This function is currently unused, but just in case we need it later on ... */
344 // internal int IndexToPos (int[] idxs)
345 // {
346 // if (idxs == null)
347 // throw new ArgumentNullException ("idxs");
349 // if ((idxs.Rank != 1) || (idxs.Length != Rank))
350 // throw new ArgumentException ();
352 // if ((idxs [0] < GetLowerBound (0)) || (idxs [0] > GetUpperBound (0)))
353 // throw new IndexOutOfRangeException();
355 // int pos = idxs [0] - GetLowerBound (0);
356 // for (int i = 1; i < Rank; i++) {
357 // if ((idxs [i] < GetLowerBound (i)) || (idxs [i] > GetUpperBound (i)))
358 // throw new IndexOutOfRangeException();
360 // pos *= GetLength (i);
361 // pos += idxs [i] - GetLowerBound (i);
362 // }
364 // return pos;
365 // }
367 public void SetValue (object value, int index)
369 if (Rank != 1)
370 throw new ArgumentException (Locale.GetText ("Array was not a one-dimensional array."));
371 if (index < GetLowerBound (0) || index > GetUpperBound (0))
372 throw new IndexOutOfRangeException (Locale.GetText (
373 "Index has to be >= lower bound and <= upper bound of the array."));
375 SetValueImpl (value, index - GetLowerBound (0));
378 public void SetValue (object value, int index1, int index2)
380 int[] ind = {index1, index2};
381 SetValue (value, ind);
384 public void SetValue (object value, int index1, int index2, int index3)
386 int[] ind = {index1, index2, index3};
387 SetValue (value, ind);
390 public static Array CreateInstance (Type elementType, int length)
392 int[] lengths = {length};
393 int[] bounds = null;
395 return CreateInstanceImpl (elementType, lengths, bounds);
398 public static Array CreateInstance (Type elementType, int length1, int length2)
400 int[] lengths = {length1, length2};
401 int[] bounds = null;
403 return CreateInstanceImpl (elementType, lengths, bounds);
406 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
408 int[] lengths = {length1, length2, length3};
409 int[] bounds = null;
411 return CreateInstanceImpl (elementType, lengths, bounds);
414 public static Array CreateInstance (Type elementType, int[] lengths)
416 if (elementType == null)
417 throw new ArgumentNullException ("elementType");
418 if (lengths == null)
419 throw new ArgumentNullException ("lengths");
421 if (lengths.Length > 255)
422 throw new TypeLoadException ();
424 int[] bounds = null;
426 return CreateInstanceImpl (elementType, lengths, bounds);
429 public static Array CreateInstance (Type elementType, int[] lengths, int [] bounds)
431 if (elementType == null)
432 throw new ArgumentNullException ("elementType");
433 if (lengths == null)
434 throw new ArgumentNullException ("lengths");
435 if (bounds == null)
436 throw new ArgumentNullException ("bounds");
438 if (lengths.Length < 1)
439 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
441 if (lengths.Length != bounds.Length)
442 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
444 for (int j = 0; j < bounds.Length; j ++) {
445 if (lengths [j] < 0)
446 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
447 "Each value has to be >= 0."));
448 if ((long)bounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
449 throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
450 "Length + bound must not exceed Int32.MaxValue."));
453 if (lengths.Length > 255)
454 throw new TypeLoadException ();
456 return CreateInstanceImpl (elementType, lengths, bounds);
459 #if NET_1_1
460 static int [] GetIntArray (long [] values)
462 int len = values.Length;
463 int [] ints = new int [len];
464 for (int i = 0; i < len; i++) {
465 long current = values [i];
466 if (current < 0 || current > (long) Int32.MaxValue)
467 throw new ArgumentOutOfRangeException ("values", Locale.GetText (
468 "Each value has to be >= 0 and <= Int32.MaxValue."));
470 ints [i] = (int) current;
472 return ints;
475 public static Array CreateInstance (Type elementType, params long [] lengths)
477 if (lengths == null) {
478 // LAMESPEC: Docs say we should throw a ArgumentNull, but .NET
479 // 1.1 actually throws a NullReference.
480 throw new NullReferenceException (Locale.GetText ("'lengths' cannot be null."));
482 return CreateInstance (elementType, GetIntArray (lengths));
485 [ComVisible (false)]
486 public object GetValue (long [] indices)
488 if (indices == null) {
489 // LAMESPEC: Docs say we should throw a ArgumentNull, but .NET
490 // 1.1 actually throws a NullReference.
491 throw new NullReferenceException (Locale.GetText ("'indices' cannot be null."));
493 return GetValue (GetIntArray (indices));
496 [ComVisible (false)]
497 public void SetValue (object value, long [] indices)
499 if (indices == null) {
500 // LAMESPEC: Docs say we should throw a ArgumentNull, but .NET
501 // 1.1 actually throws a NullReference.
502 throw new NullReferenceException (Locale.GetText ("'indices' cannot be null."));
504 SetValue (value, GetIntArray (indices));
506 #endif
508 public static int BinarySearch (Array array, object value)
510 if (array == null)
511 throw new ArgumentNullException ("array");
513 if (value == null)
514 return -1;
516 if (array.Rank > 1)
517 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
519 if (!(value is IComparable))
520 throw new ArgumentException (Locale.GetText ("value does not support IComparable."));
522 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, null);
525 public static int BinarySearch (Array array, object value, IComparer comparer)
527 if (array == null)
528 throw new ArgumentNullException ("array");
530 if (array.Rank > 1)
531 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
533 if ((comparer == null) && (value != null) && !(value is IComparable))
534 throw new ArgumentException (Locale.GetText (
535 "comparer is null and value does not support IComparable."));
537 return DoBinarySearch (array, array.GetLowerBound (0), array.GetLength (0), value, comparer);
540 public static int BinarySearch (Array array, int index, int length, object value)
542 if (array == null)
543 throw new ArgumentNullException ("array");
545 if (array.Rank > 1)
546 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
548 if (index < array.GetLowerBound (0))
549 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
550 "index is less than the lower bound of array."));
551 if (length < 0)
552 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
553 "Value has to be >= 0."));
554 // re-ordered to avoid possible integer overflow
555 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
556 throw new ArgumentException (Locale.GetText (
557 "index and length do not specify a valid range in array."));
558 if ((value != null) && (!(value is IComparable)))
559 throw new ArgumentException (Locale.GetText (
560 "value does not support IComparable"));
562 return DoBinarySearch (array, index, length, value, null);
565 public static int BinarySearch (Array array, int index, int length, object value, IComparer comparer)
567 if (array == null)
568 throw new ArgumentNullException ("array");
570 if (array.Rank > 1)
571 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
573 if (index < array.GetLowerBound (0))
574 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
575 "index is less than the lower bound of array."));
576 if (length < 0)
577 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
578 "Value has to be >= 0."));
579 // re-ordered to avoid possible integer overflow
580 if (index > array.GetLowerBound (0) + array.GetLength (0) - length)
581 throw new ArgumentException (Locale.GetText (
582 "index and length do not specify a valid range in array."));
584 if ((comparer == null) && (value != null) && !(value is IComparable))
585 throw new ArgumentException (Locale.GetText (
586 "comparer is null and value does not support IComparable."));
588 return DoBinarySearch (array, index, length, value, comparer);
591 static int DoBinarySearch (Array array, int index, int length, object value, IComparer comparer)
593 // cache this in case we need it
594 IComparable valueCompare = value as IComparable;
595 if (comparer == null)
596 comparer = Comparer.Default;
598 int iMin = index;
599 // Comment from Tum (tum@veridicus.com):
600 // *Must* start at index + length - 1 to pass rotor test co2460binarysearch_iioi
601 int iMax = index + length - 1;
602 int iCmp = 0;
603 try {
604 while (iMin <= iMax) {
605 int iMid = (iMin + iMax) / 2;
606 object elt = array.GetValueImpl (iMid);
608 iCmp = comparer.Compare (value, elt);
610 if (iCmp == 0)
611 return iMid;
612 else if (iCmp < 0)
613 iMax = iMid - 1;
614 else
615 iMin = iMid + 1; // compensate for the rounding down
618 catch (Exception e) {
619 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
622 return ~iMin;
625 public static void Clear (Array array, int index, int length)
627 if (array == null)
628 throw new ArgumentNullException ("array");
629 if (length < 0)
630 throw new ArgumentOutOfRangeException ("length < 0");
632 int low = array.GetLowerBound (0);
633 if (index < low)
634 throw new IndexOutOfRangeException ("index < lower bound");
635 index = index - low;
637 // re-ordered to avoid possible integer overflow
638 if (index > array.Length - length)
639 throw new IndexOutOfRangeException ("index + length > size");
641 ClearInternal (array, index, length);
644 [MethodImplAttribute (MethodImplOptions.InternalCall)]
645 static extern void ClearInternal (Array a, int index, int count);
647 [MethodImplAttribute (MethodImplOptions.InternalCall)]
648 public virtual extern object Clone ();
650 public static void Copy (Array sourceArray, Array destinationArray, int length)
652 // need these checks here because we are going to use
653 // GetLowerBound() on source and dest.
654 if (sourceArray == null)
655 throw new ArgumentNullException ("sourceArray");
657 if (destinationArray == null)
658 throw new ArgumentNullException ("destinationArray");
660 Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
661 destinationArray.GetLowerBound (0), length);
664 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
666 if (sourceArray == null)
667 throw new ArgumentNullException ("sourceArray");
669 if (destinationArray == null)
670 throw new ArgumentNullException ("destinationArray");
672 if (length < 0)
673 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
674 "Value has to be >= 0."));;
676 if (sourceIndex < 0)
677 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
678 "Value has to be >= 0."));;
680 if (destinationIndex < 0)
681 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
682 "Value has to be >= 0."));;
684 if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
685 return;
687 int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
688 int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
690 // re-ordered to avoid possible integer overflow
691 if (source_pos > sourceArray.Length - length || dest_pos > destinationArray.Length - length)
692 throw new ArgumentException ("length");
694 if (sourceArray.Rank != destinationArray.Rank)
695 throw new RankException (Locale.GetText ("Arrays must be of same size."));
697 Type src_type = sourceArray.GetType ().GetElementType ();
698 Type dst_type = destinationArray.GetType ().GetElementType ();
700 if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
701 for (int i = 0; i < length; i++) {
702 Object srcval = sourceArray.GetValueImpl (source_pos + i);
704 try {
705 destinationArray.SetValueImpl (srcval, dest_pos + i);
706 } catch {
707 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
708 (src_type.Equals (typeof (Object))))
709 throw new InvalidCastException ();
710 else
711 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
712 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
716 else {
717 for (int i = length - 1; i >= 0; i--) {
718 Object srcval = sourceArray.GetValueImpl (source_pos + i);
720 try {
721 destinationArray.SetValueImpl (srcval, dest_pos + i);
722 } catch {
723 if ((dst_type.IsValueType || dst_type.Equals (typeof (String))) &&
724 (src_type.Equals (typeof (Object))))
725 throw new InvalidCastException ();
726 else
727 throw new ArrayTypeMismatchException (String.Format (Locale.GetText (
728 "(Types: source={0}; target={1})"), src_type.FullName, dst_type.FullName));
734 #if NET_1_1
735 public static void Copy (Array sourceArray, long sourceIndex, Array destinationArray,
736 long destinationIndex, long length)
738 if (sourceArray == null)
739 throw new ArgumentNullException ("sourceArray");
741 if (destinationArray == null)
742 throw new ArgumentNullException ("destinationArray");
744 if (sourceIndex < Int32.MinValue || sourceIndex > Int32.MaxValue)
745 throw new ArgumentOutOfRangeException ("sourceIndex",
746 Locale.GetText ("Must be in the Int32 range."));
748 if (destinationIndex < Int32.MinValue || destinationIndex > Int32.MaxValue)
749 throw new ArgumentOutOfRangeException ("destinationIndex",
750 Locale.GetText ("Must be in the Int32 range."));
752 if (length < 0 || length > Int32.MaxValue)
753 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
754 "Value must be >= 0 and <= Int32.MaxValue."));
756 Copy (sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
759 public static void Copy (Array sourceArray, Array destinationArray, long length)
761 if (length < 0 || length > Int32.MaxValue)
762 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
763 "Value must be >= 0 and <= Int32.MaxValue."));
765 Copy (sourceArray, destinationArray, (int) length);
767 #endif
769 public static int IndexOf (Array array, object value)
771 if (array == null)
772 throw new ArgumentNullException ("array");
774 return IndexOf (array, value, 0, array.Length);
777 public static int IndexOf (Array array, object value, int startIndex)
779 if (array == null)
780 throw new ArgumentNullException ("array");
782 return IndexOf (array, value, startIndex, array.Length - startIndex);
785 public static int IndexOf (Array array, object value, int startIndex, int count)
787 if (array == null)
788 throw new ArgumentNullException ("array");
790 if (array.Rank > 1)
791 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
793 // re-ordered to avoid possible integer overflow
794 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
795 throw new ArgumentOutOfRangeException ();
797 int max = startIndex + count;
798 for (int i = startIndex; i < max; i++) {
799 if (Object.Equals (array.GetValueImpl (i), value))
800 return i;
803 return array.GetLowerBound (0) - 1;
806 [MonoTODO]
807 public void Initialize()
809 //FIXME: We would like to find a compiler that uses
810 // this method. It looks like this method do nothing
811 // in C# so no exception is trown by the moment.
814 public static int LastIndexOf (Array array, object value)
816 if (array == null)
817 throw new ArgumentNullException ("array");
819 return LastIndexOf (array, value, array.Length - 1);
822 public static int LastIndexOf (Array array, object value, int startIndex)
824 if (array == null)
825 throw new ArgumentNullException ("array");
827 return LastIndexOf (array, value, startIndex, startIndex - array.GetLowerBound (0) + 1);
830 public static int LastIndexOf (Array array, object value, int startIndex, int count)
832 if (array == null)
833 throw new ArgumentNullException ("array");
835 if (array.Rank > 1)
836 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
838 if (count < 0 || startIndex < array.GetLowerBound (0) ||
839 startIndex > array.GetUpperBound (0) || startIndex - count + 1 < array.GetLowerBound (0))
840 throw new ArgumentOutOfRangeException ();
842 for (int i = startIndex; i >= startIndex - count + 1; i--) {
843 if (Object.Equals (array.GetValueImpl (i), value))
844 return i;
847 return array.GetLowerBound (0) - 1;
850 public static void Reverse (Array array)
852 if (array == null)
853 throw new ArgumentNullException ("array");
855 Reverse (array, array.GetLowerBound (0), array.GetLength (0));
858 public static void Reverse (Array array, int index, int length)
860 if (array == null)
861 throw new ArgumentNullException ("array");
863 if (array.Rank > 1)
864 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
866 if (index < array.GetLowerBound (0) || length < 0)
867 throw new ArgumentOutOfRangeException ();
869 // re-ordered to avoid possible integer overflow
870 if (index > array.GetUpperBound (0) + 1 - length)
871 throw new ArgumentException ();
873 for (int i = 0; i < length / 2; i++)
875 object tmp;
877 tmp = array.GetValueImpl (index + i);
878 array.SetValueImpl (array.GetValueImpl (index + length - i - 1), index + i);
879 array.SetValueImpl (tmp, index + length - i - 1);
883 public static void Sort (Array array)
885 if (array == null)
886 throw new ArgumentNullException ("array");
888 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), null);
891 public static void Sort (Array keys, Array items)
893 if (keys == null)
894 throw new ArgumentNullException ("keys");
896 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), null);
899 public static void Sort (Array array, IComparer comparer)
901 if (array == null)
902 throw new ArgumentNullException ("array");
904 Sort (array, null, array.GetLowerBound (0), array.GetLength (0), comparer);
907 public static void Sort (Array array, int index, int length)
909 Sort (array, null, index, length, null);
912 public static void Sort (Array keys, Array items, IComparer comparer)
914 if (keys == null)
915 throw new ArgumentNullException ("keys");
917 Sort (keys, items, keys.GetLowerBound (0), keys.GetLength (0), comparer);
920 public static void Sort (Array keys, Array items, int index, int length)
922 Sort (keys, items, index, length, null);
925 public static void Sort (Array array, int index, int length, IComparer comparer)
927 Sort (array, null, index, length, comparer);
930 public static void Sort (Array keys, Array items, int index, int length, IComparer comparer)
932 if (keys == null)
933 throw new ArgumentNullException ("keys");
935 if (keys.Rank > 1 || (items != null && items.Rank > 1))
936 throw new RankException ();
938 if (items != null && keys.GetLowerBound (0) != items.GetLowerBound (0))
939 throw new ArgumentException ();
941 if (index < keys.GetLowerBound (0))
942 throw new ArgumentOutOfRangeException ("index");
944 if (length < 0)
945 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
946 "Value has to be >= 0."));
948 if (keys.Length - (index + keys.GetLowerBound (0)) < length
949 || (items != null && index > items.Length - length))
950 throw new ArgumentException ();
952 try {
953 int low0 = index;
954 int high0 = index + length - 1;
955 qsort (keys, items, low0, high0, comparer);
957 catch (Exception e) {
958 throw new InvalidOperationException (Locale.GetText ("The comparer threw an exception."), e);
962 private static void qsort (Array keys, Array items, int low0, int high0, IComparer comparer)
964 if (low0 >= high0)
965 return;
967 int low = low0;
968 int high = high0;
970 object objPivot = keys.GetValueImpl ((low + high) / 2);
972 while (low <= high) {
973 // Move the walls in
974 while (low < high0 && compare (keys.GetValueImpl (low), objPivot, comparer) < 0)
975 ++low;
976 while (high > low0 && compare (objPivot, keys.GetValueImpl (high), comparer) < 0)
977 --high;
979 if (low <= high) {
980 swap (keys, items, low, high);
981 ++low;
982 --high;
986 if (low0 < high)
987 qsort (keys, items, low0, high, comparer);
988 if (low < high0)
989 qsort (keys, items, low, high0, comparer);
992 private static void swap (Array keys, Array items, int i, int j)
994 object tmp;
996 tmp = keys.GetValueImpl (i);
997 keys.SetValueImpl (keys.GetValue (j), i);
998 keys.SetValueImpl (tmp, j);
1000 if (items != null) {
1001 tmp = items.GetValueImpl (i);
1002 items.SetValueImpl (items.GetValueImpl (j), i);
1003 items.SetValueImpl (tmp, j);
1007 private static int compare (object value1, object value2, IComparer comparer)
1009 if (value1 == null)
1010 return value2 == null ? 0 : -1;
1011 else if (value2 == null)
1012 return 1;
1013 else if (comparer == null)
1014 return ((IComparable) value1).CompareTo (value2);
1015 else
1016 return comparer.Compare (value1, value2);
1019 public virtual void CopyTo (Array array, int index)
1021 if (array == null)
1022 throw new ArgumentNullException ("array");
1024 // The order of these exception checks may look strange,
1025 // but that's how the microsoft runtime does it.
1026 if (this.Rank > 1)
1027 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1028 if (index + this.GetLength (0) > array.GetLowerBound (0) + array.GetLength (0))
1029 throw new ArgumentException ();
1030 if (array.Rank > 1)
1031 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
1032 if (index < 0)
1033 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1034 "Value has to be >= 0."));
1036 Copy (this, this.GetLowerBound (0), array, index, this.GetLength (0));
1039 #if NET_1_1
1040 [ComVisible (false)]
1041 public virtual void CopyTo (Array array, long index)
1043 if (index < 0 || index > Int32.MaxValue)
1044 throw new ArgumentOutOfRangeException ("index", Locale.GetText (
1045 "Value must be >= 0 and <= Int32.MaxValue."));
1047 CopyTo (array, (int) index);
1049 #endif
1051 internal class SimpleEnumerator : IEnumerator, ICloneable
1053 Array enumeratee;
1054 int currentpos;
1055 int length;
1057 public SimpleEnumerator (Array arrayToEnumerate)
1059 this.enumeratee = arrayToEnumerate;
1060 this.currentpos = -1;
1061 this.length = arrayToEnumerate.Length;
1064 public object Current {
1065 get {
1066 // Exception messages based on MS implementation
1067 if (currentpos < 0 )
1068 throw new InvalidOperationException (Locale.GetText (
1069 "Enumeration has not started."));
1070 if (currentpos >= length)
1071 throw new InvalidOperationException (Locale.GetText (
1072 "Enumeration has already ended"));
1073 // Current should not increase the position. So no ++ over here.
1074 return enumeratee.GetValueImpl (currentpos);
1078 public bool MoveNext()
1080 //The docs say Current should throw an exception if last
1081 //call to MoveNext returned false. This means currentpos
1082 //should be set to length when returning false.
1083 if (currentpos < length)
1084 currentpos++;
1085 if(currentpos < length)
1086 return true;
1087 else
1088 return false;
1091 public void Reset()
1093 currentpos = -1;
1096 public object Clone ()
1098 return MemberwiseClone ();
1101 #if NET_2_0
1102 [CLSCompliant (false)]
1103 public static void Resize <T> (ref T [] arr, int sz) {
1104 if (sz < 0)
1105 throw new ArgumentOutOfRangeException ();
1107 if (arr == null) {
1108 arr = new T [sz];
1109 return;
1112 if (arr.Length == sz)
1113 return;
1115 T [] a = new T [sz];
1116 Array.Copy (arr, a, Math.Min (sz, arr.Length));
1117 arr = a;
1120 [CLSCompliant (false)]
1121 public static bool TrueForAll <T> (T [] array, Predicate <T> p)
1123 if (array == null || p == null)
1124 throw new ArgumentNullException ();
1126 foreach (T t in array)
1127 if (! p (t))
1128 return false;
1130 return true;
1132 [CLSCompliant (false)]
1133 public static void ForEach <T> (T [] array, Action <T> a)
1135 if (array == null || a == null)
1136 throw new ArgumentNullException ();
1138 foreach (T t in array)
1139 a (t);
1142 [CLSCompliant (false)]
1143 public static U [] ConvertAll <T, U> (T [] s, Converter <T, U> c)
1145 if (s == null || c == null)
1146 throw new ArgumentNullException ();
1148 U [] r = new U [s.Length];
1150 for (int i = 0; i < s.Length; i ++)
1151 r [i] = c (s [i]);
1153 return r;
1156 [CLSCompliant (false)]
1157 public static int FindLastIndex <T> (T [] a, Predicate <T> c)
1159 if (a == null)
1160 throw new ArgumentNullException ();
1162 return FindLastIndex <T> (a, 0, a.Length, c);
1165 [CLSCompliant (false)]
1166 public static int FindLastIndex <T> (T [] a, int idx, Predicate <T> c)
1168 if (a == null)
1169 throw new ArgumentNullException ();
1171 return FindLastIndex <T> (a, idx, a.Length - idx, c);
1174 [CLSCompliant (false)]
1175 public static int FindLastIndex <T> (T [] a, int idx, int cnt, Predicate <T> c)
1177 if (a == null || c == null)
1178 throw new ArgumentNullException ();
1180 if (idx > a.Length || idx + cnt > a.Length)
1181 throw new ArgumentOutOfRangeException ();
1183 for (int i = idx + cnt - 1; i >= idx; i --)
1184 if (c (a [i]))
1185 return i;
1187 return -1;
1190 [CLSCompliant (false)]
1191 public static int FindIndex <T> (T [] a, Predicate <T> c)
1193 if (a == null)
1194 throw new ArgumentNullException ();
1196 return FindIndex <T> (a, 0, a.Length, c);
1199 [CLSCompliant (false)]
1200 public static int FindIndex <T> (T [] a, int idx, Predicate <T> c)
1202 if (a == null)
1203 throw new ArgumentNullException ();
1205 return FindIndex <T> (a, idx, a.Length - idx, c);
1208 [CLSCompliant (false)]
1209 public static int FindIndex <T> (T [] a, int idx, int cnt, Predicate <T> c)
1211 if (a == null || c == null)
1212 throw new ArgumentNullException ();
1214 if (idx > a.Length || idx + cnt > a.Length)
1215 throw new ArgumentOutOfRangeException ();
1217 for (int i = idx; i < idx + cnt; i ++)
1218 if (c (a [i]))
1219 return i;
1221 return -1;
1224 [CLSCompliant (false)]
1225 public static int BinarySearch <T> (T [] a, T x)
1227 if (a == null)
1228 throw new ArgumentNullException ("a");
1230 return BinarySearch <T> (a, 0, a.Length, x, null);
1233 [CLSCompliant (false)]
1234 public static int BinarySearch <T> (T [] a, T x, IComparer <T> c)
1236 if (a == null)
1237 throw new ArgumentNullException ("a");
1239 return BinarySearch <T> (a, 0, a.Length, x, c);
1242 [CLSCompliant (false)]
1243 public static int BinarySearch <T> (T [] a, int offset, int length, T x)
1245 return BinarySearch <T> (a, offset, length, x, null);
1248 [CLSCompliant (false)]
1249 public static int BinarySearch <T> (T [] a, int offset, int length, T x, IComparer <T> c)
1251 if (a == null)
1252 throw new ArgumentNullException ("a");
1253 if (offset > a.Length || (offset + length) > a.Length || offset < 0)
1254 throw new ArgumentOutOfRangeException ();
1256 if (c == null)
1257 c = Comparer <T>.Default;
1259 int iMin = offset;
1260 int iMax = offset + length - 1;
1261 int iCmp = 0;
1262 try {
1263 while (iMin <= iMax) {
1264 int iMid = (iMin + iMax) / 2;
1265 iCmp = c.Compare (x, a [iMid]);
1267 if (iCmp == 0)
1268 return iMid;
1269 else if (iCmp < 0)
1270 iMax = iMid - 1;
1271 else
1272 iMin = iMid + 1; // compensate for the rounding down
1275 catch (Exception e) {
1276 throw new InvalidOperationException (Locale.GetText ("Comparer threw an exception."), e);
1279 return ~iMin;
1282 [CLSCompliant (false)]
1283 public static int IndexOf <T> (T [] array, T value)
1285 if (array == null)
1286 throw new ArgumentNullException ("array");
1288 return IndexOf (array, value, 0, array.Length);
1291 [CLSCompliant (false)]
1292 public static int IndexOf <T> (T [] array, T value, int startIndex)
1294 if (array == null)
1295 throw new ArgumentNullException ("array");
1297 return IndexOf (array, value, startIndex, array.Length - startIndex);
1300 [CLSCompliant (false)]
1301 public static int IndexOf <T> (T [] array, T value, int startIndex, int count)
1303 if (array == null)
1304 throw new ArgumentNullException ("array");
1306 // re-ordered to avoid possible integer overflow
1307 if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count)
1308 throw new ArgumentOutOfRangeException ();
1310 int max = startIndex + count;
1311 for (int i = startIndex; i < max; i++) {
1312 if (Object.Equals (array [i], value))
1313 if (Object.Equals (array [i], value))
1314 return i;
1317 return -1;
1320 [CLSCompliant (false)]
1321 public static int LastIndexOf <T> (T [] array, T value)
1323 if (array == null)
1324 throw new ArgumentNullException ("array");
1326 return LastIndexOf (array, value, array.Length - 1);
1329 [CLSCompliant (false)]
1330 public static int LastIndexOf <T> (T [] array, T value, int startIndex)
1332 if (array == null)
1333 throw new ArgumentNullException ("array");
1335 return LastIndexOf (array, value, startIndex, startIndex - array.Length + 1);
1338 [CLSCompliant (false)]
1339 public static int LastIndexOf <T> (T [] array, T value, int startIndex, int count)
1341 if (array == null)
1342 throw new ArgumentNullException ("array");
1344 if (count < 0 || startIndex > array.Length || startIndex - count + 1 < 0)
1345 throw new ArgumentOutOfRangeException ();
1347 for (int i = startIndex; i >= startIndex - count + 1; i--) {
1348 if (Object.Equals (array [i], value))
1349 return i;
1352 return -1;
1355 [CLSCompliant (false)]
1356 public static T [] FindAll <T> (T [] a, Predicate <T> p)
1358 if (a == null || p == null)
1359 throw new ArgumentNullException ();
1361 int pos = 0;
1362 T [] d = new T [a.Length];
1363 foreach (T t in a)
1364 if (p (t))
1365 d [pos ++] = t;
1367 Resize <T> (ref a, pos);
1368 return a;
1371 [CLSCompliant (false)]
1372 public static bool Exists <T> (T [] a, Predicate <T> p)
1374 if (a == null || p == null)
1375 throw new ArgumentNullException ();
1377 foreach (T t in a)
1378 if (p (t))
1379 return true;
1380 return false;
1383 [CLSCompliant (false)]
1384 [MonoTODO]
1385 public static IList<T> AsReadOnly<T> (T[] array)
1387 throw new NotImplementedException ();
1390 #if FIXME
1391 [CLSCompliant (false)]
1392 public static Nullable <T> Find <T> (T [] a, Predicate <T> p)
1394 if (a == null || p == null)
1395 throw new ArgumentNullException ();
1397 foreach (T t in a)
1398 if (p (t))
1399 return new Nullable <T> (t);
1401 return default (Nullable <T>);
1404 [CLSCompliant (false)]
1405 public static Nullable <T> FindLast <T> (T [] a, Predicate <T> p)
1407 if (a == null || p == null)
1408 throw new ArgumentNullException ();
1410 for (int i = a.Length - 1; i >= 0; i--)
1411 if (p (a [i]))
1412 return new Nullable <T> (a [i]);
1414 return default (Nullable <T>);
1416 #endif
1418 // Fixme: wtf is constrained about this
1419 public static void ConstrainedCopy (Array s, int s_i, Array d, int d_i, int c)
1421 Copy (s, s_i, d, d_i, c);
1423 #endif