2021-08-04 22:10:27 +03:00

1691 lines
66 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace system
{
[System.Serializable]
public abstract class Array : System.ICloneable, IList, IStructuralComparable, IStructuralEquatable
{
//
// Array helper proxy used when casting an array to an interface
// or to System.Array
//
[java.attr.RetainType] private object arr;
[java.attr.RetainType] private int len;
[java.attr.RetainType] private int rank;
[java.attr.RetainType] private bool jagged;
protected Array(object _arr)
{
arr = _arr;
len = java.lang.reflect.Array.getLength(_arr);
var s = ((java.lang.Object) arr).getClass().getName();
for (; rank < s.Length && s[rank] == '['; rank++) ;
}
static void ThrowIfNull(object checkObject)
{
if (checkObject == null)
throw new System.ArgumentNullException();
}
int ICollection.Count => len;
//
// ICloneable
//
public object Clone() => Clone(arr, len);
public static object Clone(object arr, int len)
{
switch (arr)
{
case bool[] boolArray:
return java.util.Arrays.copyOf(boolArray, len);
case sbyte[] byteArray:
return java.util.Arrays.copyOf(byteArray, len);
case char[] charArray:
return java.util.Arrays.copyOf(charArray, len);
case short[] shortArray:
return java.util.Arrays.copyOf(shortArray, len);
case int[] intArray:
return java.util.Arrays.copyOf(intArray, len);
case long[] longArray:
return java.util.Arrays.copyOf(longArray, len);
case float[] floatArray:
return java.util.Arrays.copyOf(floatArray, len);
case double[] doubleArray:
return java.util.Arrays.copyOf(doubleArray, len);
}
var type = ((java.lang.Object) arr).getClass().getComponentType();
var copy = java.util.Arrays.copyOf((object[]) arr, len);
int idx;
object obj;
if (type.isArray())
{
for (idx = 0; idx < len; idx++)
{
obj = java.lang.reflect.Array.get(copy, idx);
if (obj != null)
{
obj = Clone(obj, java.lang.reflect.Array.getLength(obj));
java.lang.reflect.Array.set(copy, idx, obj);
}
}
}
else if (system.RuntimeType.IsValueClass(type))
{
var copyArray = (ValueType[]) copy;
for (idx = 0; idx < len; idx++)
copyArray[idx] = ((ValueMethod) copyArray[idx]).Clone();
}
return copy;
}
//
// ConstrainedCopy, Copy, CopyTo, ICollection.CopyTo
//
private static void CheckCopyArgs(Array sourceArray, int sourceIndex,
Array destinationArray, int destinationIndex,
int length)
{
ThrowIfNull(sourceArray);
ThrowIfNull(destinationArray);
if ( sourceArray.rank != 1 && (! sourceArray.jagged)
|| sourceArray.rank != destinationArray.rank
|| sourceArray.jagged != destinationArray.jagged)
throw new System.RankException();
if (sourceIndex < 0 || destinationIndex < 0)
throw new System.ArgumentOutOfRangeException();
if ( sourceIndex + length > sourceArray.len
|| destinationIndex + length > destinationArray.len)
throw new System.ArgumentException();
}
public static void ConstrainedCopy(Array sourceArray, int sourceIndex,
Array destinationArray, int destinationIndex,
int length)
{
CheckCopyArgs(sourceArray, sourceIndex,
destinationArray, destinationIndex,
length);
var destinationArray_arr = destinationArray.arr;
object copy = Clone(destinationArray_arr, destinationArray.len);
try
{
CopyInternal(sourceArray.arr, sourceIndex,
destinationArray_arr, destinationIndex,
length);
copy = null;
}
finally
{
if (copy != null)
{
CopyInternal(copy, sourceIndex,
destinationArray_arr, destinationIndex,
length);
}
}
}
public void CopyTo(System.Array array, long index)
{
int intIndex = (int) index;
if (intIndex != index)
throw new System.ArgumentOutOfRangeException();
CopyTo(array, intIndex);
}
public void CopyTo(System.Array array, int index)
{
// note that CopyTo is defined to only work for single dim arrays
Copy(this, 0, (system.Array) (object) array, index, len);
}
public static void Copy(Array sourceArray, Array destinationArray, int length)
=> Copy(sourceArray, 0, destinationArray, 0, length);
public static void Copy(Array sourceArray, Array destinationArray, long length)
=> Copy(sourceArray, 0, destinationArray, 0, length);
public static void Copy(Array sourceArray, long sourceIndex,
Array destinationArray, long destinationIndex,
long length)
{
int intSourceIndex = (int) sourceIndex;
int intDestinationIndex = (int) destinationIndex;
int intLength = (int) length;
if (intSourceIndex != sourceIndex || intDestinationIndex != destinationIndex)
throw new System.ArgumentOutOfRangeException();
if (intLength != length)
throw new System.ArgumentOutOfRangeException();
Copy(sourceArray, intSourceIndex,
destinationArray, intDestinationIndex,
intLength);
}
public static void Copy(Array sourceArray, int sourceIndex,
Array destinationArray, int destinationIndex,
int length)
{
CheckCopyArgs(sourceArray, sourceIndex,
destinationArray, destinationIndex,
length);
CopyInternal(sourceArray.arr, sourceIndex,
destinationArray.arr, destinationIndex,
length);
}
private static void CopyInternal(object srcArr, int srcIndex,
object dstArr, int dstIndex,
int length)
{
var srcElemType = ((java.lang.Object) srcArr).getClass().getComponentType();
var dstElemType = ((java.lang.Object) dstArr).getClass().getComponentType();
if (! dstElemType.isAssignableFrom(srcElemType))
throw new System.ArrayTypeMismatchException();
bool isValueType = system.RuntimeType.IsValueClass(srcElemType);
if (isValueType != system.RuntimeType.IsValueClass(dstElemType))
throw new System.ArrayTypeMismatchException();
if (isValueType)
{
ValueType srcObj, dstObj;
if ( object.ReferenceEquals(srcArr, dstArr)
&& dstIndex > srcIndex
&& dstIndex < srcIndex + length)
{
// copy backwards to prevent smearing
while (length-- > 0)
{
srcObj = (ValueType) java.lang.reflect.Array.get(srcArr, srcIndex + length);
dstObj = (ValueType) java.lang.reflect.Array.get(dstArr, dstIndex + length);
((ValueMethod) ((ValueType) srcObj)).CopyTo((ValueType) dstObj);
}
}
else
{
for (int idx = 0; idx < length; idx++)
{
srcObj = (ValueType) java.lang.reflect.Array.get(srcArr, srcIndex + idx);
dstObj = (ValueType) java.lang.reflect.Array.get(dstArr, dstIndex + idx);
((ValueMethod) ((ValueType) srcObj)).CopyTo((ValueType) dstObj);
}
}
}
else
{
// for an array of primitives or references, use built-in arraycopy
java.lang.System.arraycopy(srcArr, srcIndex, dstArr, dstIndex, length);
}
}
//
// System.Array methods
//
public static ReadOnlyCollection<T> AsReadOnly<T>(T[] array)
{
ThrowIfNull(array);
return new ReadOnlyCollection<T>(array);
}
public int Rank => jagged ? 1 : rank;
//
// GetLength, GetLongLength, GetLowerBound, GetUpperBound
//
public int GetLength(int dimension)
{
if (dimension < 0 || dimension >= Rank)
throw new System.IndexOutOfRangeException();
if (dimension == 0)
return len;
object sub = arr;
for (int i = 0; i < dimension; i++)
sub = java.lang.reflect.Array.get(sub, 0);
return java.lang.reflect.Array.getLength(sub);
}
public long GetLongLength(int dimension) => GetLength(dimension);
public int GetLowerBound(int dimension) => 0;
public int GetUpperBound(int dimension) => GetLength(dimension) - 1;
//
// GetValue (integer)
//
public object GetValue(int index) => Load(arr, index);
public object GetValue(int index1, int index2)
{
if (Rank != 2)
throw new System.ArgumentException();
var sub = java.lang.reflect.Array.get(arr, index1);
return Load(sub, index2);
}
public object GetValue(int index1, int index2, int index3)
{
if (Rank != 3)
throw new System.ArgumentException();
var sub = java.lang.reflect.Array.get(arr, index1);
sub = java.lang.reflect.Array.get(sub, index2);
return Load(sub, index3);
}
public object GetValue(params int[] indices)
{
ThrowIfNull(indices);
int n = indices.Length;
if (Rank != n--)
throw new System.ArgumentException();
object sub = arr;
for (int i = 0; i < n; i++)
sub = java.lang.reflect.Array.get(sub, indices[i]);
return Load(sub, indices[n]);
}
//
// GetValue (long)
//
public object GetValue(long index)
{
var intIndex = (int) index;
if (intIndex != index)
throw new System.ArgumentOutOfRangeException();
return GetValue(intIndex);
}
public object GetValue(long index1, long index2)
{
int intIndex1 = (int) index1;
int intIndex2 = (int) index2;
if (intIndex1 != index1 || intIndex2 != index2)
throw new System.ArgumentOutOfRangeException();
return GetValue(intIndex1, intIndex2);
}
public object GetValue(long index1, long index2, long index3)
{
int intIndex1 = (int) index1;
int intIndex2 = (int) index2;
int intIndex3 = (int) index3;
if (intIndex1 != index1 || intIndex2 != index2 || intIndex3 != index3)
throw new System.ArgumentOutOfRangeException();
return GetValue(intIndex1, intIndex2, intIndex3);
}
public object GetValue(params long[] indices)
{
int[] intIndices = null;
if (indices != null)
{
int n = indices.Length;
intIndices = new int[n];
for (int i = 0; i < n; i++)
{
long longIndex = indices[i];
int intIndex = (int) longIndex;
if (intIndex != longIndex)
throw new System.ArgumentOutOfRangeException();
intIndices[i] = intIndex;
}
}
return GetValue(intIndices);
}
//
// SetValue (integer)
//
public void SetValue(object value, int index) => Store(arr, index, value);
public void SetValue(object value, int index1, int index2)
{
if (Rank != 2)
throw new System.ArgumentException();
var sub = java.lang.reflect.Array.get(arr, index1);
Store(sub, index2, value);
}
public void SetValue(object value, int index1, int index2, int index3)
{
if (Rank != 3)
throw new System.ArgumentException();
var sub = java.lang.reflect.Array.get(arr, index1);
sub = java.lang.reflect.Array.get(sub, index2);
Store(sub, index3, value);
}
public void SetValue(object value, params int[] indices)
{
ThrowIfNull(indices);
int n = indices.Length;
if (Rank != n--)
throw new System.ArgumentException();
object sub = arr;
for (int i = 0; i < n; i++)
sub = java.lang.reflect.Array.get(sub, indices[i]);
Store(sub, indices[n], value);
}
public void SetValue(object value, long index)
{
var intIndex = (int) index;
if (intIndex != index)
throw new System.ArgumentOutOfRangeException();
SetValue(value, intIndex);
}
public void SetValue(object value, long index1, long index2)
{
int intIndex1 = (int) index1;
int intIndex2 = (int) index2;
if (intIndex1 != index1 || intIndex2 != index2)
throw new System.ArgumentOutOfRangeException();
SetValue(value, intIndex1, intIndex2);
}
public void SetValue(object value, long index1, long index2, long index3)
{
int intIndex1 = (int) index1;
int intIndex2 = (int) index2;
int intIndex3 = (int) index3;
if (intIndex1 != index1 || intIndex2 != index2 || intIndex3 != index3)
throw new System.ArgumentOutOfRangeException();
SetValue(value, intIndex1, intIndex2, intIndex3);
}
public void SetValue(object value, params long[] indices)
{
int[] intIndices = null;
if (indices != null)
{
int n = indices.Length;
intIndices = new int[n];
for (int i = 0; i < n; i++)
{
long longIndex = indices[i];
int intIndex = (int) longIndex;
if (intIndex != longIndex)
throw new System.ArgumentOutOfRangeException();
intIndices[i] = intIndex;
}
}
SetValue(value, intIndices);
}
//
// IndexOf
//
public static int IndexOf(Array array, object value, int startIndex, int count)
{
ThrowIfNull(array);
if (array.Rank != 1)
throw new System.RankException();
if (startIndex < 0 || startIndex > array.len)
throw new System.ArgumentOutOfRangeException();
if (count < 0 || count > array.len - startIndex)
throw new System.ArgumentOutOfRangeException();
int endIndex = startIndex + count;
switch (array.arr)
{
case bool[] boolArray:
var boolValue = (bool) value;
for (; startIndex < endIndex; startIndex++)
if (boolArray[startIndex] == boolValue)
return startIndex;
break;
case sbyte[] byteArray:
var byteValue = (sbyte) value;
for (; startIndex < endIndex; startIndex++)
if (byteArray[startIndex] == byteValue)
return startIndex;
break;
case char[] charArray:
var charValue = (char) value;
for (; startIndex < endIndex; startIndex++)
if (charArray[startIndex] == charValue)
return startIndex;
break;
case short[] shortArray:
var shortValue = (short) value;
for (; startIndex < endIndex; startIndex++)
if (shortArray[startIndex] == shortValue)
return startIndex;
break;
case int[] intArray:
var intValue = (int) value;
for (; startIndex < endIndex; startIndex++)
if (intArray[startIndex] == intValue)
return startIndex;
break;
case long[] longArray:
var longValue = (long) value;
for (; startIndex < endIndex; startIndex++)
if (longArray[startIndex] == longValue)
return startIndex;
break;
case float[] floatArray:
var floatValue = (float) value;
for (; startIndex < endIndex; startIndex++)
if (floatArray[startIndex] == floatValue)
return startIndex;
break;
case double[] doubleArray:
var doubleValue = (double) value;
for (; startIndex < endIndex; startIndex++)
if (doubleArray[startIndex] == doubleValue)
return startIndex;
break;
case object[] objectArray:
if (value == null)
{
for (; startIndex < endIndex; startIndex++)
if (objectArray[startIndex] == null)
return startIndex;
}
else
{
for (; startIndex < endIndex; startIndex++)
{
var objectAtIndex = objectArray[startIndex];
if (objectAtIndex != null && objectAtIndex.Equals(value))
return startIndex;
}
}
break;
default:
throw new System.InvalidOperationException();
}
return -1;
}
public static int IndexOf(Array array, object value, int startIndex)
{
ThrowIfNull(array);
return IndexOf(array, value, startIndex, array.len - startIndex);
}
public static int IndexOf(Array array, object value) => IndexOf(array, value, 0);
public static int IndexOf<T>(T[] array, T value)
=> IndexOf((Array) (object) array, (object) value, 0);
public static int IndexOf<T>(T[] array, T value, int startIndex)
=> IndexOf((Array) (object) array, (object) value, startIndex);
public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
=> IndexOf((Array) (object) array, (object) value, startIndex, count);
//
// IndexOf
//
public static int LastIndexOf(Array array, object value, int startIndex, int count)
{
ThrowIfNull(array);
if (array.Rank != 1)
throw new System.RankException();
if (startIndex < 0 || startIndex > array.len)
throw new System.ArgumentOutOfRangeException();
if (count < 0 || count > array.len - startIndex)
throw new System.ArgumentOutOfRangeException();
int endIndex = startIndex + count;
switch (array.arr)
{
case bool[] boolArray:
var boolValue = (bool) value;
while (endIndex-- > startIndex)
if (boolArray[endIndex] == boolValue)
return endIndex;
break;
case sbyte[] byteArray:
var byteValue = (sbyte) value;
while (endIndex-- > startIndex)
if (byteArray[endIndex] == byteValue)
return endIndex;
break;
case char[] charArray:
var charValue = (char) value;
while (endIndex-- > startIndex)
if (charArray[endIndex] == charValue)
return endIndex;
break;
case short[] shortArray:
var shortValue = (short) value;
while (endIndex-- > startIndex)
if (shortArray[endIndex] == shortValue)
return endIndex;
break;
case int[] intArray:
var intValue = (int) value;
while (endIndex-- > startIndex)
if (intArray[endIndex] == intValue)
return endIndex;
break;
case long[] longArray:
var longValue = (long) value;
while (endIndex-- > startIndex)
if (longArray[endIndex] == longValue)
return endIndex;
break;
case float[] floatArray:
var floatValue = (float) value;
while (endIndex-- > startIndex)
if (floatArray[endIndex] == floatValue)
return endIndex;
break;
case double[] doubleArray:
var doubleValue = (double) value;
while (endIndex-- > startIndex)
if (doubleArray[endIndex] == doubleValue)
return endIndex;
break;
case object[] objectArray:
if (value == null)
{
while (endIndex-- > startIndex)
if (objectArray[endIndex] == null)
return endIndex;
}
else
{
while (endIndex-- > startIndex)
{
var objectAtIndex = objectArray[endIndex];
if (objectAtIndex != null && objectAtIndex.Equals(value))
return endIndex;
}
}
break;
default:
throw new System.InvalidOperationException();
}
return -1;
}
public static int LastIndexOf(Array array, object value, int startIndex)
{
ThrowIfNull(array);
return LastIndexOf(array, value, startIndex, array.len - startIndex);
}
public static int LastIndexOf(Array array, object value) => LastIndexOf(array, value, 0);
public static int LastIndexOf<T>(T[] array, T value)
=> LastIndexOf((Array) (object) array, (object) value, 0);
public static int LastIndexOf<T>(T[] array, T value, int startIndex)
=> LastIndexOf((Array) (object) array, (object) value, startIndex);
public static int LastIndexOf<T>(T[] array, T value, int startIndex, int count)
=> LastIndexOf((Array) (object) array, (object) value, startIndex, count);
//
// Sort (non-generic)
//
public static void Sort(Array array)
=> SortCommon(array, array, 0, -1, false, null);
public static void Sort(Array array, system.collections.IComparer comparer)
=> SortCommon(array, array, 0, -1, false, comparer);
public static void Sort(Array array, int index, int length)
=> SortCommon(array, array, index, length, true, null);
public static void Sort(Array array, int index, int length, system.collections.IComparer comparer)
=> SortCommon(array, array, index, length, true, comparer);
public static void Sort(Array keys, Array items)
=> SortCommon(keys, items, 0, -1, false, null);
public static void Sort(Array keys, Array items, system.collections.IComparer comparer)
=> SortCommon(keys, items, 0, -1, false, comparer);
public static void Sort(Array keys, Array items, int index, int length)
=> SortCommon(keys, items, index, length, true, null);
public static void Sort(Array keys, Array items, int index, int length, system.collections.IComparer comparer)
=> SortCommon(keys, items, index, length, true, comparer);
//
// Sort (generic)
//
public static void Sort<T>(T[] array)
=> SortGeneric<T>(array, array, 0, -1, false, null);
public static void Sort<T>(T[] array, IComparer<T> comparer)
=> SortGeneric<T>(array, array, 0, -1, false, comparer);
public static void Sort<T>(T[] array, int index, int length)
=> SortGeneric<T>(array, array, index, length, true, null);
public static void Sort<T>(T[] array, int index, int length, IComparer<T> comparer)
=> SortGeneric<T>(array, array, index, length, true, comparer);
public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items)
=> SortGeneric<TKey>(keys, items, 0, -1, false, null);
public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, IComparer<TKey> comparer)
=> SortGeneric<TKey>(keys, items, 0, -1, false, comparer);
public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length)
=> SortGeneric<TKey>(keys, items, index, length, true, null);
public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length,
IComparer<TKey> comparer)
=> SortGeneric<TKey>(keys, items, index, length, true, comparer);
private static void SortGeneric<T>(object keys_, object items_,
int index, int length,
bool haveLength,
IComparer<T> comparer)
{
ThrowIfNull(keys_);
var keys = GetProxy(keys_);
Array items;
if (object.ReferenceEquals(keys_, items_))
items = keys;
else
{
ThrowIfNull(items_);
items = GetProxy(items_);
}
SortCommon(keys, items, index, length, haveLength,
new system.collections.GenericComparerProxy<T>(comparer));
}
//
// Sort (common method)
//
private static void SortCommon(Array keys, Array items,
int index, int length, bool haveLength,
java.util.Comparator comparer)
{
ThrowIfNull(keys);
if (! object.ReferenceEquals(keys, items)) // sorting different arrays
throw new System.PlatformNotSupportedException(); // not yet supported
if (keys.rank != 1)
throw new System.RankException();
int endIndex;
if (index < 0)
throw new System.ArgumentOutOfRangeException();
if (haveLength)
{
if (length < 0)
throw new System.ArgumentOutOfRangeException();
if (keys.len - index < length)
throw new System.ArgumentException();
endIndex = index + length;
}
else
{
endIndex = keys.len;
if (index >= endIndex)
throw new System.ArgumentException();
length = endIndex - index;
}
if (length <= 1)
return;
if (comparer == null)
{
switch (keys.arr)
{
case sbyte[] byteArray: java.util.Arrays.sort(byteArray, index, endIndex); return;
case char[] charArray: java.util.Arrays.sort(charArray, index, endIndex); return;
case short[] shortArray: java.util.Arrays.sort(shortArray, index, endIndex); return;
case int[] intArray: java.util.Arrays.sort(intArray, index, endIndex); return;
case long[] longArray: java.util.Arrays.sort(longArray, index, endIndex); return;
case float[] floatArray: java.util.Arrays.sort(floatArray, index, endIndex); return;
case double[] doubleArray: java.util.Arrays.sort(doubleArray, index, endIndex); return;
case object[] objectArray: java.util.Arrays.sort(objectArray, index, endIndex); return;
}
}
else
{
var objectArray = keys.arr as object[];
if (objectArray == null)
{
// sorting a primitive array using a comparer, not yet supported
throw new System.PlatformNotSupportedException();
}
java.util.Arrays.sort(objectArray, index, endIndex, comparer);
}
}
/*public static void Sort<T>(T[] array, Comparison<T> comparison)*/
//
// BinarySearch
//
public static int BinarySearch(Array array, object value)
{
ThrowIfNull(array);
return BinarySearch(array, 0, array.len, value, null);
}
public static int BinarySearch(Array array, int index, int length, object value)
=> BinarySearch(array, index, length, value, null);
public static int BinarySearch(Array array, object value,
System.Collections.IComparer comparer)
{
ThrowIfNull(array);
return BinarySearch(array, 0, array.len, value, comparer);
}
public static int BinarySearch(Array array, int index, int length, object value,
System.Collections.IComparer comparer)
{
ThrowIfNull(array);
if (index < 0 || length < 0)
throw new System.ArgumentOutOfRangeException();
if (array.len - index < length)
throw new System.ArgumentException();
if (array.rank != 1)
throw new System.RankException();
/*not supported
if (comparer == null || comparer == System.Collections.Comparer.Default)
{
}*/
throw new System.PlatformNotSupportedException();
}
public static int BinarySearch<T>(T[] array, T value) => BinarySearch(array, value);
public static int BinarySearch<T>(T[] array, T value,
System.Collections.Generic.IComparer<T> comparer)
{
throw new System.PlatformNotSupportedException();
}
public static int BinarySearch<T>(T[] array, int index, int length, T value)
{
throw new System.PlatformNotSupportedException();
}
public static int BinarySearch<T>(T[] array, int index, int length, T value,
System.Collections.Generic.IComparer<T> comparer)
{
throw new System.PlatformNotSupportedException();
}
//
// Clear
//
public static void Clear(Array array, int index, int length)
{
ThrowIfNull(array);
if (index < 0 || length < 0)
throw new System.IndexOutOfRangeException();
var endIndex = index + length;
if (endIndex > array.len)
throw new System.IndexOutOfRangeException();
switch (array.arr)
{
case bool[] boolArray:
java.util.Arrays.fill(boolArray, index, endIndex, false);
break;
case sbyte[] byteArray:
java.util.Arrays.fill(byteArray, index, endIndex, (sbyte) 0);
break;
case char[] charArray:
java.util.Arrays.fill(charArray, index, endIndex, (char) 0);
break;
case short[] shortArray:
java.util.Arrays.fill(shortArray, index, endIndex, (short) 0);
break;
case int[] intArray:
java.util.Arrays.fill(intArray, index, endIndex, (int) 0);
break;
case long[] longArray:
java.util.Arrays.fill(longArray, index, endIndex, (long) 0);
break;
case float[] floatArray:
java.util.Arrays.fill(floatArray, index, endIndex, (float) 0);
break;
case double[] doubleArray:
java.util.Arrays.fill(doubleArray, index, endIndex, (double) 0);
break;
case object[] objectArray:
if (system.RuntimeType.IsValueClass(
((java.lang.Object) (object) objectArray)
.getClass().getComponentType()))
{
for (; length-- > 0; index++)
((ValueMethod) (ValueType) objectArray[index]).Clear();
}
else
{
java.util.Arrays.fill(objectArray, index, endIndex, null);
}
break;
default:
throw new System.InvalidOperationException();
}
}
//
// Fill
//
public static void Fill<T>(T[] array, T value)
{
ThrowIfNull(array);
FillCommon(array, (object) value, 0, java.lang.reflect.Array.getLength(array));
}
public static void Fill<T>(T[] array, T value, int startIndex, int count)
{
ThrowIfNull(array);
if (startIndex < 0 || count < 0)
throw new System.IndexOutOfRangeException();
var endIndex = startIndex + count;
if (endIndex > java.lang.reflect.Array.getLength(array))
throw new System.IndexOutOfRangeException();
FillCommon(array, (object) value, startIndex, endIndex);
}
private static void FillCommon(object array, object value, int startIndex, int endIndex)
{
switch (array)
{
case bool[] boolArray:
java.util.Arrays.fill(boolArray, startIndex, endIndex, (bool) value);
break;
case sbyte[] byteArray:
java.util.Arrays.fill(byteArray, startIndex, endIndex, (sbyte) value);
break;
case char[] charArray:
java.util.Arrays.fill(charArray, startIndex, endIndex, (char) value);
break;
case short[] shortArray:
java.util.Arrays.fill(shortArray, startIndex, endIndex, (short) value);
break;
case int[] intArray:
java.util.Arrays.fill(intArray, startIndex, endIndex, (int) value);
break;
case long[] longArray:
java.util.Arrays.fill(longArray, startIndex, endIndex, (long) value);
break;
case float[] floatArray:
java.util.Arrays.fill(floatArray, startIndex, endIndex, (float) value);
break;
case double[] doubleArray:
java.util.Arrays.fill(doubleArray, startIndex, endIndex, (double) value);
break;
case object[] objectArray:
if (system.RuntimeType.IsValueClass(
((java.lang.Object) array).getClass().getComponentType()))
{
ValueType v = (ValueType) value;
for (; startIndex < endIndex; startIndex++)
((ValueMethod) v).CopyTo((ValueType) objectArray[startIndex]);
}
else
{
java.util.Arrays.fill(objectArray, startIndex, endIndex, value);
}
break;
default:
throw new System.InvalidOperationException();
}
}
//
// Initialize
//
public void Initialize()
{
var type = ((java.lang.Object) arr).getClass().getComponentType();
if (system.RuntimeType.IsValueClass(type))
{
var objectArray = (object[]) arr;
for (int idx = 0; idx < len; idx++)
((ValueMethod) (ValueType) objectArray[idx]).Clear();
}
}
/*public static bool TrueForAll<T>(T[] array, Predicate<T> match)
public static void Reverse(Array array)
public static void Reverse(Array array, int index, int length)
public static void Resize<T> (ref T[] array, int newSize)
public static void ForEach<T> (T[] array, Action<T> action);
public static bool Exists<T> (T[] array, Predicate<T> match);
public static T[] Empty<T> ();
public static TOutput[] ConvertAll<TInput,TOutput> (TInput[] array, Converter<TInput,TOutput> converter);
//LastIndexOf, Find, FindAll, FindIndex, FindLast, CreateInstance*/
//
// IList interface
//
bool IList.Contains(object value) => IndexOf(this, value, 0, len) >= 0;
int IList.IndexOf(object value) => IndexOf(this, value);
void IList.Clear() => Clear(this, 0, len);
// Array does not support addition and removal
int IList.Add(object value) => throw new System.NotSupportedException();
void IList.Insert(int index, object value) => throw new System.NotSupportedException();
void IList.Remove(object value) => throw new System.NotSupportedException();
void IList.RemoveAt(int index) => throw new System.NotSupportedException();
object IList.this[int index] {
get => Load(arr, index);
set => SetValue(value, index);
}
public bool IsReadOnly => false;
public bool IsFixedSize => true;
public bool IsSynchronized => false;
public object SyncRoot => arr;
//
// IStructuralComparable, IStructuralEquatable
//
int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null)
return 1;
Array otherArray = other as Array;
if (otherArray == null || len != otherArray.len)
throw new System.ArgumentException();
for (int i = 0; i < len; i++)
{
var c = comparer.Compare(Load(arr, i), Load(otherArray.arr, i));
if (c != 0)
return c;
}
return 0;
}
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null)
return false;
if (object.ReferenceEquals(this, other))
return true;
Array otherArray = other as Array;
if (otherArray == null || len != otherArray.len)
return false;
for (int i = 0; i < len; i++)
{
if (! comparer.Equals(Load(arr, i), Load(otherArray.arr, i)))
return false;
}
return true;
}
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
ThrowIfNull(comparer);
int hash = 0;
for (int i = (len >= 8 ? len - 8 : 0); i < len; i++)
{
// same calculation as in reference implementation of System.Array
hash = ((hash << 5) + hash) ^ (comparer.GetHashCode(Load(arr, i)));
}
return hash;
}
//
// Helper methods for array initialization and access
//
public static object New(int count, System.Type type)
{
var runtimeType = (system.RuntimeType) type;
var cls = runtimeType.JavaClassForArray();
var array = java.lang.reflect.Array.newInstance(cls, count);
if (cls.getComponentType() != null)
MarkJagged(array);
else if (system.RuntimeType.IsValueClass(cls))
{
Initialize(array, runtimeType,
(system.ValueType) runtimeType.CallConstructor(true),
1);
}
return array;
}
public static void Initialize(object array, System.Type type, system.ValueType model, int dims)
{
if (model == null)
model = (system.ValueType) (((system.RuntimeType) type).CallConstructor(true));
if (dims == 1)
InitSingle((object[]) array, model);
else
InitMulti((object[]) array, model, dims);
void InitSingle(object[] array, system.ValueType model)
{
int n = array.Length;
if (n > 0)
{
java.lang.reflect.Array.set(array, 0, model);
for (int i = 1; i < n; i++)
java.lang.reflect.Array.set(array, i, ((ValueMethod) model).Clone());
}
}
void InitMulti(object[] array, system.ValueType model, int dims)
{
int n = array.Length;
if (dims == 1 && n > 0)
{
for (int i = 0; i < n; i++)
java.lang.reflect.Array.set(array, i, ((ValueMethod) model).Clone());
}
else if (dims > 1)
{
for (int i = 0; i < n; i++)
InitMulti((object[]) array[i], model, dims - 1);
}
}
}
public static void Store(object array, int index, object value)
{
try
{
switch (array)
{
case bool[] boolArray:
boolArray[index] = ((Boolean) value).Get() != 0 ? true : false;
break;
case sbyte[] byteArray:
byteArray[index] = (sbyte) ((SByte) value).Get();
break;
case char[] charArray:
charArray[index] = (char) ((Char) value).Get();
break;
case short[] shortArray:
shortArray[index] = (short) ((Int16) value).Get();
break;
case int[] intArray:
intArray[index] = (int) ((Int32) value).Get();
break;
case long[] longArray:
longArray[index] = (long) ((Int64) value).Get();
break;
case float[] floatArray:
floatArray[index] = (float) ((Single) value).Get();
break;
case double[] doubleArray:
doubleArray[index] = (double) ((Double) value).Get();
break;
case ValueType[] valueArray:
// this will throw invalid cast if the types do not match.
// but note that it will succeed with generic instance types
// even when the type arguments do not match.
((ValueMethod) (ValueType) value).CopyTo(valueArray[index]);
break;
case object[] objectArray:
// note that if a value type is being stored, we assume
// that it was already boxed, and we don't clone it here
if (value is system.Reference valueRef)
value = valueRef.Get();
objectArray[index] = value;
break;
}
}
catch (System.Exception exc)
{
throw new System.ArrayTypeMismatchException("", exc);
}
}
public static object Load(object array, int index)
{
// if array of a primitive type, returns a boxed copy of array[index].
// if array of a value type or reference type, returns array[index].
switch (array)
{
case bool[] boolArray: return Boolean.Box(boolArray[index] ? 1 : 0);
case sbyte[] byteArray: return SByte.Box(byteArray[index]);
case char[] charArray: return Char.Box(charArray[index]);
case short[] shortArray: return Int16.Box(shortArray[index]);
case int[] intArray: return Int32.Box(intArray[index]);
case long[] longArray: return Int64.Box(longArray[index]);
case float[] floatArray: return Single.Box(floatArray[index]);
case double[] doubleArray: return Double.Box(doubleArray[index]);
case object[] objectArray: return objectArray[index];
}
throw new System.IndexOutOfRangeException();
}
public static ValueType Box(object array, int index)
{
// called from CodeArrays::Address(),
// array parameter is always a single-dim array
// returns a boxed reference into an array
switch (array)
{
case bool[] boolArray: return Boolean.Box(boolArray, index);
case sbyte[] byteArray: return SByte.Box(byteArray, index);
case char[] charArray: return Char.Box(charArray, index);
case short[] shortArray: return Int16.Box(shortArray, index);
case int[] intArray: return Int32.Box(intArray, index);
case long[] longArray: return Int64.Box(longArray, index);
case float[] floatArray: return Single.Box(floatArray, index);
case double[] doubleArray: return Double.Box(doubleArray, index);
case ValueType[] valueArray: return valueArray[index];
case object[] objectArray: return Reference.Box(objectArray, index);
}
throw new System.IndexOutOfRangeException();
}
//
// CheckCast
//
public static object CheckCast(object array, java.lang.Class castToClass, bool @throw)
{
if (array is object[])
{
var elemClass = ((java.lang.Object) array).getClass().getComponentType();
if (elemClass != null)
{
if (system.RuntimeType.IsValueClass(elemClass))
{
if (elemClass == castToClass)
return array;
}
else if (castToClass.isAssignableFrom(elemClass))
return array;
}
}
if (array != null && @throw)
{
GenericType.ThrowInvalidCastException(array,
RuntimeType.GetType(castToClass).MakeArrayType());
}
return null;
}
public static object CheckCast(object array, System.Type castToType, bool @throw)
{
if (array != null)
{
if (array is system.Array.ProxySyncRoot proxyArray)
array = proxyArray.SyncRoot;
var elemClass = ((java.lang.Object) array).getClass().getComponentType();
if (elemClass != null)
{
var elemType = RuntimeType.GetType(elemClass);
if (system.RuntimeType.IsValueClass(elemClass))
{
if (object.ReferenceEquals(elemType, castToType))
return array;
}
else if (elemClass.isPrimitive())
{
var castToClass = ((RuntimeType) castToType).JavaClassForArray();
if (castToClass == elemClass)
return array;
}
else
{
if (castToType.IsAssignableFrom(elemType))
return array;
}
}
if (@throw)
GenericType.ThrowInvalidCastException(array, castToType.MakeArrayType());
}
return null;
}
//
// IEnumerator
//
public IEnumerator GetEnumerator() => new Enumerator(arr, len, Rank);
[System.Serializable]
public class Enumerator : IEnumerator, System.ICloneable
{
[java.attr.RetainType] private object arr;
[java.attr.RetainType] private int len;
[java.attr.RetainType] private int rank;
[java.attr.RetainType] private int idx;
[java.attr.RetainType] private Enumerator sub;
public Enumerator(object _arr, int _len, int _rank)
{
arr = _arr;
len = _len;
rank = _rank;
idx = -1;
}
public bool MoveNext()
{
for (;;)
{
if (sub != null)
{
if (sub.MoveNext())
return true;
sub = null;
}
int next = idx + 1;
if (next >= len)
return false;
idx = next;
if (rank > 1)
{
var subArr = java.lang.reflect.Array.get(arr, idx);
sub = new Enumerator(subArr,
java.lang.reflect.Array.getLength(subArr),
rank - 1);
continue;
}
return true;
}
}
public object Current
{
get
{
if (sub != null)
return sub.Current;
if (idx < 0)
throw new System.InvalidOperationException();
if (idx >= len)
throw new System.InvalidOperationException();
return Load(arr, idx);
}
}
public void Reset()
{
idx = -1;
if (sub != null)
sub = null;
}
public object Clone() => MemberwiseClone();
}
//
// GetProxy
//
public static object GetProxy(object obj, System.Type castToType, bool callCast)
{
var objClass = ((java.lang.Object) obj).getClass();
if (objClass.isArray())
{
int ok = 0;
// check if asking to cast the object to System.Array or one of
// the non-generic interfaces that an array should implement
if ( object.ReferenceEquals(castToType, cachedArrayType)
|| object.ReferenceEquals(castToType, cachedICloneable)
|| object.ReferenceEquals(castToType, cachedPlainIEnumerable)
|| object.ReferenceEquals(castToType, cachedPlainICollection)
|| object.ReferenceEquals(castToType, cachedPlainIList)
|| object.ReferenceEquals(castToType, cachedIStructuralComparable)
|| object.ReferenceEquals(castToType, cachedIStructuralEquatable))
{
ok = 1; // non-generic
}
else if (castToType.IsConstructedGenericType)
{
// otherwise check if asking to cast the object to one of the
// generic interfaces that an array should implement. later on,
// the call to IGenericObject.TryCast() verifies the actual
// generic parameters types (see the check for ok == 2, below).
var genericDef = castToType.GetGenericTypeDefinition();
if ( object.ReferenceEquals(genericDef, cachedGenericIEnumerable)
|| object.ReferenceEquals(genericDef, cachedGenericICollection)
|| object.ReferenceEquals(genericDef, cachedGenericIList)
|| object.ReferenceEquals(genericDef, cachedGenericIReadOnlyCollection)
|| object.ReferenceEquals(genericDef, cachedGenericIReadOnlyList))
{
ok = 2; // generic
}
}
if (ok != 0)
{
var proxy = ArrayProxyCache.GetOrAdd(obj, null);
if (object.ReferenceEquals(proxy, null))
{
// create the Array.Proxy<T> object, where T is the array element.
// note that we use reflection to call the constructor, which takes
// one additional hidden parameter for the generic type.
var newProxyObject =
ProxyConstructor.newInstance(new object[] {
obj, GetArrayElementType(obj, objClass) });
proxy = ArrayProxyCache.GetOrAdd(obj, newProxyObject);
}
if (ok == 2)
{
// if we are getting a proxy for a generic interface, we must now
// make sure the proxy object supports the specific generic type.
var genericProxy = ((IGenericObject) proxy).TryCast(castToType);
if (callCast)
proxy = genericProxy;
else if (genericProxy == null)
proxy = null;
}
return proxy;
}
}
else if (objClass == (java.lang.Class) typeof(java.lang.String))
{
// string can be cast to system.collections.IEnumerable,
// system.ICloneable, and, specifically in this implementation,
// also to system.Array (see CodeCall::ShouldCastArrayArgument
// and CodeArrays::MaybeGetProxy methods)
if ( object.ReferenceEquals(castToType, cachedArrayType)
|| object.ReferenceEquals(castToType, cachedICloneable)
|| object.ReferenceEquals(castToType, cachedPlainIEnumerable)
|| object.ReferenceEquals(castToType, cachedGenericIEnumerable))
{
return GetProxy( ((java.lang.String) obj).toCharArray(),
castToType, callCast);
}
if (castToType.IsConstructedGenericType)
{
// castable to system.collections.generic.IEnumerable<char>
var genericDef = castToType.GetGenericTypeDefinition();
if (object.ReferenceEquals(genericDef, cachedGenericIEnumerable))
{
return GetProxy( ((java.lang.String) obj).toCharArray(),
castToType, callCast);
}
}
return String.CreateWrapper(obj, castToType);
}
return null;
}
public static Array GetProxy(object obj)
{
var proxy = GetProxy(obj, cachedArrayType, false);
if (proxy == null)
GenericType.ThrowInvalidCastException(obj, cachedArrayType);
// because 'proxy' is of type 'object', casting it to directly to
// System.Array would generate code that calls GetProxy (see also
// CodeCall.Translate_Return and GenericUtil.ShouldCallGenericCast),
// we avoid this by casting it first to ProxySyncRoot
return (Array) (Array.ProxySyncRoot) proxy;
}
private static System.Type GetArrayElementType(
object arrayObject, java.lang.Class arrayClass)
{
// an array object does not keep generic type information
// for its component, so a Tuple<int,string>[] array becomes
// just Tuple$$2[]. casting to IEnumerable<Tuple<int,string>>
// would fail. below, we try to extract the concrete generic
// type from the first element in the array.
//
// first, check if the array component is a non-concrete
// generic type, and that the array has at least one element.
var elementType = system.RuntimeType.GetType(
arrayClass.getComponentType());
if ( elementType.IsGenericTypeDefinition
&& java.lang.reflect.Array.getLength(arrayObject) > 0)
{
// extract the first element, and make sure it is the same
// class as the array (so same number of generic argument)
var element0 = java.lang.reflect.Array.get(arrayObject, 0);
if ( (! object.ReferenceEquals(element0, null))
&& element0.GetType() is RuntimeType element0Type
&& ((RuntimeType) elementType).JavaClassForArray()
== element0Type.JavaClassForArray())
{
// return a concrete generic type
elementType = elementType.MakeGenericType(
element0Type.GetGenericArguments());
}
}
return elementType;
}
public static void MarkJagged(object obj)
{
((Array) GetProxy(obj, cachedArrayType, false)).jagged = true;
}
[java.attr.RetainType] private static readonly System.Type cachedArrayType =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Array));
[java.attr.RetainType] private static readonly System.Type cachedICloneable =
system.RuntimeType.GetType((java.lang.Class) typeof(System.ICloneable));
[java.attr.RetainType] private static System.Type cachedPlainIEnumerable =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.IEnumerable));
[java.attr.RetainType] private static System.Type cachedPlainICollection =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.ICollection));
[java.attr.RetainType] private static System.Type cachedPlainIList =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.IList));
[java.attr.RetainType] private static System.Type cachedIStructuralComparable =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.IStructuralComparable));
[java.attr.RetainType] private static System.Type cachedIStructuralEquatable =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.IStructuralEquatable));
[java.attr.RetainType] private static System.Type cachedGenericIEnumerable =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.Generic.IEnumerable<>));
[java.attr.RetainType] private static System.Type cachedGenericICollection =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.Generic.ICollection<>));
[java.attr.RetainType] private static System.Type cachedGenericIList =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.Generic.IList<>));
[java.attr.RetainType] private static System.Type cachedGenericIReadOnlyCollection =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.Generic.IReadOnlyCollection<>));
[java.attr.RetainType] private static System.Type cachedGenericIReadOnlyList =
system.RuntimeType.GetType((java.lang.Class) typeof(System.Collections.Generic.IReadOnlyList<>));
#pragma warning disable 0436
[java.attr.RetainType] private static readonly java.lang.reflect.Constructor ProxyConstructor =
(java.lang.reflect.Constructor) (object)
(((java.lang.Class) typeof(Array.Proxy<>)).getDeclaredConstructors())[0];
#pragma warning restore 0436
[java.attr.RetainType] private static readonly system.runtime.compilerservices.ConditionalWeakTable ArrayProxyCache
= new system.runtime.compilerservices.ConditionalWeakTable();
public interface ProxySyncRoot
{
// this interface is used by system.threading.Monitor to identify
// an array proxy object, and get a reference to the actual array
object SyncRoot { get; }
}
public sealed class Proxy<T> : Array, IList<T>, IReadOnlyList<T>, ProxySyncRoot
{
public Proxy(object _arr) : base(_arr) {}
IEnumerator<T> IEnumerable<T>.GetEnumerator() => new GenericEnumerator(arr, len, Rank);
[System.Serializable]
public class GenericEnumerator : system.Array.Enumerator, IEnumerator<T>
{
public GenericEnumerator(object _arr, int _len, int _rank) : base(_arr, _len, _rank) {}
T IEnumerator<T>.Current => (T) base.Current;
void System.IDisposable.Dispose() {}
}
bool ICollection<T>.Contains(T value) => IndexOf(this, value, 0, len) >= 0;
int IList<T>.IndexOf(T value) => IndexOf(this, value);
void ICollection<T>.CopyTo(T[] array, int index)
{
if (Rank != 1)
throw new System.ArgumentException();
base.CopyTo(array, index);
}
// Array does not support addition and removal
void ICollection<T>.Add(T value) => throw new System.NotSupportedException("Array");
void ICollection<T>.Clear() => throw new System.NotSupportedException("Array");
bool ICollection<T>.Remove (T value) => throw new System.NotSupportedException("Array");
void IList<T>.Insert(int index, T value) => throw new System.NotSupportedException("Array");
void IList<T>.RemoveAt(int index) => throw new System.NotSupportedException("Array");
public int Count => len; // implements ICollection, IReadOnlyCollection
public T this[int index] { // implements IList, IReadOnlyList
get => (T) Load(arr, index);
set => SetValue(value, index);
}
}
//
// static initializer
//
static Array()
{
// translate exception java.lang.NegativeArraySizeException
// into System.ArgumentOutOfRangeException
system.Util.DefineException(
(java.lang.Class) typeof(java.lang.NegativeArraySizeException),
(exc) => new System.ArgumentOutOfRangeException(exc.getMessage())
);
system.Util.DefineException(
(java.lang.Class) typeof(java.lang.IndexOutOfBoundsException),
(exc) => new System.IndexOutOfRangeException(exc.getMessage())
);
system.Util.DefineException(
(java.lang.Class) typeof(java.lang.NegativeArraySizeException),
(exc) => new System.OverflowException(
"Array dimensions exceeded supported range.")
);
/*system.Util.DefineException(
(java.lang.Class) typeof(java.util.ConcurrentModificationException),
(exc) => new System.InvalidOperationException(exc.getMessage())
);*/
system.Util.DefineException(
(java.lang.Class) typeof(java.lang.ArrayStoreException),
(exc) => new System.ArrayTypeMismatchException(exc.getMessage())
);
}
}
}