From 28a84d4799ac6c6cfadda16cd54afa44aedd711f Mon Sep 17 00:00:00 2001
From: spaceflint <>
Date: Thu, 10 Sep 2020 07:56:54 +0300
Subject: [PATCH] Incremental changes
---
Baselib/Baselib.csproj | 1 +
Baselib/src/System/AppDomain.cs | 67 +-
Baselib/src/System/Array.cs | 4 +-
Baselib/src/System/Boolean.cs | 40 +-
Baselib/src/System/Byte.cs | 58 +-
Baselib/src/System/Char.cs | 38 +-
Baselib/src/System/Double.cs | 34 +-
Baselib/src/System/GenericType.cs | 21 +-
.../src/System/Globalization/CompareInfo.cs | 189 +++++-
.../src/System/Globalization/CultureInfo.cs | 4 +
Baselib/src/System/Globalization/TextInfo.cs | 85 +++
Baselib/src/System/Int16.cs | 12 +-
Baselib/src/System/Int32.cs | 18 +-
Baselib/src/System/Int64.cs | 56 +-
.../src/System/Reflection/CustomAttribute.cs | 8 +
.../src/System/Reflection/RuntimeAssembly.cs | 83 ++-
.../src/System/Reflection/RuntimeModule.cs | 34 +-
Baselib/src/System/Runtime/RuntimeHelpers.cs | 3 +
Baselib/src/System/Single.cs | 36 +-
Baselib/src/System/String.cs | 637 +++++++++++++++---
.../System/Text/RegularExpressions/Match.cs | 2 +-
.../System/Text/RegularExpressions/Regex.cs | 87 +++
Baselib/system.filter | 2 +
CilToJava/src/CilMethod.cs | 23 +
CilToJava/src/CodeArray.cs | 6 +-
CilToJava/src/CodeCall.cs | 3 +
CilToJava/src/CodeCompare.cs | 10 +-
CilToJava/src/CodeMisc.cs | 20 +-
CilToJava/src/GenericUtil.cs | 16 +-
.../src/{TestCompareInfo.cs => TestString.cs} | 137 +++-
USAGE.md | 2 -
31 files changed, 1504 insertions(+), 232 deletions(-)
create mode 100644 Baselib/src/System/Globalization/TextInfo.cs
create mode 100644 Baselib/src/System/Reflection/CustomAttribute.cs
rename Tests/src/{TestCompareInfo.cs => TestString.cs} (56%)
diff --git a/Baselib/Baselib.csproj b/Baselib/Baselib.csproj
index ab1ff3b..712ea2b 100644
--- a/Baselib/Baselib.csproj
+++ b/Baselib/Baselib.csproj
@@ -17,6 +17,7 @@
+
diff --git a/Baselib/src/System/AppDomain.cs b/Baselib/src/System/AppDomain.cs
index 1fe9ce0..d5a3842 100644
--- a/Baselib/src/System/AppDomain.cs
+++ b/Baselib/src/System/AppDomain.cs
@@ -3,7 +3,6 @@ namespace system
{
public sealed class AppDomain
{
-
public static AppDomain CurrentDomain
=> System.Threading.LazyInitializer.EnsureInitialized(ref theInstance);
@@ -18,5 +17,71 @@ namespace system
}
private static AppDomain theInstance;
+
+
+
+ //
+ // GetAssemblies
+ //
+
+ public System.Reflection.Assembly[] GetAssemblies()
+ {
+ var classLoaderObject =
+ ((java.lang.Object) (object) this).getClass().getClassLoader();
+ InitClassLoaderFields(classLoaderObject);
+ var domains = (java.util.Set) Util.JavaUnsafe.getObject(
+ classLoaderObject, _DomainsOffset);
+ int n = domains.size();
+ int i = 0;
+ var assemblies = new System.Reflection.Assembly[n];
+ for (var it = domains.iterator(); it.hasNext() && i < n; i++)
+ {
+ var domain = (java.security.ProtectionDomain) it.next();
+ assemblies[i] =
+ system.reflection.RuntimeAssembly.GetAssemblyForDomain(domain);
+ }
+ return assemblies;
+ }
+
+ //
+ // GetClassesInAssembly
+ //
+
+ public java.util.Vector GetAllClasses()
+ {
+ var classLoaderObject =
+ ((java.lang.Object) (object) this).getClass().getClassLoader();
+ InitClassLoaderFields(classLoaderObject);
+ return (java.util.Vector) Util.JavaUnsafe.getObject(
+ classLoaderObject, _ClassesOffset);
+ }
+
+ //
+ // InitClassLoaderFields
+ //
+
+ private void InitClassLoaderFields(java.lang.ClassLoader classLoaderObject)
+ {
+ if (_ClassesOffset == -1 || _DomainsOffset == -1)
+ {
+ var classLoaderClass =
+ ((java.lang.Object) (object) classLoaderObject).getClass();
+ for (;;)
+ {
+ if (classLoaderClass ==
+ (java.lang.Class) typeof(java.lang.ClassLoader))
+ break;
+ classLoaderClass = classLoaderClass.getSuperclass();
+ }
+
+ _ClassesOffset = Util.JavaUnsafe.objectFieldOffset(
+ classLoaderClass.getDeclaredField("classes"));
+ _DomainsOffset = Util.JavaUnsafe.objectFieldOffset(
+ classLoaderClass.getDeclaredField("domains"));
+ }
+ }
+
+ [java.attr.RetainType] static long _ClassesOffset = -1;
+ [java.attr.RetainType] static long _DomainsOffset = -1;
}
}
diff --git a/Baselib/src/System/Array.cs b/Baselib/src/System/Array.cs
index ecbc643..77a17a2 100644
--- a/Baselib/src/System/Array.cs
+++ b/Baselib/src/System/Array.cs
@@ -1427,10 +1427,10 @@ namespace system
(exc) => new System.IndexOutOfRangeException(exc.getMessage())
);
- system.Util.DefineException(
+ /*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),
diff --git a/Baselib/src/System/Boolean.cs b/Baselib/src/System/Boolean.cs
index f9e0c9f..7cd832c 100644
--- a/Baselib/src/System/Boolean.cs
+++ b/Baselib/src/System/Boolean.cs
@@ -3,7 +3,8 @@ namespace system
{
public class Boolean : system.ValueType, system.ValueMethod, java.lang.Cloneable,
- System.IConvertible
+ System.IComparable, System.IComparable,
+ System.IConvertible, System.IEquatable
{
[java.attr.RetainType] protected int v;
@@ -36,6 +37,33 @@ namespace system
public override string ToString() => Get() != 0 ? "True" : "False";
+ public string ToString(System.IFormatProvider provider) => ToString();
+
+
+
+ // System.IEquatable
+ public bool Equals(bool v) => (Get() != 0 ? v : (! v));
+
+
+
+ // System.IComparable
+ public virtual int CompareTo(object obj)
+ {
+ if (obj is Boolean objBoolean)
+ return CompareTo(objBoolean.Get() != 0 ? true : false);
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
+ throw new System.ArgumentException();
+ }
+
+ // System.IComparable
+ public int CompareTo(bool b)
+ {
+ return (Get() == 0) ? (b ? -1 : 0)
+ : (b ? 0 : 1);
+ }
+
+
void ValueMethod.Clear() => Set(0);
void ValueMethod.CopyTo(ValueType into) => ((Boolean) into).Set(Get());
@@ -63,8 +91,6 @@ namespace system
// CodeNumber.Indirection methods
//
-
-
public int Get_U8() => (byte) Get();
public int Get_I8() => Get();
public void Set_I8(int v) => Set(v);
@@ -92,8 +118,6 @@ namespace system
// IConvertible
//
-
-
public System.TypeCode GetTypeCode() => System.TypeCode.Boolean;
bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
@@ -123,11 +147,9 @@ namespace system
System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
=> System.Convert.ToDecimal(Get());
System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
- => throw new System.InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo_Int32_DateTime"));
- string System.IConvertible.ToString(System.IFormatProvider provider)
- => ToString();
+ => throw new System.InvalidCastException();
object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
- => null;//System.Convert.DefaultToType((System.IConvertible) this, type, provider);
+ => system.Convert.DefaultToType((System.IConvertible) this, type, provider);
diff --git a/Baselib/src/System/Byte.cs b/Baselib/src/System/Byte.cs
index e0922b1..6d25168 100644
--- a/Baselib/src/System/Byte.cs
+++ b/Baselib/src/System/Byte.cs
@@ -2,7 +2,8 @@
namespace system
{
- public class SByte : system.ValueType, system.ValueMethod,
+ public class SByte : system.ValueType, system.ValueMethod, java.lang.Cloneable,
+ System.IComparable, System.IComparable,
System.IConvertible, System.IEquatable, System.IFormattable
{
@@ -44,8 +45,31 @@ namespace system
{
if (string.IsNullOrEmpty(format))
return ToString();
- return ParseNumbers.FormatNumber(
- (java.lang.String) (object) format, provider, java.lang.Integer.valueOf(Get()));
+ return ParseNumbers.FormatNumber((java.lang.String) (object) format, provider,
+ java.lang.Integer.valueOf(Get()));
+ }
+
+ public string ToString(string format) => ToString(format, null);
+
+ public string ToString(System.IFormatProvider provider) => ToString();
+
+
+
+ // System.IComparable
+ public virtual int CompareTo(object obj)
+ {
+ if (obj is SByte objSByte)
+ return CompareTo((sbyte) objSByte.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
+ throw new System.ArgumentException();
+ }
+
+ // System.IComparable
+ public int CompareTo(sbyte b)
+ {
+ var a = Get();
+ return (a < b ? -1 : a > b ? 1 : 0);
}
@@ -76,8 +100,6 @@ namespace system
// CodeNumber.Indirection methods
//
-
-
public int Get_U8() => (byte) Get();
public int Get_I8() => (sbyte) Get();
public void Set_I8(int v) => Set((int) ((byte) v | ((uint) Get() & (uint) 0xFFFFFF00)));
@@ -105,8 +127,6 @@ namespace system
// IConvertible
//
-
-
public virtual System.TypeCode GetTypeCode() => System.TypeCode.SByte;
bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
@@ -136,11 +156,9 @@ namespace system
System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
=> System.Convert.ToDecimal(Get());
System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
- => throw new System.InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo_Int32_DateTime"));
- string System.IConvertible.ToString(System.IFormatProvider provider)
- => ToString();
+ => throw new System.InvalidCastException();
object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
- => null;//System.Convert.DefaultToType((System.IConvertible) this, type, provider);
+ => system.Convert.DefaultToType((System.IConvertible) this, type, provider);
@@ -173,7 +191,7 @@ namespace system
#pragma warning disable 0659
- public class Byte : SByte, System.IEquatable
+ public class Byte : SByte, System.IComparable, System.IEquatable
{
new public static Byte Box(int v) => new Byte() { v = (sbyte) v };
@@ -188,12 +206,26 @@ namespace system
return (objByte != null && objByte.Get() == Get());
}
- // System.IEquatable
+ // System.IEquatable
public bool Equals(byte v) => v == Get();
public override System.TypeCode GetTypeCode() => System.TypeCode.Byte;
+ // System.IComparable
+ public override int CompareTo(object obj)
+ {
+ if (obj is Byte objByte)
+ return CompareTo((byte) objByte.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
+ throw new System.ArgumentException();
+ }
+ // System.IComparable
+ public int CompareTo(byte v) => CompareTo((sbyte) Get(), (sbyte) v);
+
+ public static int CompareTo(sbyte a, sbyte b)
+ => a == b ? 0 : (a & 0xFF) < (b & 0xFF) ? -1 : 1;
//
diff --git a/Baselib/src/System/Char.cs b/Baselib/src/System/Char.cs
index 4f94049..a3ab8f3 100644
--- a/Baselib/src/System/Char.cs
+++ b/Baselib/src/System/Char.cs
@@ -2,7 +2,8 @@
namespace system
{
- public class Char : system.ValueType, system.ValueMethod,
+ public class Char : system.ValueType, system.ValueMethod, java.lang.Cloneable,
+ System.IComparable, System.IComparable,
System.IConvertible, System.IEquatable
{
@@ -41,13 +42,27 @@ namespace system
public override string ToString() => java.lang.String.valueOf((char) Get());
- /*public string ToString(IFormatProvider provider)
- {
- return java.lang.String.valueOf(Get(this));
- }*/
+ public string ToString(System.IFormatProvider provider) => ToString();
public static string ToString(char c) => java.lang.String.valueOf(c);
+
+
+ // System.IComparable
+ public virtual int CompareTo(object obj)
+ {
+ if (obj is Char objChar)
+ return CompareTo(objChar.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
+ throw new System.ArgumentException();
+ }
+
+ // System.IComparable
+ public int CompareTo(char b) => Get() - ((int) b);
+
+
+
//public static char ToUpper(char c, system.globalization.CultureInfo cultureInfo)
public static char ToUpperInvariant(char c) =>
@@ -66,8 +81,7 @@ namespace system
static char StringCharAt(string str, int idx)
{
- if (str == null)
- throw new System.ArgumentNullException();
+ ThrowHelper.ThrowIfNull(str);
if ((uint) idx >= (uint) str.Length)
throw new System.ArgumentOutOfRangeException();
return str[idx];
@@ -97,8 +111,6 @@ namespace system
// CodeNumber.Indirection methods
//
-
-
public int Get_U8() => (byte) Get();
public int Get_I8() => Get();
public void Set_I8(int v) => Set(v);
@@ -122,8 +134,6 @@ namespace system
// IConvertible
//
-
-
public System.TypeCode GetTypeCode() => System.TypeCode.Char;
bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
@@ -153,11 +163,9 @@ namespace system
System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
=> System.Convert.ToDecimal(Get());
System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
- => throw new System.InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo_Int32_DateTime"));
- string System.IConvertible.ToString(System.IFormatProvider provider)
- => ToString();
+ => throw new System.InvalidCastException();
object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
- => null;//System.Convert.DefaultToType((System.IConvertible) this, type, provider);
+ => system.Convert.DefaultToType((System.IConvertible) this, type, provider);
diff --git a/Baselib/src/System/Double.cs b/Baselib/src/System/Double.cs
index 10c04c6..e8b6829 100644
--- a/Baselib/src/System/Double.cs
+++ b/Baselib/src/System/Double.cs
@@ -2,7 +2,8 @@
namespace system
{
- public class Double : system.ValueType, system.ValueMethod,
+ public class Double : system.ValueType, system.ValueMethod, java.lang.Cloneable,
+ System.IComparable, System.IComparable,
System.IConvertible, System.IEquatable, System.IFormattable
{
@@ -56,6 +57,29 @@ namespace system
(java.lang.String) (object) format, provider, java.lang.Double.valueOf(Get()));
}
+ public string ToString(string format) => ToString(format, null);
+
+ public string ToString(System.IFormatProvider provider) => ToString();
+
+
+
+ // System.IComparable
+ public virtual int CompareTo(object obj)
+ {
+ if (obj is Double objDouble)
+ return CompareTo(objDouble.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
+ throw new System.ArgumentException();
+ }
+
+ // System.IComparable
+ public int CompareTo(double b)
+ {
+ var a = Get();
+ return (a < b ? -1 : a > b ? 1 : 0);
+ }
+
void ValueMethod.Clear() => Set(0);
@@ -119,8 +143,6 @@ namespace system
// IConvertible
//
-
-
public System.TypeCode GetTypeCode() => System.TypeCode.Double;
bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
@@ -150,11 +172,9 @@ namespace system
System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
=> System.Convert.ToDecimal(Get());
System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
- => throw new System.InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo_Int32_DateTime"));
- string System.IConvertible.ToString(System.IFormatProvider provider)
- => ToString();
+ => throw new System.InvalidCastException();
object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
- => null;//System.Convert.DefaultToType((System.IConvertible) this, type, provider);
+ => system.Convert.DefaultToType((System.IConvertible) this, type, provider);
diff --git a/Baselib/src/System/GenericType.cs b/Baselib/src/System/GenericType.cs
index c3c83de..820eba2 100644
--- a/Baselib/src/System/GenericType.cs
+++ b/Baselib/src/System/GenericType.cs
@@ -121,18 +121,27 @@ namespace system
if (genericObject.TryCast(castToType) != null)
return obj;
if (obj is system.Array.ProxySyncRoot objArray)
- {
- var proxy = Array.GetProxy(objArray.SyncRoot, castToType, false);
- if (proxy != null)
- return proxy;
- }
+ obj = objArray.SyncRoot;
}
- else
+
+ if (obj != null)
{
+ // handle the cases where ShouldCallGenericCast in GenericUtil
+ // identifies an interface that should be implemented by an
+ // array object, or a string
var proxy = Array.GetProxy(obj, castToType, false);
if (proxy != null)
return proxy;
+
+ // check if the object (which might not be array or string)
+ // can actually be cast to the target type
+ if ( (! castToType.IsGenericType)
+ && castToType is RuntimeType castToRuntimeType
+ && castToRuntimeType.JavaClassForArray()
+ .isAssignableFrom(((java.lang.Object) obj).getClass()))
+ return obj;
}
+
if (@throw)
ThrowInvalidCastException(obj, castToType);
return null;
diff --git a/Baselib/src/System/Globalization/CompareInfo.cs b/Baselib/src/System/Globalization/CompareInfo.cs
index c0ab4a8..4f2a886 100644
--- a/Baselib/src/System/Globalization/CompareInfo.cs
+++ b/Baselib/src/System/Globalization/CompareInfo.cs
@@ -44,6 +44,21 @@ namespace system.globalization {
JavaBreakIter = java.text.BreakIterator.getCharacterInstance(locale);
}
+ //
+ // Equals
+ //
+
+ public override bool Equals(object other)
+ => other is CompareInfo otherCompareInfo && Name == otherCompareInfo.Name;
+
+ public override int GetHashCode() => Name.GetHashCode();
+
+ public string Name => CultureInfoRef.Name;
+
+ public override string ToString() => "CompareInfo - " + CultureInfoRef.ToString();
+
+
+
//
// GetCompareInfo
//
@@ -57,12 +72,6 @@ namespace system.globalization {
public static CompareInfo InvariantCompareInfo
=> system.globalization.CultureInfo.InvariantCulture.CompareInfo;
- //
- //
- //
-
- public override string ToString() => "CompareInfo - " + CultureInfoRef.ToString();
-
//
@@ -95,6 +104,166 @@ namespace system.globalization {
return true;
}
+
+
+ //
+ // Compare (public API)
+ //
+
+ public virtual int Compare(string string1, string string2)
+ => CompareString(string1, 0, -1, string2, 0, -1, CompareOptions.None);
+
+ public virtual int Compare(string string1, string string2, CompareOptions options)
+ => CompareString(string1, 0, -1, string2, 0, -1, options);
+
+ public virtual int Compare(string string1, int offset1, string string2, int offset2)
+ => CompareString(string1, offset1, -1, string2, offset2, -1, CompareOptions.None);
+
+ public virtual int Compare(string string1, int offset1, string string2, int offset2,
+ CompareOptions options)
+ => CompareString(string1, offset1, -1, string2, offset2, -1, options);
+
+ public virtual int Compare(string string1, int offset1, int length1,
+ string string2, int offset2, int length2)
+ {
+ if (length1 < 0 || length2 < 0)
+ throw new ArgumentOutOfRangeException();
+ return CompareString(string1, offset1, length1, string2, offset2, length2, CompareOptions.None);
+ }
+
+ public virtual int Compare(string string1, int offset1, int length1,
+ string string2, int offset2, int length2,
+ CompareOptions options)
+ {
+ if (length1 < 0 || length2 < 0)
+ throw new ArgumentOutOfRangeException();
+ return CompareString(string1, offset1, length1, string2, offset2, length2, options);
+ }
+
+ //
+ // CompareString (internal method)
+ //
+
+ private int CompareString(string string1, int offset1, int length1,
+ string string2, int offset2, int length2,
+ CompareOptions options)
+ {
+ if (offset1 < 0 || offset2 < 0)
+ throw new ArgumentOutOfRangeException();
+ int endOffset1 = GetEndOffset(string1, offset1, length1);
+ int endOffset2 = GetEndOffset(string2, offset2, length2);
+
+ if (string1 == null)
+ return (string2 == null) ? 0 : -1;
+ else if (string2 == null)
+ return 1;
+
+ if ((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) != 0)
+ {
+ bool ignoreCase;
+ if (options == CompareOptions.Ordinal)
+ ignoreCase = false;
+ else if (options == CompareOptions.OrdinalIgnoreCase)
+ ignoreCase = true;
+ else
+ throw new System.ArgumentException();
+
+ return CompareStringOrdinal(string1, offset1, endOffset1,
+ string2, offset2, endOffset2,
+ ignoreCase);
+ }
+ else
+ {
+ return CompareStringCulture(string1, offset1, endOffset1,
+ string2, offset2, endOffset2,
+ CompareOptionsToCollatorMask(options));
+ }
+
+ static int GetEndOffset(string str, int ofs, int len)
+ {
+ if (str == null)
+ {
+ if (ofs == 0 && len <= 0)
+ return -1;
+ }
+ else
+ {
+ int strLen = ((java.lang.String) (object) str).length();
+ if (len == -1)
+ {
+ if (ofs < strLen)
+ return strLen;
+ }
+ else if ((ofs += len) <= strLen)
+ return ofs;
+ }
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ //
+ // CompareStringOrdinal (internal method)
+ //
+
+ private static int CompareStringOrdinal(string string1, int index1, int endIndex1,
+ string string2, int index2, int endIndex2,
+ bool ignoreCase)
+ {
+ var str1 = (java.lang.String) (object)
+ (((java.lang.String) (object) string1).substring(index1, endIndex1));
+ var str2 = (java.lang.String) (object)
+ (((java.lang.String) (object) string2).substring(index2, endIndex2));
+ return ignoreCase ? str1.compareToIgnoreCase(str2) : str1.compareTo(str2);
+ }
+
+ //
+ // CompareStringCulture (internal method)
+ //
+
+ private int CompareStringCulture(string string1, int index1, int endIndex1,
+ string string2, int index2, int endIndex2,
+ uint mask)
+ {
+ // create iterators for the two strings. see also IndexOfStringCulture
+
+ var iterator1 = new Iterator(this, mask,
+ new java.text.StringCharacterIterator(
+ string1, index1, endIndex1, index1));
+
+ var iterator2 = new Iterator(this, mask,
+ new java.text.StringCharacterIterator(
+ string2, index2, endIndex2, index2));
+
+ for (;;)
+ {
+ var order1 = iterator1.Next();
+ var order2 = iterator2.Next();
+
+ if (order1 == null)
+ return (order2 == null) ? 0 : -1;
+ else if (order2 == null)
+ return 1;
+
+ int n1 = order1.Length;
+ int n2 = order2.Length;
+ int n = (n1 <= n2) ? n1 : n2;
+ for (int i = 0; i < n; i++)
+ {
+ int o1 = order1[i];
+ int o2 = order2[i];
+ if (o1 != o2)
+ return o1 - o2;
+ if (o1 == 0)
+ break;
+ }
+
+ if (n1 != n2)
+ return n1 - n2;
+ }
+ }
+
+
+
//
// IndexOf (char, public API)
//
@@ -255,12 +424,12 @@ namespace system.globalization {
//
public static int IndexOfString(string source, string value, int startIndex,
- CompareOptions options, CompareInfo compareInfo)
+ CompareOptions options, CompareInfo compareInfo)
{
ThrowHelper.ThrowIfNull(source);
int sourceLength = ((java.lang.String) (object) source).length();
- if (startIndex >= sourceLength)
+ if (startIndex < 0 || startIndex >= sourceLength)
throw new System.ArgumentOutOfRangeException();
if (options == CompareOptions.Ordinal)
@@ -620,7 +789,7 @@ namespace system.globalization {
int sourceLength = ((java.lang.String) (object) source).length();
if (! haveStartIndex)
startIndex = sourceLength - 1;
- else if (startIndex >= sourceLength)
+ else if (startIndex < 0 || startIndex >= sourceLength)
throw new System.ArgumentOutOfRangeException();
if (options == CompareOptions.Ordinal)
@@ -1359,7 +1528,7 @@ namespace system.globalization {
else if (small.sequence[S] == 0)
{
// if the small sequence ends before the large sequence,
- // this cannot be a made. this is to correctly emulate
+ // this cannot be a match. this is to correctly emulate
// the .Net comparison, where, for example, a search for
// just "A" cannot match the (AE) symbol.
diff --git a/Baselib/src/System/Globalization/CultureInfo.cs b/Baselib/src/System/Globalization/CultureInfo.cs
index b3a706f..b344f8a 100644
--- a/Baselib/src/System/Globalization/CultureInfo.cs
+++ b/Baselib/src/System/Globalization/CultureInfo.cs
@@ -8,6 +8,7 @@ namespace system.globalization {
[java.attr.RetainType] java.util.Locale JavaLocale;
[java.attr.RetainType] volatile CompareInfo CompareInfoRef;
+ [java.attr.RetainType] volatile TextInfo TextInfoRef;
@@ -42,6 +43,7 @@ namespace system.globalization {
}
JavaLocale = locale;
CompareInfoRef = new CompareInfo(this, JavaLocale);
+ TextInfoRef = new TextInfo(this, JavaLocale);
}
@@ -92,6 +94,8 @@ namespace system.globalization {
public virtual CompareInfo CompareInfo => CompareInfoRef;
+ public virtual TextInfo TextInfo => TextInfoRef;
+
public static CultureInfo CurrentCulture
=> system.threading.Thread.CurrentThread.CurrentCulture;
diff --git a/Baselib/src/System/Globalization/TextInfo.cs b/Baselib/src/System/Globalization/TextInfo.cs
new file mode 100644
index 0000000..be4cec2
--- /dev/null
+++ b/Baselib/src/System/Globalization/TextInfo.cs
@@ -0,0 +1,85 @@
+
+using System;
+using System.Runtime.Serialization;
+
+namespace system.globalization {
+
+ [Serializable]
+ public class TextInfo : ICloneable, IDeserializationCallback
+ {
+ [java.attr.RetainType] CultureInfo CultureInfoRef;
+ [java.attr.RetainType] java.util.Locale JavaLocale;
+
+ //
+ // called by CultureInfo
+ //
+
+ public TextInfo(CultureInfo cultureInfo, java.util.Locale locale)
+ {
+ CultureInfoRef = cultureInfo;
+ JavaLocale = locale;
+ }
+
+ //
+ //
+ //
+
+ public static TextInfo CurrentTextInfo
+ => system.threading.Thread.CurrentThread.CurrentCulture.TextInfo;
+
+ public static TextInfo InvariantTextInfo
+ => system.globalization.CultureInfo.InvariantCulture.TextInfo;
+
+ //
+ // ToLower, ToUpper, ToTitleCase
+ //
+
+ public virtual char ToLower(char c)
+ => ((java.lang.String) (object)
+ ((java.lang.String) (object) java.lang.String.valueOf(c))
+ .toLowerCase(JavaLocale)).charAt(0);
+
+ public virtual string ToLower(string s)
+ => ((java.lang.String) (object) s).toLowerCase(JavaLocale);
+
+ public virtual char ToUpper(char c)
+ => ((java.lang.String) (object)
+ ((java.lang.String) (object) java.lang.String.valueOf(c))
+ .toUpperCase(JavaLocale)).charAt(0);
+
+ public virtual string ToUpper(string s)
+ => ((java.lang.String) (object) s).toUpperCase(JavaLocale);
+
+ public virtual char ToTitleCase(string s)
+ {
+ // java.lang.Character.toTitleCase(java.lang.String.toUpperCase(locale))
+ throw new System.PlatformNotSupportedException();
+ }
+
+ //
+ // Equals
+ //
+
+ public override bool Equals(object other)
+ => other is TextInfo otherTextInfo && CultureName == otherTextInfo.CultureName;
+
+ public override int GetHashCode() => CultureName.GetHashCode();
+
+ public string CultureName => CultureInfoRef.Name;
+
+ public override string ToString() => "TextInfo - " + CultureInfoRef.ToString();
+
+ public bool IsReadOnly => true;
+
+ public virtual object Clone() => MemberwiseClone();
+
+ //
+ //
+ //
+
+ void IDeserializationCallback.OnDeserialization(object sender)
+ => throw new PlatformNotSupportedException();
+
+ }
+
+}
diff --git a/Baselib/src/System/Int16.cs b/Baselib/src/System/Int16.cs
index 9f9fbf9..8314ec2 100644
--- a/Baselib/src/System/Int16.cs
+++ b/Baselib/src/System/Int16.cs
@@ -2,7 +2,7 @@
namespace system
{
- public class Int16 : system.ValueType, system.ValueMethod,
+ public class Int16 : system.ValueType, system.ValueMethod, java.lang.Cloneable,
System.IComparable, System.IComparable,
System.IConvertible, System.IEquatable, System.IFormattable
{
@@ -58,17 +58,17 @@ namespace system
// System.IComparable
public virtual int CompareTo(object obj)
{
- if (object.ReferenceEquals(obj, null))
- return 1;
if (obj is Int16 objInt16)
return CompareTo((short) objInt16.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
throw new System.ArgumentException();
}
// System.IComparable
public int CompareTo(short b)
{
- int a = Get();
+ var a = Get();
return (a < b ? -1 : a > b ? 1 : 0);
}
@@ -215,10 +215,10 @@ namespace system
// System.IComparable
public override int CompareTo(object obj)
{
- if (object.ReferenceEquals(obj, null))
- return 1;
if (obj is UInt16 objUInt16)
return CompareTo((ushort) objUInt16.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
throw new System.ArgumentException();
}
diff --git a/Baselib/src/System/Int32.cs b/Baselib/src/System/Int32.cs
index 54f62ec..830a30e 100644
--- a/Baselib/src/System/Int32.cs
+++ b/Baselib/src/System/Int32.cs
@@ -2,7 +2,7 @@
namespace system
{
- public class Int32 : system.ValueType, system.ValueMethod,
+ public class Int32 : system.ValueType, system.ValueMethod, java.lang.Cloneable,
System.IComparable, System.IComparable,
System.IConvertible, System.IEquatable, System.IFormattable
{
@@ -58,20 +58,22 @@ namespace system
public string ToString(System.IFormatProvider provider) => ToString();
+
+
// System.IComparable
public virtual int CompareTo(object obj)
{
- if (object.ReferenceEquals(obj, null))
- return 1;
if (obj is Int32 objInt32)
return CompareTo((int) objInt32.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
throw new System.ArgumentException();
}
// System.IComparable
public int CompareTo(int b)
{
- int a = Get();
+ var a = Get();
return (a < b ? -1 : a > b ? 1 : 0);
}
@@ -151,8 +153,6 @@ namespace system
// CodeNumber.Indirection methods
//
-
-
public int Get_U8() => (byte) Get();
public int Get_I8() => (sbyte) Get();
public void Set_I8(int v) => Set((int) ((byte) v | ((uint) Get() & (uint) 0xFFFFFF00)));
@@ -176,8 +176,6 @@ namespace system
// IConvertible
//
-
-
public virtual System.TypeCode GetTypeCode() => System.TypeCode.Int32;
bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
@@ -273,10 +271,10 @@ namespace system
// System.IComparable
public override int CompareTo(object obj)
{
- if (object.ReferenceEquals(obj, null))
- return 1;
if (obj is UInt32 objUInt32)
return CompareTo((uint) objUInt32.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
throw new System.ArgumentException();
}
diff --git a/Baselib/src/System/Int64.cs b/Baselib/src/System/Int64.cs
index c1ab858..f865b5e 100644
--- a/Baselib/src/System/Int64.cs
+++ b/Baselib/src/System/Int64.cs
@@ -2,7 +2,8 @@
namespace system
{
- public class Int64 : system.ValueType, system.ValueMethod,
+ public class Int64 : system.ValueType, system.ValueMethod, java.lang.Cloneable,
+ System.IComparable, System.IComparable,
System.IConvertible, System.IEquatable, System.IFormattable
{
@@ -63,6 +64,25 @@ namespace system
+ // System.IComparable
+ public virtual int CompareTo(object obj)
+ {
+ if (obj is Int64 objInt64)
+ return CompareTo((long) objInt64.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
+ throw new System.ArgumentException();
+ }
+
+ // System.IComparable
+ public int CompareTo(long b)
+ {
+ var a = Get();
+ return (a < b ? -1 : a > b ? 1 : 0);
+ }
+
+
+
public static long OverflowAdd(long a, long b)
{
long c = a + b;
@@ -123,8 +143,6 @@ namespace system
// CodeNumber.Indirection methods
//
-
-
public int Get_U8() => (byte) Get();
public int Get_I8() => (sbyte) Get();
public void Set_I8(int v) => Set((int) ((byte) v | ((ulong) Get() & (ulong) 0xFFFFFFFFFFFFFF00)));
@@ -148,8 +166,6 @@ namespace system
// IConvertible
//
-
-
public virtual System.TypeCode GetTypeCode() => System.TypeCode.Int64;
bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
@@ -227,12 +243,14 @@ namespace system
public static int Size => 8;
public static readonly IntPtr Zero = new IntPtr(0);
+
+ new public static IntPtr Box(long v) => new IntPtr(v);
}
#pragma warning disable 0659
- public class UInt64 : Int64, System.IEquatable
+ public class UInt64 : Int64, System.IComparable, System.IEquatable
{
new public static UInt64 Box(long v) => new UInt64() { v = v };
@@ -255,8 +273,17 @@ namespace system
public override System.TypeCode GetTypeCode() => System.TypeCode.UInt64;
- //public int CompareTo(ulong v) => java.lang.Long.compareUnsigned(Get(), (long) v);
+ // System.IComparable
+ public override int CompareTo(object obj)
+ {
+ if (obj is UInt64 objUInt64)
+ return CompareTo((ulong) objUInt64.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
+ throw new System.ArgumentException();
+ }
+ // System.IComparable
public int CompareTo(ulong v) => CompareTo(Get(), (long) v);
public static int CompareTo(long a, long b)
@@ -368,4 +395,19 @@ namespace system
}
+
+
+ public class UIntPtr : UInt64
+ {
+
+ public UIntPtr(int v) => this.v = v;
+ public UIntPtr(long v) => this.v = v;
+
+ public static int Size => 8;
+
+ public static readonly UIntPtr Zero = new UIntPtr(0);
+
+ new public static UIntPtr Box(long v) => new UIntPtr(v);
+ }
+
}
diff --git a/Baselib/src/System/Reflection/CustomAttribute.cs b/Baselib/src/System/Reflection/CustomAttribute.cs
new file mode 100644
index 0000000..4c2724a
--- /dev/null
+++ b/Baselib/src/System/Reflection/CustomAttribute.cs
@@ -0,0 +1,8 @@
+
+
+namespace system.reflection
+{
+
+ public struct CustomAttributeTypedArgument { }
+
+}
diff --git a/Baselib/src/System/Reflection/RuntimeAssembly.cs b/Baselib/src/System/Reflection/RuntimeAssembly.cs
index 4a324c1..e475550 100644
--- a/Baselib/src/System/Reflection/RuntimeAssembly.cs
+++ b/Baselib/src/System/Reflection/RuntimeAssembly.cs
@@ -1,6 +1,5 @@
using System;
-using System.Reflection;
using System.Globalization;
using System.Runtime.Serialization;
@@ -11,65 +10,93 @@ namespace system.reflection
public class RuntimeAssembly : System.Reflection.Assembly, ISerializable
{
- private java.security.CodeSource JavaCodeSource;
+ [java.attr.RetainType] private java.security.ProtectionDomain JavaDomain;
+ private System.Reflection.Module[] theModule;
+ private static java.util.concurrent.ConcurrentHashMap _DomainToAssemblyMap;
//
//
//
- protected RuntimeAssembly(java.security.CodeSource codeSource)
+ private RuntimeAssembly(java.security.ProtectionDomain domain)
{
- JavaCodeSource = codeSource;
+ JavaDomain = domain;
}
//
- //
+ // GetAssemblyForDomain
//
- public static RuntimeAssembly GetExecutingAssembly(ref system.threading.StackCrawlMark stackMark)
+ public static System.Reflection.Assembly GetAssemblyForDomain(
+ java.security.ProtectionDomain domain)
{
+ if (domain == null)
+ throw new DllNotFoundException();
+ var map = System.Threading.LazyInitializer
+ .EnsureInitialized(
+ ref _DomainToAssemblyMap);
+ var assembly = (RuntimeAssembly) map.get(domain);
+ if (assembly == null)
+ {
+ var newAssembly = new RuntimeAssembly(domain);
+ assembly = (RuntimeAssembly)
+ map.putIfAbsent(domain, newAssembly) ?? newAssembly;
+ }
+ return assembly;
+ }
+
+ //
+ // GetExecutingAssembly
+ //
+
+ public static RuntimeAssembly GetExecutingAssembly(
+ ref system.threading.StackCrawlMark stackMark)
+ {
+ java.security.ProtectionDomain domain = null;
var stackTrace = (new java.lang.Throwable()).getStackTrace();
foreach (var stackElem in stackTrace)
{
var clsnm = stackElem.getClassName();
if (! clsnm.StartsWith("system.reflection."))
- return GetAssemblyForClass(java.lang.Class.forName(clsnm));
- }
- throw new DllNotFoundException();
- }
-
- static RuntimeAssembly GetAssemblyForClass(java.lang.Class cls)
- {
- var jar = cls?.getProtectionDomain()?.getCodeSource();
- if (jar != null)
- {
- var map = System.Threading.LazyInitializer
- .EnsureInitialized(
- ref _CodeSourceToAssemblyMap);
- var assembly = (RuntimeAssembly) map.get(jar);
- if (assembly == null)
{
- var newAssembly = new RuntimeAssembly(jar);
- assembly = (RuntimeAssembly) map.putIfAbsent(jar, newAssembly) ?? newAssembly;
+ domain = java.lang.Class.forName(clsnm)?.getProtectionDomain();
+ break;
}
- return assembly;
}
- throw new DllNotFoundException();
+ return (RuntimeAssembly) GetAssemblyForDomain(domain);
}
- private static java.util.concurrent.ConcurrentHashMap _CodeSourceToAssemblyMap;
+ //
+ // GetModules
+ //
+
+ public override System.Reflection.Module[] GetModules(bool getResourceModules)
+ {
+ return System.Threading.LazyInitializer
+ .EnsureInitialized(ref theModule, () =>
+ {
+ var mod = (System.Reflection.Module) (object)
+ (new RuntimeModule() { JavaDomain = JavaDomain });
+ return new System.Reflection.Module[] { mod };
+ });
+ }
//
- //
+ // GetName
//
public override System.Reflection.AssemblyName GetName(bool copiedName)
{
- var name = new System.Reflection.AssemblyName(JavaCodeSource.getLocation().getFile());
+ var name = new System.Reflection.AssemblyName(
+ JavaDomain.getCodeSource().getLocation().getFile());
name.Version = new Version();
return name;
}
+ //
+ // nInit
+ //
+
[java.attr.RetainName]
public static void nInit(System.Reflection.AssemblyName thisAssemblyName,
out RuntimeAssembly assembly,
diff --git a/Baselib/src/System/Reflection/RuntimeModule.cs b/Baselib/src/System/Reflection/RuntimeModule.cs
index 8b40feb..56dc9d0 100644
--- a/Baselib/src/System/Reflection/RuntimeModule.cs
+++ b/Baselib/src/System/Reflection/RuntimeModule.cs
@@ -4,10 +4,38 @@ using System.Runtime.InteropServices;
namespace system.reflection
{
- public abstract class Module { }
-
- public sealed class RuntimeModule
+ public abstract class Module
{
+ public abstract System.Type[] GetTypes();
+ }
+
+ public sealed class RuntimeModule : Module
+ {
+ [java.attr.RetainType] public java.security.ProtectionDomain JavaDomain;
+
+ public override System.Type[] GetTypes()
+ {
+ for (;;)
+ {
+ try
+ {
+ var types = new System.Collections.Generic.List();
+
+ var iterator = AppDomain.CurrentDomain.GetAllClasses().iterator();
+ while (iterator.hasNext())
+ {
+ var cls = (java.lang.Class) iterator.next();
+ if (cls.getProtectionDomain() == JavaDomain)
+ types.Add(system.RuntimeType.GetType(cls));
+ }
+
+ return types.ToArray();
+ }
+ catch (java.util.ConcurrentModificationException)
+ {
+ }
+ }
+ }
public MetadataImport MetadataImport => _MetadataImport;
public StructLayoutAttribute StructLayoutAttribute => _StructLayoutAttribute;
diff --git a/Baselib/src/System/Runtime/RuntimeHelpers.cs b/Baselib/src/System/Runtime/RuntimeHelpers.cs
index 36f14cc..c916dde 100644
--- a/Baselib/src/System/Runtime/RuntimeHelpers.cs
+++ b/Baselib/src/System/Runtime/RuntimeHelpers.cs
@@ -16,6 +16,9 @@ namespace system.runtime.compilerservices {
return 0;
}
+ public static int GetHashCode(object o)
+ => (o != null) ? o.GetHashCode() : 0;
+
}
}
diff --git a/Baselib/src/System/Single.cs b/Baselib/src/System/Single.cs
index 157da55..ae0dddd 100644
--- a/Baselib/src/System/Single.cs
+++ b/Baselib/src/System/Single.cs
@@ -2,7 +2,8 @@
namespace system
{
- public class Single : system.ValueType, system.ValueMethod,
+ public class Single : system.ValueType, system.ValueMethod, java.lang.Cloneable,
+ System.IComparable, System.IComparable,
System.IConvertible, System.IEquatable, System.IFormattable
{
@@ -44,7 +45,7 @@ namespace system
- // System.IEquatable
+ // System.IEquatable
public bool Equals(float v) => v == Get();
// System.IFormattable
@@ -56,6 +57,29 @@ namespace system
(java.lang.String) (object) format, provider, java.lang.Float.valueOf(Get()));
}
+ public string ToString(string format) => ToString(format, null);
+
+ public string ToString(System.IFormatProvider provider) => ToString();
+
+
+
+ // System.IComparable
+ public virtual int CompareTo(object obj)
+ {
+ if (obj is Single objSingle)
+ return CompareTo(objSingle.Get());
+ else if (object.ReferenceEquals(obj, null))
+ return 1;
+ throw new System.ArgumentException();
+ }
+
+ // System.IComparable
+ public int CompareTo(float b)
+ {
+ var a = Get();
+ return (a < b ? -1 : a > b ? 1 : 0);
+ }
+
void ValueMethod.Clear() => Set(0);
@@ -84,8 +108,6 @@ namespace system
// IConvertible
//
-
-
public System.TypeCode GetTypeCode() => System.TypeCode.Single;
bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
@@ -115,11 +137,9 @@ namespace system
System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
=> System.Convert.ToDecimal(Get());
System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
- => throw new System.InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo_Int32_DateTime"));
- string System.IConvertible.ToString(System.IFormatProvider provider)
- => ToString();
+ => throw new System.InvalidCastException();
object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
- => null;//System.Convert.DefaultToType((System.IConvertible) this, type, provider);
+ => system.Convert.DefaultToType((System.IConvertible) this, type, provider);
diff --git a/Baselib/src/System/String.cs b/Baselib/src/System/String.cs
index f1426ee..2e597cf 100644
--- a/Baselib/src/System/String.cs
+++ b/Baselib/src/System/String.cs
@@ -52,36 +52,56 @@ namespace system
return new string(buffer);
}
+ //
+ // ToLower, ToUpper
+ //
+
+ public static string ToLower(string self)
+ => system.globalization.TextInfo.CurrentTextInfo.ToLower(self);
+
+ public static string ToLowerInvariant(string self)
+ => system.globalization.TextInfo.InvariantTextInfo.ToLower(self);
+
+ public static string ToUpper(string self)
+ => system.globalization.TextInfo.CurrentTextInfo.ToUpper(self);
+
+ public static string ToUpperInvariant(string self)
+ => system.globalization.TextInfo.InvariantTextInfo.ToUpper(self);
+
//
// Concat object
//
+ static void AppendIfNotNull(java.lang.StringBuilder sb, object obj)
+ {
+ if (obj is string)
+ {
+ sb.append((string) obj);
+ }
+ else if (obj != null)
+ {
+ var str = obj.ToString();
+ if (str != null)
+ sb.append(str);
+ }
+ }
+
public static string Concat(object[] objs)
{
- if (objs == null)
- throw new System.ArgumentNullException();
+ ThrowHelper.ThrowIfNull(objs);
var sb = new java.lang.StringBuilder();
- int n = objs.Length;
- for (int i = 0; i < n; i++)
- {
- var o = objs[i];
- if (o != null)
- sb.append(o.ToString());
- }
+ foreach (var obj in objs)
+ AppendIfNotNull(sb, obj);
return sb.ToString();
}
public static string Concat(object objA, object objB, object objC, object objD)
{
var sb = new java.lang.StringBuilder();
- if (objA != null)
- sb.append(objA.ToString());
- if (objB != null)
- sb.append(objB.ToString());
- if (objC != null)
- sb.append(objC.ToString());
- if (objC != null)
- sb.append(objD.ToString());
+ AppendIfNotNull(sb, objA);
+ AppendIfNotNull(sb, objB);
+ AppendIfNotNull(sb, objC);
+ AppendIfNotNull(sb, objD);
return sb.ToString();
}
@@ -96,32 +116,22 @@ namespace system
// Concat string
//
- public static string Concat(params string[] strs)
+ public static string Concat(string[] strs)
{
- if (strs == null)
- throw new System.ArgumentNullException();
+ ThrowHelper.ThrowIfNull(strs);
var sb = new java.lang.StringBuilder();
- int n = strs.Length;
- for (int i = 0; i < n; i++)
- {
- var s = strs[i];
- if (s != null)
- sb.append(s);
- }
+ foreach (var str in strs)
+ AppendIfNotNull(sb, str);
return sb.ToString();
}
public static string Concat(string strA, string strB, string strC, string strD)
{
var sb = new java.lang.StringBuilder();
- if (strA != null)
- sb.append(strA);
- if (strB != null)
- sb.append(strB);
- if (strC != null)
- sb.append(strC);
- if (strD != null)
- sb.append(strD);
+ AppendIfNotNull(sb, strA);
+ AppendIfNotNull(sb, strB);
+ AppendIfNotNull(sb, strC);
+ AppendIfNotNull(sb, strD);
return sb.ToString();
}
@@ -134,47 +144,184 @@ namespace system
// Concat enumerator
//
- #if false
- [java.attr.RetainName]
public static string Concat(System.Collections.Generic.IEnumerable enumerable)
{
- if (enumerable == null)
- throw new System.ArgumentNullException();
+ ThrowHelper.ThrowIfNull(enumerable);
var sb = new java.lang.StringBuilder();
- using (var enumerator = enumerable.GetEnumerator())
- {
- while (enumerator.MoveNext())
- {
- var e = enumerator.Current;
- if (e != null)
- {
- string s = e.ToString();
- if (s != null)
- sb.append(s);
- }
- }
- }
+ foreach (var obj in enumerable)
+ AppendIfNotNull(sb, obj);
return sb.ToString();
}
- //[java.attr.RetainName]
public static string Concat(System.Collections.Generic.IEnumerable enumerable)
+ => Concat(enumerable);
+
+ //
+ // Split
+ //
+
+ public static string[] Split(string str, char[] separator)
+ => InternalSplit((java.lang.String) (object) str, separator, System.Int32.MaxValue, System.StringSplitOptions.None);
+
+ public static string[] Split(string str, string[] separator)
+ => InternalSplit((java.lang.String) (object) str, separator, System.Int32.MaxValue, System.StringSplitOptions.None);
+
+ public static string[] Split(string str, char[] separator, int count)
+ => InternalSplit((java.lang.String) (object) str, separator, count, System.StringSplitOptions.None);
+
+ public static string[] Split(string str, string[] separator, int count)
+ => InternalSplit((java.lang.String) (object) str, separator, count, System.StringSplitOptions.None);
+
+ public static string[] Split(string str, char[] separator, System.StringSplitOptions options)
+ => InternalSplit((java.lang.String) (object) str, separator, System.Int32.MaxValue, options);
+
+ public static string[] Split(string str, string[] separator, System.StringSplitOptions options)
+ => InternalSplit((java.lang.String) (object) str, separator, System.Int32.MaxValue, options);
+
+ public static string[] Split(string str, char[] separator, int count, System.StringSplitOptions options)
+ => InternalSplit((java.lang.String) (object) str, separator, count, options);
+
+ public static string[] Split(string str, string[] separator, int count, System.StringSplitOptions options)
+ => InternalSplit((java.lang.String) (object) str, separator, count, options);
+
+ private static string[] InternalSplit(java.lang.String str,
+ object separator, int count,
+ System.StringSplitOptions options)
{
- if (enumerable == null)
- throw new System.ArgumentNullException();
- var sb = new java.lang.StringBuilder();
- using (var enumerator = enumerable.GetEnumerator())
+ if (count < 0)
+ throw new System.ArgumentOutOfRangeException();
+
+ bool omit = (options == System.StringSplitOptions.None) ? false
+ : (options == System.StringSplitOptions.RemoveEmptyEntries) ? true
+ : throw new System.ArgumentException();
+
+ var emptyArray = new string[0];
+ if (count == 0)
+ return emptyArray;
+
+ int length = str.length();
+ var list = new java.util.ArrayList();
+
+ if (separator is char[] charSeparator)
+ SplitCharacter(str, length, list, count, omit, charSeparator);
+ else if (separator is java.lang.String[] strSeparator)
+ SplitString(str, length, list, count, omit, strSeparator);
+ else // assuming separator is null
+ SplitWhiteSpace(str, length, list, count, omit);
+
+ return (string[]) list.toArray(emptyArray);
+ }
+
+ private static void SplitWhiteSpace(java.lang.String str, int length,
+ java.util.ArrayList list, int maxCount,
+ bool omit)
+ {
+ int listCount = 0;
+ int lastIndex = -1;
+ for (int index = 0; index < length; index++)
{
- while (enumerator.MoveNext())
+ if (! Char.IsWhiteSpace(str.charAt(index)))
+ continue;
+ if (index == ++lastIndex && omit)
+ continue;
+ if (++listCount == maxCount)
{
- var s = enumerator.Current;
- if (s != null)
- sb.append(s);
+ list.add(str.substring(lastIndex));
+ return;
+ }
+ list.add(str.substring(lastIndex, index));
+ lastIndex = index;
+ }
+ if (length != ++lastIndex || ! omit)
+ list.add(str.substring(lastIndex));
+ }
+
+ private static void SplitCharacter(java.lang.String str, int length,
+ java.util.ArrayList list, int maxCount,
+ bool omit, char[] anyOf)
+ {
+ int listCount = 0;
+ int lastIndex = -1;
+ for (int index = 0; index < length; index++)
+ {
+ if (! CharAtIsAnyOf(str, index, anyOf))
+ continue;
+ if (index == ++lastIndex && omit)
+ continue;
+ if (++listCount == maxCount)
+ {
+ list.add(str.substring(lastIndex));
+ return;
+ }
+ list.add(str.substring(lastIndex, index));
+ lastIndex = index;
+ }
+ if (length != ++lastIndex || ! omit)
+ list.add(str.substring(lastIndex));
+ }
+
+ private static void SplitString(java.lang.String str, int length,
+ java.util.ArrayList list, int maxCount,
+ bool omit, java.lang.String[] anyOfStr)
+ {
+ int anyOfNum = anyOfStr.Length;
+ char[] anyOfChar = new char[anyOfNum];
+ for (int index = 0; index < anyOfNum; index++)
+ {
+ var s = anyOfStr[index];
+ anyOfChar[index] =
+ (s != null && s.length() > 0) ? s.charAt(index) : '\0';
+ }
+
+ int listCount = 0;
+ int lastIndex = 0;
+ for (int index = 0; index < length; )
+ {
+ int len = StrAtIsAnyOf(str, index, anyOfNum, anyOfChar, anyOfStr);
+ if (len == -1)
+ index++;
+ else
+ {
+ if (index != lastIndex || ! omit)
+ {
+ if (++listCount == maxCount)
+ {
+ list.add(str.substring(lastIndex));
+ return;
+ }
+ list.add(str.substring(lastIndex, index));
+ }
+ lastIndex = (index += len);
}
}
- return sb.ToString();
+ if (length != lastIndex || ! omit)
+ list.add(str.substring(lastIndex));
+ }
+
+ private static bool CharAtIsAnyOf(java.lang.String str, int idx, char[] anyOf)
+ {
+ char ch1 = str.charAt(idx);
+ foreach (var ch2 in anyOf)
+ if (ch2 == ch1)
+ return true;
+ return false;
+ }
+
+ private static int StrAtIsAnyOf(java.lang.String str, int idx, int anyOfNum,
+ char[] anyOfChar, java.lang.String[] anyOfStr)
+ {
+ char ch = str.charAt(idx);
+ for (int i = 0; i < anyOfNum; i++)
+ {
+ if (anyOfChar[i] == ch)
+ {
+ int len = anyOfStr[i].length();
+ if (str.regionMatches(idx, anyOfStr[i], 0, len))
+ return len;
+ }
+ }
+ return -1;
}
- #endif
//
// Join
@@ -208,6 +355,56 @@ namespace system
});
}
+ //
+ // Replace
+ //
+
+ public static string Replace(java.lang.String str, char oldChar, char newChar)
+ => str.replace(oldChar, newChar);
+
+ public static string Replace(java.lang.String str, string oldStr, string newStr)
+ {
+ ThrowHelper.ThrowIfNull(oldStr);
+ int lenOld = ((java.lang.String) (object) oldStr).length();
+ if (lenOld == 0)
+ throw new System.ArgumentException();
+
+ int idx1 = str.indexOf(oldStr, 0);
+ if (idx1 == -1)
+ return (string) (object) str;
+ int idx0 = 0;
+ int len = str.length();
+ var sb = new java.lang.StringBuilder();
+ for (;;)
+ {
+ sb.append(str.substring(idx0, idx1));
+ if (newStr != null)
+ sb.append(newStr);
+ if ( (idx0 = idx1 + lenOld) >= len
+ || (idx1 = str.indexOf(oldStr, idx0)) == -1)
+ {
+ sb.append(str.substring(idx0));
+ return sb.ToString();
+ }
+ }
+ }
+
+ //
+ // Copy
+ //
+
+ public static string Copy(java.lang.String str)
+ {
+ ThrowHelper.ThrowIfNull(str);
+ return java.lang.String.valueOf(str.toCharArray());
+ }
+
+ public static string Intern(java.lang.String str)
+ {
+ ThrowHelper.ThrowIfNull(str);
+ return str.intern();
+ }
+
//
// CopyTo
//
@@ -215,8 +412,7 @@ namespace system
public static void CopyTo(java.lang.String str, int sourceIndex,
char[] destination, int destinationIndex, int count)
{
- if (destination == null)
- throw new System.ArgumentNullException();
+ ThrowHelper.ThrowIfNull(destination);
if ( count < 0 || sourceIndex < 0 || destinationIndex < 0
|| count > str.length() - sourceIndex
|| destinationIndex > destination.Length - count)
@@ -276,6 +472,196 @@ namespace system
+ //
+ // CompareOrdinal
+ //
+
+ public static int CompareOrdinal(java.lang.String strA, java.lang.String strB)
+ {
+ if (object.ReferenceEquals(strA, strB))
+ return 0;
+ if (strA == null)
+ return -1;
+ if (strB == null)
+ return 1;
+ return strA.compareTo(strB);
+ }
+
+ public static int CompareOrdinal(java.lang.String strA, int indexA,
+ java.lang.String strB, int indexB, int length)
+ {
+ if (object.ReferenceEquals(strA, strB))
+ return 0;
+ if (strA == null)
+ return -1;
+ if (strB == null)
+ return 1;
+ int endIndexA, endIndexB;
+ if ( indexA < 0 || (endIndexA = indexA + length) > strA.length()
+ || indexB < 0 || (endIndexB = indexB + length) > strB.length())
+ throw new System.ArgumentOutOfRangeException();
+ return ((java.lang.String) (object) strA.substring(indexA, endIndexA))
+ .compareTo((java.lang.String) (object) strB.substring(indexB, endIndexB));
+ }
+
+
+
+ //
+ // Compare without length
+ //
+
+ public static int Compare(string strA, string strB)
+ => system.globalization.CompareInfo.CurrentCompareInfo.Compare(strA, strB,
+ System.Globalization.CompareOptions.None);
+
+ public static int Compare(string strA, string strB, bool ignoreCase)
+ => system.globalization.CompareInfo.CurrentCompareInfo.Compare(strA, strB,
+ ignoreCase ? System.Globalization.CompareOptions.IgnoreCase
+ : System.Globalization.CompareOptions.None);
+
+ public static int Compare(string strA, string strB, System.StringComparison option)
+ {
+ var (compareInfo, compareOption) = StringComparisonToCompareArguments(option);
+ return compareInfo.Compare(strA, strB, compareOption);
+ }
+
+ public static int Compare(string strA, string strB,
+ bool ignoreCase, System.Globalization.CultureInfo culture)
+ => culture.CompareInfo.Compare(strA, strB,
+ ignoreCase ? System.Globalization.CompareOptions.IgnoreCase
+ : System.Globalization.CompareOptions.None);
+
+ public static int Compare(string strA, string strB,
+ System.Globalization.CultureInfo culture,
+ System.Globalization.CompareOptions options)
+ => culture.CompareInfo.Compare(strA, strB, options);
+
+ //
+ // Compare with length
+ //
+
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length)
+ => Compare(strA, indexA, strB, indexB, length,
+ system.globalization.CompareInfo.CurrentCompareInfo,
+ System.Globalization.CompareOptions.None);
+
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length,
+ bool ignoreCase)
+ => Compare(strA, indexA, strB, indexB, length,
+ system.globalization.CompareInfo.CurrentCompareInfo,
+ System.Globalization.CompareOptions.IgnoreCase);
+
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length,
+ System.StringComparison comparisonType)
+ {
+ var (compareInfo, compareOption) = StringComparisonToCompareArguments(comparisonType);
+ return Compare(strA, indexA, strB, indexB, length, compareInfo, compareOption);
+ }
+
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length,
+ bool ignoreCase, system.globalization.CultureInfo culture)
+ => Compare(strA, indexA, strB, indexB, length, culture.CompareInfo,
+ ignoreCase ? System.Globalization.CompareOptions.IgnoreCase
+ : System.Globalization.CompareOptions.None);
+
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length,
+ system.globalization.CultureInfo culture,
+ System.Globalization.CompareOptions options)
+ => Compare(strA, indexA, strB, indexB, length, culture.CompareInfo, options);
+
+ private static int Compare(string strA, int indexA, string strB, int indexB, int length,
+ system.globalization.CompareInfo compareInfo,
+ System.Globalization.CompareOptions compareOptions)
+ {
+ int lengthA = length;
+ if (strA != null)
+ {
+ int maxlenA = ((java.lang.String) (object) strA).length() - indexA;
+ if (maxlenA < lengthA)
+ lengthA = maxlenA;
+ }
+
+ int lengthB = length;
+ if (strB != null)
+ {
+ int maxlenB = ((java.lang.String) (object) strB).length() - indexB;
+ if (maxlenB < lengthB)
+ lengthB = maxlenB;
+ }
+
+ return compareInfo.Compare(
+ strA, indexA, lengthA, strB, indexB, lengthB, compareOptions);
+ }
+
+
+
+ //
+ // IndexOfAny, LastIndexOfAny
+ //
+
+ public static int IndexOfAny(java.lang.String str, char[] anyOf)
+ => InternalIndexOfAny(str, anyOf, 1, /* index */ true, 0,
+ /* count */ false, 0);
+
+ public static int IndexOfAny(java.lang.String str, char[] anyOf, int startIndex)
+ => InternalIndexOfAny(str, anyOf, 1, /* index */ true, startIndex,
+ /* count */ false, 0);
+
+ public static int IndexOfAny(java.lang.String str, char[] anyOf, int startIndex, int count)
+ => InternalIndexOfAny(str, anyOf, 1, /* index */ true, startIndex,
+ /* count */ true, count);
+
+ public static int LastIndexOfAny(java.lang.String str, char[] anyOf)
+ => InternalIndexOfAny(str, anyOf, -1, /* index */ false, 0,
+ /* count */ false, 0);
+
+ public static int LastIndexOfAny(java.lang.String str, char[] anyOf, int startIndex)
+ => InternalIndexOfAny(str, anyOf, -1, /* index */ true, startIndex,
+ /* count */ false, 0);
+
+ public static int LastIndexOfAny(java.lang.String str, char[] anyOf, int startIndex, int count)
+ => InternalIndexOfAny(str, anyOf, -1, /* index */ true, startIndex,
+ /* count */ true, count);
+
+ private static int InternalIndexOfAny(java.lang.String str, char[] anyOf, int dir,
+ bool haveStartIndex, int startIndex,
+ bool haveCount, int count)
+ {
+ ThrowHelper.ThrowIfNull(anyOf);
+
+ int length = str.length();
+ if (haveCount && count < 0)
+ throw new System.ArgumentOutOfRangeException();
+ int endIndex;
+
+ if (dir == 1)
+ {
+ // IndexOfAny
+ endIndex = haveCount ? (startIndex + count) : length;
+ if (startIndex < 0 || endIndex > length)
+ throw new System.ArgumentOutOfRangeException();
+ }
+ else
+ {
+ // LastIndexOfAny
+ if (! haveStartIndex)
+ startIndex = length - 1;
+ endIndex = haveCount ? (startIndex - count + 1) : 0;
+ if (endIndex < 0 || startIndex >= length)
+ throw new System.ArgumentOutOfRangeException();
+ }
+
+ for (int index = startIndex; index != endIndex; index += dir)
+ {
+ if (CharAtIsAnyOf(str, index, anyOf))
+ return index;
+ }
+
+ return -1;
+ }
+
+
+
//
// IndexOf (char, ordinal)
//
@@ -475,9 +861,6 @@ namespace system
- //
- // IndexOfAny
- //
@@ -501,18 +884,46 @@ namespace system
public static bool StartsWith(java.lang.String str, string pfx)
{
- if (pfx == null)
- throw new System.ArgumentNullException();
+ ThrowHelper.ThrowIfNull(pfx);
return str.startsWith(pfx);
}
public static bool EndsWith(java.lang.String str, string sfx)
{
- if (sfx == null)
- throw new System.ArgumentNullException();
+ ThrowHelper.ThrowIfNull(sfx);
return str.endsWith(sfx);
}
+
+
+ //
+ // Contains
+ //
+
+
+
+ public static bool Contains(java.lang.String large, char small)
+ => large.indexOf(small, 0) >= 0;
+
+ public static bool Contains(java.lang.String large, string small)
+ => large.indexOf(small, 0) >= 0;
+
+ public static bool Contains(string large, char small, System.StringComparison option)
+ {
+ var (compareInfo, compareOption) = StringComparisonToCompareArguments(option);
+ return system.globalization.CompareInfo.IndexOfChar(
+ large, small, 0, compareOption, compareInfo) >= 0;
+ }
+
+ public static bool Contains(string large, string small, System.StringComparison option)
+ {
+ var (compareInfo, compareOption) = StringComparisonToCompareArguments(option);
+ return system.globalization.CompareInfo.IndexOfString(
+ large, small, 0, compareOption, compareInfo) >= 0;
+ }
+
+
+
//
//
//
@@ -521,6 +932,18 @@ namespace system
public static bool IsNullOrEmpty(java.lang.String str) => (str == null || str.length() == 0);
+ public static bool IsNullOrWhiteSpace(java.lang.String str)
+ {
+ if (str != null)
+ {
+ int n = str.length();
+ for (int i = 0; i < n; i++)
+ if (! Char.IsWhiteSpace(str.charAt(i)))
+ return false;
+ }
+ return true;
+ }
+
public static char[] ToCharArray(java.lang.String str) => str.toCharArray();
//
@@ -582,28 +1005,74 @@ namespace system
public static object CreateWrapper(object maybeString, System.Type castToType)
{
- if ( maybeString is java.lang.String
+ if ( maybeString is string reallyString
&& ( object.ReferenceEquals(castToType, cachedComparableString)
- || object.ReferenceEquals(castToType, cachedEquatableString)))
+ || object.ReferenceEquals(castToType, cachedEquatableString)
+ || object.ReferenceEquals(castToType, cachedIComparable)
+ || object.ReferenceEquals(castToType, cachedIConvertible)))
{
- return new Wrapper(maybeString);
+ return new Wrapper(reallyString);
}
return null;
}
[java.attr.RetainType] private static readonly System.Type cachedComparableString;
[java.attr.RetainType] private static readonly System.Type cachedEquatableString;
+ [java.attr.RetainType] private static readonly System.Type cachedIComparable;
+ [java.attr.RetainType] private static readonly System.Type cachedIConvertible;
- class Wrapper : System.IComparable, System.IEquatable
+ class Wrapper : System.IComparable, System.IEquatable,
+ System.IComparable, System.IConvertible
{
- [java.attr.RetainType] private java.lang.String str;
- public Wrapper(object _s) => str = (java.lang.String) (object) _s;
- // CompareTo implementation is wrong, should be culture sensitive
+ [java.attr.RetainType] private string str;
+ public Wrapper(string _s) => str = _s;
+ // generic CompareTo implementation is culture sensitive
public int CompareTo(string other)
- => str.compareTo((java.lang.String) (object) other);
+ => system.String.Compare(str, other);
// Equals is not sensitive to culture or case
public bool Equals(string other)
- => str.@equals((java.lang.String) (object) other);
+ => ((java.lang.String) (object) str).@equals(
+ (java.lang.String) (object) other);
+ // non-generic CompareTo implementation is culture sensitive
+ public int CompareTo(object other)
+ {
+ return (other is string ostr) ? system.String.Compare(str, ostr)
+ : (other == null) ? 1
+ : throw new System.ArgumentException();
+ }
+ // IConvertible
+ public string ToString(System.IFormatProvider provider) => str;
+ public System.TypeCode GetTypeCode() => System.TypeCode.String;
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider)
+ => System.Convert.ToBoolean(str, provider);
+ char System.IConvertible.ToChar(System.IFormatProvider provider)
+ => System.Convert.ToChar(str, provider);
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider)
+ => System.Convert.ToSByte(str, provider);
+ byte System.IConvertible.ToByte(System.IFormatProvider provider)
+ => System.Convert.ToByte(str, provider);
+ short System.IConvertible.ToInt16(System.IFormatProvider provider)
+ => System.Convert.ToInt16(str, provider);
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider)
+ => System.Convert.ToUInt16(str, provider);
+ int System.IConvertible.ToInt32(System.IFormatProvider provider)
+ => System.Convert.ToInt16(str, provider);
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider)
+ => System.Convert.ToUInt32(str, provider);
+ long System.IConvertible.ToInt64(System.IFormatProvider provider)
+ => System.Convert.ToInt64(str, provider);
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider)
+ => System.Convert.ToUInt64(str, provider);
+ float System.IConvertible.ToSingle(System.IFormatProvider provider)
+ => System.Convert.ToSingle(str, provider);
+ double System.IConvertible.ToDouble(System.IFormatProvider provider)
+ => System.Convert.ToDouble(str, provider);
+ System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider)
+ => System.Convert.ToDecimal(str, provider);
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider)
+ => System.Convert.ToDateTime(str, provider);
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider)
+ => system.Convert.DefaultToType((System.IConvertible) this, type, provider);
}
@@ -623,6 +1092,8 @@ namespace system
cachedComparableString = typeof(System.IComparable);
cachedEquatableString = typeof(System.IEquatable);
+ cachedIComparable = typeof(System.IComparable);
+ cachedIConvertible = typeof(System.IConvertible);
}
}
@@ -661,8 +1132,12 @@ namespace java.lang
public abstract string toUpperCase(java.util.Locale locale);
public abstract string toLowerCase(java.util.Locale locale);
public abstract int compareTo(java.lang.String other);
+ public abstract int compareToIgnoreCase(java.lang.String other);
public abstract bool equals(java.lang.String other);
+ public abstract string intern();
+ public abstract string replace(char oldChar, char newChar);
[java.attr.Discard] extern public static string format(string fmt, object[] args);
[java.attr.Discard] extern public static string valueOf(char c);
+ [java.attr.Discard] extern public static string valueOf(char[] data);
}
}
diff --git a/Baselib/src/System/Text/RegularExpressions/Match.cs b/Baselib/src/System/Text/RegularExpressions/Match.cs
index 6e6d23b..20d602c 100644
--- a/Baselib/src/System/Text/RegularExpressions/Match.cs
+++ b/Baselib/src/System/Text/RegularExpressions/Match.cs
@@ -15,7 +15,7 @@ namespace system.text.regularexpressions
groupCollection = new GroupCollection(this, matcher, input);
}
- private Match() : base(0, "", 0, 0)
+ private Match() : base(-1, "", -1, -1)
{
groupCollection = new GroupCollection(this, null, null);
}
diff --git a/Baselib/src/System/Text/RegularExpressions/Regex.cs b/Baselib/src/System/Text/RegularExpressions/Regex.cs
index 56cac05..988ce5b 100644
--- a/Baselib/src/System/Text/RegularExpressions/Regex.cs
+++ b/Baselib/src/System/Text/RegularExpressions/Regex.cs
@@ -16,6 +16,49 @@ namespace system.text.regularexpressions
JavaPattern = java.util.regex.Pattern.compile(pattern);
}
+ public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options)
+ {
+ int flags = 0;
+
+ if ((options & System.Text.RegularExpressions.RegexOptions.CultureInvariant) != 0)
+ options &= ~System.Text.RegularExpressions.RegexOptions.CultureInvariant;
+ else
+ {
+ flags |= java.util.regex.Pattern.UNICODE_CASE
+ | java.util.regex.Pattern.CANON_EQ;
+ }
+
+ if ((options & System.Text.RegularExpressions.RegexOptions.IgnoreCase) != 0)
+ {
+ options &= ~System.Text.RegularExpressions.RegexOptions.IgnoreCase;
+ flags |= java.util.regex.Pattern.CASE_INSENSITIVE;
+ }
+
+ if ((options & System.Text.RegularExpressions.RegexOptions.IgnorePatternWhitespace) != 0)
+ {
+ options &= ~System.Text.RegularExpressions.RegexOptions.IgnorePatternWhitespace;
+ flags |= java.util.regex.Pattern.COMMENTS;
+ }
+
+ if ((options & System.Text.RegularExpressions.RegexOptions.Multiline) != 0)
+ {
+ options &= ~System.Text.RegularExpressions.RegexOptions.Multiline;
+ flags |= java.util.regex.Pattern.MULTILINE;
+ }
+
+ if ((options & System.Text.RegularExpressions.RegexOptions.Singleline) != 0)
+ {
+ options &= ~System.Text.RegularExpressions.RegexOptions.Singleline;
+ flags |= java.util.regex.Pattern.DOTALL;
+ }
+
+ options &= ~System.Text.RegularExpressions.RegexOptions.Compiled;
+ if (options != 0)
+ throw new System.ArgumentOutOfRangeException();
+
+ JavaPattern = java.util.regex.Pattern.compile(pattern);
+ }
+
//
// Match
//
@@ -35,6 +78,50 @@ namespace system.text.regularexpressions
public static MatchCollection Matches(string input, string pattern)
=> new Regex(pattern).Matches(input);
+ //
+ // IsMatch
+ //
+
+ public bool IsMatch(string input)
+ => Match(input).Success;
+
+ //
+ // Escape
+ //
+
+ public static string Escape(string str)
+ {
+ int idx1 = str.IndexOfAny(EscapeChars);
+ if (idx1 == -1)
+ return str;
+ int idx0 = 0;
+ int len = ((java.lang.String) (object) str).length();
+ var sb = new java.lang.StringBuilder();
+ for (;;)
+ {
+ sb.append(((java.lang.String) (object) str).substring(idx0, idx1));
+ sb.append('\\');
+ var ch = ((java.lang.String) (object) str).charAt(idx1);
+ if (ch == '\u0009') ch = 't';
+ else if (ch == '\u000A') ch = 'n';
+ else if (ch == '\u000C') ch = 'f';
+ else if (ch == '\u000D') ch = 'r';
+ sb.append(ch);
+
+ if ( (idx0 = idx1 + 1) >= len
+ || (idx1 = str.IndexOfAny(EscapeChars, idx0)) == -1)
+ {
+ sb.append(((java.lang.String) (object) str).substring(idx0));
+ return sb.ToString();
+ }
+ }
+ }
+
+ [java.attr.RetainType] private static readonly char[] EscapeChars = {
+ '\u0009', '\u000A', '\u000C', '\u000D', '\u0020', // spaces
+ '#', '$', '(', ')', '*', '+', '.', '?', '[', '\\', '^', '{', '|' };
+ // |{^\[?.+*)($# SPC(32)TAB(9)0x000D,0x000C, 0x000A,0x0009
+
//
// ISerializable
//
diff --git a/Baselib/system.filter b/Baselib/system.filter
index 6de524f..4b5eb92 100644
--- a/Baselib/system.filter
+++ b/Baselib/system.filter
@@ -4,3 +4,5 @@ System.Collections.Generic.Stack`1
System.Collections.Generic.Queue`1
System.ComponentModel.CategoryAttribute
+
+System.Text.RegularExpressions.RegexOptions
diff --git a/CilToJava/src/CilMethod.cs b/CilToJava/src/CilMethod.cs
index c9a743e..aa3bb7a 100644
--- a/CilToJava/src/CilMethod.cs
+++ b/CilToJava/src/CilMethod.cs
@@ -644,6 +644,29 @@ namespace SpaceFlint.CilToJava
+ public static void FixNameForVirtualToStaticCall(JavaMethodRef method, CilType callClass)
+ {
+ // this method is called from CodeCall.ConvertVirtualToStaticCall,
+ // which converts a virtual call to a static call by inserting an
+ // initial 'this' parameter.
+ // if the target method was altered by AppendMethodNameSuffix,
+ // then we also have to insert the name for that initial 'this'.
+
+ string name = method.Name;
+ int idx = name.IndexOf(CilMain.OPEN_PARENS);
+ if (idx != -1)
+ {
+ string newName = name.Substring(0, idx)
+ + CilMain.OPEN_PARENS
+ + callClass.JavaName.Replace('.', '-')
+ + CilMain.CLOSE_PARENS
+ + name.Substring(idx);
+ method.Name = newName;
+ }
+ }
+
+
+
internal static bool CompareMethods(MethodDefinition m1, MethodDefinition m2)
{
if (m1.Name != m2.Name)
diff --git a/CilToJava/src/CodeArray.cs b/CilToJava/src/CodeArray.cs
index 770cd3c..e057a14 100644
--- a/CilToJava/src/CodeArray.cs
+++ b/CilToJava/src/CodeArray.cs
@@ -272,7 +272,8 @@ namespace SpaceFlint.CilToJava
else
{
if ( elemType.PrimitiveType == TypeCode.Int16
- && arrayType.PrimitiveType == TypeCode.Char)
+ && ( arrayType.PrimitiveType == TypeCode.Char
+ || arrayType.PrimitiveType == TypeCode.UInt16))
{
// ldelem.i2 with a char[] array, should be 'caload' not 'saload'
elemType = arrayType.AdjustRank(-arrayType.ArrayRank);
@@ -358,7 +359,8 @@ namespace SpaceFlint.CilToJava
else
{
if ( elemType.PrimitiveType == TypeCode.Int16
- && arrayType.PrimitiveType == TypeCode.Char)
+ && ( arrayType.PrimitiveType == TypeCode.Char
+ || arrayType.PrimitiveType == TypeCode.UInt16))
{
// stelem.i2 with a char[] array, should be 'castore' not 'sastore'
elemType = arrayType.AdjustRank(-arrayType.ArrayRank);
diff --git a/CilToJava/src/CodeCall.cs b/CilToJava/src/CodeCall.cs
index 77d4547..bf34c6b 100644
--- a/CilToJava/src/CodeCall.cs
+++ b/CilToJava/src/CodeCall.cs
@@ -398,6 +398,9 @@ namespace SpaceFlint.CilToJava
parameters[0].Type = JavaType.ObjectType;
}
+ else
+ CilMethod.FixNameForVirtualToStaticCall(tempMethod, callClass);
+
code.NewInstruction(0xB8 /* invokestatic */,
new JavaType(0, 0, callClass.JavaName), tempMethod);
diff --git a/CilToJava/src/CodeCompare.cs b/CilToJava/src/CodeCompare.cs
index 27264ae..6a4b3e8 100644
--- a/CilToJava/src/CodeCompare.cs
+++ b/CilToJava/src/CodeCompare.cs
@@ -748,9 +748,15 @@ namespace SpaceFlint.CilToJava
}
}
}
- else
+
+ stackMap.ResetLocalsInFrame((ushort) inst.Offset, resetLocals);
+
+ if (inst.OpCode.Code >= Code.Ceq && inst.OpCode.Code <= Code.Clt_Un)
{
- stackMap.ResetLocalsInFrame((ushort) inst.Offset, resetLocals);
+ // also reset the additional frame created while processing
+ // 'ceq'-type instructions, see also method Compare() above
+ stackMap.ResetLocalsInFrame(
+ (ushort) (inst.Offset + 1), resetLocals);
}
inst = inst.Next;
diff --git a/CilToJava/src/CodeMisc.cs b/CilToJava/src/CodeMisc.cs
index 3432d9c..7acd85d 100644
--- a/CilToJava/src/CodeMisc.cs
+++ b/CilToJava/src/CodeMisc.cs
@@ -267,12 +267,22 @@ namespace SpaceFlint.CilToJava
{
var dataType = CilType.From(typeRef);
- var stackTop1 = (CilType) code.StackMap.PopStack(CilMain.Where);
- var stackTop2 = (CilType) code.StackMap.PopStack(CilMain.Where);
- if (CodeSpan.LoadStore(false, stackTop2, null, dataType, code))
+ var valueType = (CilType) code.StackMap.PopStack(CilMain.Where);
+ var intoType = (CilType) code.StackMap.PopStack(CilMain.Where);
+ if (CodeSpan.LoadStore(false, intoType, null, dataType, code))
return;
- code.StackMap.PushStack(stackTop2);
- code.StackMap.PushStack(stackTop1);
+
+ if ( (! dataType.IsReference)
+ && intoType is BoxedType intoBoxedType
+ && dataType.PrimitiveType == intoBoxedType.UnboxedType.PrimitiveType)
+ {
+ // 'stobj primitive' with a primitive value on the stack
+ intoBoxedType.SetValueOV(code);
+ return;
+ }
+
+ code.StackMap.PushStack(intoType);
+ code.StackMap.PushStack(valueType);
GenericUtil.ValueCopy(dataType, code, true);
code.StackMap.PopStack(CilMain.Where);
diff --git a/CilToJava/src/GenericUtil.cs b/CilToJava/src/GenericUtil.cs
index 12908dd..d805cb6 100644
--- a/CilToJava/src/GenericUtil.cs
+++ b/CilToJava/src/GenericUtil.cs
@@ -768,13 +768,25 @@ namespace SpaceFlint.CilToJava
if (fromType.Equals(intoType))
return false; // no, if same type (by value)
+ // if casting to one of the non-generic types of that a string
+ // implements, and the source is either a string or an object
+
+ bool fromTypeIsObjectType = fromType.Equals(JavaType.ObjectType);
+
+ if ( (fromTypeIsObjectType || fromType.Equals(JavaType.StringType))
+ && ( intoType.JavaName == "system.IComparable"
+ || intoType.JavaName == "system.IConvertible"))
+ {
+ return true;
+ }
+
// if casting to one of the types that any array should implememt,
// and the castee is an array, or 'object', or one of those types,
// then always call TestCast/CallCast, because we might have to
// create a helper proxy for an array object
- bool fromTypeMayBeArray = ( fromType.ArrayRank != 0
- || fromType.Equals(JavaType.ObjectType)
+ bool fromTypeMayBeArray = ( fromTypeIsObjectType
+ || fromType.ArrayRank != 0
|| IsArray(fromType.JavaName));
return (fromTypeMayBeArray && IsArray(intoType.JavaName));
diff --git a/Tests/src/TestCompareInfo.cs b/Tests/src/TestString.cs
similarity index 56%
rename from Tests/src/TestCompareInfo.cs
rename to Tests/src/TestString.cs
index 16d4b63..2108ef9 100644
--- a/Tests/src/TestCompareInfo.cs
+++ b/Tests/src/TestString.cs
@@ -6,19 +6,102 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Tests
{
[TestClass]
- public class TestCompareInfo : BaseTest
+ public class TestString : BaseTest
{
public override void TestMain()
{
- TestIndexOf1();
+ TestSplit();
+ TestIndexOf();
+ TestCompare();
+ TestCast("Test");
}
- //
- //
- //
- static void TestIndexOf1()
+
+ void TestSplit()
+ {
+ // This example demonstrates the String() methods that use
+ // the StringSplitOptions enumeration.
+ string s1 = ",ONE,,TWO,,,THREE,,";
+ string s2 = "[stop]" +
+ "ONE[stop][stop]" +
+ "TWO[stop][stop][stop]" +
+ "THREE[stop][stop]";
+ char[] charSeparators = new char[] {','};
+ string[] stringSeparators = new string[] {"[stop]"};
+ string[] result;
+ // ------------------------------------------------------------------------------
+ // Split a string delimited by characters.
+ // ------------------------------------------------------------------------------
+ // Display the original string and delimiter characters.
+ Console.WriteLine("String = \"{0}\" Delimiter = '{1}'", s1, charSeparators[0]);
+
+ // Split a string delimited by characters and return all elements.
+ Console.Write("Split by char, omit=0: ");
+ result = s1.Split(charSeparators, StringSplitOptions.None);
+ Show(result);
+
+ // Split a string delimited by characters and return all non-empty elements.
+ Console.Write("Split by char, omit=1: ");
+ result = s1.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);
+ Show(result);
+
+ // Split the original string into the string and empty string before the
+ // delimiter and the remainder of the original string after the delimiter.
+ Console.Write("Split by char, omit=0, lim=2: ");
+ result = s1.Split(charSeparators, 2, StringSplitOptions.None);
+ Show(result);
+
+ // Split the original string into the string after the delimiter and the
+ // remainder of the original string after the delimiter.
+ Console.Write("Split by char, omit=1, lim=2: ");
+ result = s1.Split(charSeparators, 2, StringSplitOptions.RemoveEmptyEntries);
+ Show(result);
+
+ // ------------------------------------------------------------------------------
+ // Split a string delimited by another string.
+ // ------------------------------------------------------------------------------
+ // Display the original string and delimiter string.
+ Console.WriteLine("String = \"{0}\" Delimiter = \"{1}\"", s2, stringSeparators[0]);
+
+ // Split a string delimited by another string and return all elements.
+ Console.Write("Split by str, omit=0: ");
+ result = s2.Split(stringSeparators, StringSplitOptions.None);
+ Show(result);
+
+ // Split the original string at the delimiter and return all non-empty elements.
+ Console.Write("Split by str, omit=1: ");
+ result = s2.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries);
+ Show(result);
+
+ // Split the original string into the empty string before the
+ // delimiter and the remainder of the original string after the delimiter.
+ Console.Write("Split by str, omit=0, lim=2: ");
+ result = s2.Split(stringSeparators, 2, StringSplitOptions.None);
+ Show(result);
+
+ // Split the original string into the string after the delimiter and the
+ // remainder of the original string after the delimiter.
+ Console.Write("Split by str, omit=1, lim=2: ");
+ result = s2.Split(stringSeparators, 2, StringSplitOptions.RemoveEmptyEntries);
+ Show(result);
+
+ // Display the array of separated strings using a local function
+ void Show(string[] entries)
+ {
+ Console.Write("{0} results: ", entries.Length);
+ foreach (string entry in entries)
+ {
+ Console.Write("<{0}>", entry);
+ }
+ Console.WriteLine();
+ }
+ }
+
+
+
+ static void TestIndexOf()
{
// based on examples in documentation page for
// System.Globalization.CompareInfo.IndexOf methods
@@ -109,14 +192,44 @@ namespace Tests
PrintMarker( " Ü : ", -1, myComp.LastIndexOf( myStr, 'Ü', iS, CompareOptions.IgnoreCase ) );
PrintMarker( " ü : ", -1, myComp.LastIndexOf( myStr, 'ü', iS, CompareOptions.IgnoreCase ) );
Console.WriteLine();
+
+ static void PrintMarker( String Prefix, int First, int Last ) {
+ if (First > -1) Console.Write($"\t\tFirst({First})");
+ if (Last > -1) Console.Write($"\t\tLast({First})");
+ if (First < 0 && Last < 0)
+ Console.Write($"\t\tNone\t");
+ }
}
- public static void PrintMarker( String Prefix, int First, int Last ) {
- if (First > -1) Console.Write($"\t\tFirst({First})");
- if (Last > -1) Console.Write($"\t\tLast({First})");
- if (First < 0 && Last < 0)
- Console.Write($"\t\tNone\t");
+
+
+ void TestCompare()
+ {
+ // Defines the strings to compare.
+ String myStr1 = "My Uncle Bill's clients";
+ String myStr2 = "My uncle bill's clients";
+
+ // Creates a CompareInfo that uses the InvariantCulture.
+ CompareInfo myComp = CultureInfo.InvariantCulture.CompareInfo;
+
+ // Compares two strings using myComp.
+ Console.WriteLine( "Comparing \"{0}\" and \"{1}\"", myStr1, myStr2 );
+ Console.WriteLine( " With no CompareOptions : {0}", myComp.Compare( myStr1, myStr2 ) );
+ Console.WriteLine( " With None : {0}", myComp.Compare( myStr1, myStr2, CompareOptions.None ) );
+ Console.WriteLine( " With Ordinal : {0}", myComp.Compare( myStr1, myStr2, CompareOptions.Ordinal ) );
+ //Console.WriteLine( " With StringSort : {0}", myComp.Compare( myStr1, myStr2, CompareOptions.StringSort ) );
+ Console.WriteLine( " With IgnoreCase : {0}", myComp.Compare( myStr1, myStr2, CompareOptions.IgnoreCase ) );
+ //Console.WriteLine( " With IgnoreSymbols : {0}", myComp.Compare( myStr1, myStr2, CompareOptions.IgnoreSymbols ) );
+ //Console.WriteLine( " With IgnoreCase and IgnoreSymbols : {0}", myComp.Compare( myStr1, myStr2, CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols ) );
}
+
+
+
+ void TestCast(object str)
+ {
+ Console.WriteLine("Convertible? " + ((str as IConvertible) != null)
+ + " Comparable? " + ((str as IComparable) != null));
+ }
+
}
}
-
diff --git a/USAGE.md b/USAGE.md
index b6aacb0..740f56c 100644
--- a/USAGE.md
+++ b/USAGE.md
@@ -93,5 +93,3 @@ Here are some known differences, deficiencies and incompatibilities of the Blueb
- Standard numeric format strings are supported, but a custom format, or an `IFormatProvider` which also implements `NumberFormatInfo` will cause `ToString` functions to throw an exception.
- Non-ordinal, culture-dependant string comparisons and casing are not 100% same, because of differences between Windows NLS and the `java.text` package.
-
-- `String` is not castable to `IConvertible` or to the non-generic `IComparable` interface.