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)
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:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
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
;
40 using System
.Collections
.Generic
;
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
57 int length
= this.GetLength (0);
59 for (int i
= 1; i
< this.Rank
; i
++) {
60 length
*= this.GetLength (i
);
68 public long LongLength
{
69 get { return Length; }
75 return this.GetRank ();
80 object IList
.this [int index
] {
82 if (unchecked ((uint) index
) >= unchecked ((uint) Length
))
83 throw new ArgumentOutOfRangeException ("index");
84 return GetValueImpl (index
);
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 ();
100 Array
.Clear (this, this.GetLowerBound (0), this.Length
);
103 bool IList
.Contains (object value)
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
)))
116 int IList
.IndexOf (object value)
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.
126 return i
+ this.GetLowerBound (0);
131 // lower bound may be MinValue
132 retVal
= this.GetLowerBound (0) - 1;
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
);
162 public long GetLongLength (int dimension
)
164 return GetLength (dimension
);
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
);
192 int ICollection
.Count
{
198 public virtual bool IsSynchronized
{
204 public virtual object SyncRoot
{
210 public virtual bool IsFixedSize
{
216 public virtual bool IsReadOnly
{
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
)
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
);
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
);
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
);
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
);
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
);
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
);
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
);
343 // // This function is currently unused, but just in case we need it later on ... */
344 // internal int IndexToPos (int[] idxs)
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);
367 public void SetValue (object value, int index
)
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}
;
395 return CreateInstanceImpl (elementType
, lengths
, bounds
);
398 public static Array
CreateInstance (Type elementType
, int length1
, int length2
)
400 int[] lengths
= {length1, length2}
;
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}
;
411 return CreateInstanceImpl (elementType
, lengths
, bounds
);
414 public static Array
CreateInstance (Type elementType
, int[] lengths
)
416 if (elementType
== null)
417 throw new ArgumentNullException ("elementType");
419 throw new ArgumentNullException ("lengths");
421 if (lengths
.Length
> 255)
422 throw new TypeLoadException ();
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");
434 throw new ArgumentNullException ("lengths");
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
++) {
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
);
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
;
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
));
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
));
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
));
508 public static int BinarySearch (Array array
, object value)
511 throw new ArgumentNullException ("array");
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
)
528 throw new ArgumentNullException ("array");
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)
543 throw new ArgumentNullException ("array");
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."));
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
)
568 throw new ArgumentNullException ("array");
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."));
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
;
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;
604 while (iMin
<= iMax
) {
605 int iMid
= (iMin
+ iMax
) / 2;
606 object elt
= array
.GetValueImpl (iMid
);
608 iCmp
= comparer
.Compare (value, elt
);
615 iMin
= iMid
+ 1; // compensate for the rounding down
618 catch (Exception e
) {
619 throw new InvalidOperationException (Locale
.GetText ("Comparer threw an exception."), e
);
625 public static void Clear (Array array
, int index
, int length
)
628 throw new ArgumentNullException ("array");
630 throw new ArgumentOutOfRangeException ("length < 0");
632 int low
= array
.GetLowerBound (0);
634 throw new IndexOutOfRangeException ("index < lower bound");
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");
673 throw new ArgumentOutOfRangeException ("length", Locale
.GetText (
674 "Value has to be >= 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
))
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
);
705 destinationArray
.SetValueImpl (srcval
, dest_pos
+ i
);
707 if ((dst_type
.IsValueType
|| dst_type
.Equals (typeof (String
))) &&
708 (src_type
.Equals (typeof (Object
))))
709 throw new InvalidCastException ();
711 throw new ArrayTypeMismatchException (String
.Format (Locale
.GetText (
712 "(Types: source={0}; target={1})"), src_type
.FullName
, dst_type
.FullName
));
717 for (int i
= length
- 1; i
>= 0; i
--) {
718 Object srcval
= sourceArray
.GetValueImpl (source_pos
+ i
);
721 destinationArray
.SetValueImpl (srcval
, dest_pos
+ i
);
723 if ((dst_type
.IsValueType
|| dst_type
.Equals (typeof (String
))) &&
724 (src_type
.Equals (typeof (Object
))))
725 throw new InvalidCastException ();
727 throw new ArrayTypeMismatchException (String
.Format (Locale
.GetText (
728 "(Types: source={0}; target={1})"), src_type
.FullName
, dst_type
.FullName
));
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
);
769 public static int IndexOf (Array array
, object value)
772 throw new ArgumentNullException ("array");
774 return IndexOf (array
, value, 0, array
.Length
);
777 public static int IndexOf (Array array
, object value, int startIndex
)
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
)
788 throw new ArgumentNullException ("array");
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))
803 return array
.GetLowerBound (0) - 1;
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)
817 throw new ArgumentNullException ("array");
819 return LastIndexOf (array
, value, array
.Length
- 1);
822 public static int LastIndexOf (Array array
, object value, int startIndex
)
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
)
833 throw new ArgumentNullException ("array");
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))
847 return array
.GetLowerBound (0) - 1;
850 public static void Reverse (Array array
)
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
)
861 throw new ArgumentNullException ("array");
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
++)
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
)
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
)
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
)
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
)
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
)
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");
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 ();
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
)
970 object objPivot
= keys
.GetValueImpl ((low
+ high
) / 2);
972 while (low
<= high
) {
974 while (low
< high0
&& compare (keys
.GetValueImpl (low
), objPivot
, comparer
) < 0)
976 while (high
> low0
&& compare (objPivot
, keys
.GetValueImpl (high
), comparer
) < 0)
980 swap (keys
, items
, low
, high
);
987 qsort (keys
, items
, low0
, high
, comparer
);
989 qsort (keys
, items
, low
, high0
, comparer
);
992 private static void swap (Array keys
, Array items
, int i
, int j
)
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
)
1010 return value2
== null ? 0 : -1;
1011 else if (value2
== null)
1013 else if (comparer
== null)
1014 return ((IComparable
) value1
).CompareTo (value2
);
1016 return comparer
.Compare (value1
, value2
);
1019 public virtual void CopyTo (Array array
, int index
)
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.
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 ();
1031 throw new RankException (Locale
.GetText ("Only single dimension arrays are supported."));
1033 throw new ArgumentOutOfRangeException ("index", Locale
.GetText (
1034 "Value has to be >= 0."));
1036 Copy (this, this.GetLowerBound (0), array
, index
, this.GetLength (0));
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
);
1051 internal class SimpleEnumerator
: IEnumerator
, ICloneable
1057 public SimpleEnumerator (Array arrayToEnumerate
)
1059 this.enumeratee
= arrayToEnumerate
;
1060 this.currentpos
= -1;
1061 this.length
= arrayToEnumerate
.Length
;
1064 public object Current
{
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
)
1085 if(currentpos
< length
)
1096 public object Clone ()
1098 return MemberwiseClone ();
1102 [CLSCompliant (false)]
1103 public static void Resize
<T
> (ref T
[] arr
, int sz
) {
1105 throw new ArgumentOutOfRangeException ();
1112 if (arr
.Length
== sz
)
1115 T
[] a
= new T
[sz
];
1116 Array
.Copy (arr
, a
, Math
.Min (sz
, arr
.Length
));
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
)
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
)
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
++)
1156 [CLSCompliant (false)]
1157 public static int FindLastIndex
<T
> (T
[] a
, Predicate
<T
> c
)
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
)
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
--)
1190 [CLSCompliant (false)]
1191 public static int FindIndex
<T
> (T
[] a
, Predicate
<T
> c
)
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
)
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
++)
1224 [CLSCompliant (false)]
1225 public static int BinarySearch
<T
> (T
[] a
, T x
)
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
)
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
)
1252 throw new ArgumentNullException ("a");
1253 if (offset
> a
.Length
|| (offset
+ length
) > a
.Length
|| offset
< 0)
1254 throw new ArgumentOutOfRangeException ();
1257 c
= Comparer
<T
>.Default
;
1260 int iMax
= offset
+ length
- 1;
1263 while (iMin
<= iMax
) {
1264 int iMid
= (iMin
+ iMax
) / 2;
1265 iCmp
= c
.Compare (x
, a
[iMid
]);
1272 iMin
= iMid
+ 1; // compensate for the rounding down
1275 catch (Exception e
) {
1276 throw new InvalidOperationException (Locale
.GetText ("Comparer threw an exception."), e
);
1282 [CLSCompliant (false)]
1283 public static int IndexOf
<T
> (T
[] array
, T
value)
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
)
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
)
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))
1320 [CLSCompliant (false)]
1321 public static int LastIndexOf
<T
> (T
[] array
, T
value)
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
)
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
)
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))
1355 [CLSCompliant (false)]
1356 public static T
[] FindAll
<T
> (T
[] a
, Predicate
<T
> p
)
1358 if (a
== null || p
== null)
1359 throw new ArgumentNullException ();
1362 T
[] d
= new T
[a
.Length
];
1367 Resize
<T
> (ref a
, pos
);
1371 [CLSCompliant (false)]
1372 public static bool Exists
<T
> (T
[] a
, Predicate
<T
> p
)
1374 if (a
== null || p
== null)
1375 throw new ArgumentNullException ();
1383 [CLSCompliant (false)]
1385 public static IList
<T
> AsReadOnly
<T
> (T
[] array
)
1387 throw new NotImplementedException ();
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 ();
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
--)
1412 return new Nullable
<T
> (a
[i
]);
1414 return default (Nullable
<T
>);
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
);