Index: corlib.dll.sources =================================================================== --- corlib.dll.sources (revision 47945) +++ corlib.dll.sources (working copy) @@ -8,6 +8,14 @@ Microsoft.Win32/Win32RegistryApi.cs Microsoft.Win32/Win32ResultCode.cs Microsoft.Win32.SafeHandles/SafeFileHandle.cs +Mono.Globalization.Unicode/CodePointIndexer.cs +Mono.Globalization.Unicode/MSCompatUnicodeTable.cs +Mono.Globalization.Unicode/MSCompatUnicodeTableUtil.cs +Mono.Globalization.Unicode/SimpleCollator.cs +Mono.Globalization.Unicode/SortKey.cs +Mono.Globalization.Unicode/SortKeyBuffer.cs +Mono.Globalization.Unicode/Normalization.cs +Mono.Globalization.Unicode/NormalizationTableUtil.cs Mono/Runtime.cs Mono.Math/BigInteger.cs Mono.Math.Prime/ConfidenceFactor.cs @@ -303,7 +311,6 @@ System.Globalization/NumberFormatInfo.cs System.Globalization/NumberStyles.cs System.Globalization/RegionInfo.cs -System.Globalization/SortKey.cs System.Globalization/StringInfo.cs System.Globalization/TaiwanCalendar.cs System.Globalization/TextElementEnumerator.cs Index: Makefile =================================================================== --- Makefile (revision 47945) +++ Makefile (working copy) @@ -3,6 +3,15 @@ include ../../build/rules.make export __SECURITY_BOOTSTRAP_DB=$(topdir)/class/corlib +RESOURCE_FILES = \ + collation.core.bin \ + collation.tailoring.bin \ + collation.cjkCHS.bin \ + collation.cjkCHT.bin \ + collation.cjkJA.bin \ + collation.cjkKO.bin \ + collation.cjkKOlv2.bin + corlib_flags = -unsafe -nostdlib LOCAL_MCS_FLAGS = -nowarn:169,612,618,649 -d:INSIDE_CORLIB @@ -12,7 +21,7 @@ LIBRARY = corlib.dll LIBRARY_NAME = mscorlib.dll -LIB_MCS_FLAGS = $(corlib_flags) +LIB_MCS_FLAGS = $(corlib_flags) $(RESOURCE_FILES:%=/resource:%) LIBRARY_USE_INTERMEDIATE_FILE = yes LIBRARY_COMPILE = $(BOOT_COMPILE) Index: System/String.cs =================================================================== --- System/String.cs (revision 47945) +++ System/String.cs (working copy) @@ -38,6 +38,7 @@ #if NET_2_0 using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; +using Mono.Globalization.Unicode; #endif namespace System @@ -714,6 +715,44 @@ return (value == null) || (value.Length == 0); } + public string Normalize () + { + return Normalize (NormalizationForm.FormC); + } + + public string Normalize (NormalizationForm form) + { + switch (form) { + default: + return Normalization.Normalize (this, 0); + case NormalizationForm.FormD: + return Normalization.Normalize (this, 1); + case NormalizationForm.FormKC: + return Normalization.Normalize (this, 2); + case NormalizationForm.FormKD: + return Normalization.Normalize (this, 3); + } + } + + public bool IsNormalized () + { + return IsNormalized (NormalizationForm.FormC); + } + + public bool IsNormalized (NormalizationForm form) + { + switch (form) { + default: + return Normalization.IsNormalized (this, 0); + case NormalizationForm.FormD: + return Normalization.IsNormalized (this, 1); + case NormalizationForm.FormKC: + return Normalization.IsNormalized (this, 2); + case NormalizationForm.FormKD: + return Normalization.IsNormalized (this, 3); + } + } + public string Remove (int startIndex) { if (startIndex < 0) @@ -768,7 +807,7 @@ if (this.length < value.length) return false; - return (0 == Compare (this, 0, value, 0 , value.length)); + return CultureInfo.CurrentCulture.CompareInfo.IsPrefix (this, value); } /* This method is culture insensitive */ Index: System.Globalization/CompareInfo.cs =================================================================== --- System.Globalization/CompareInfo.cs (revision 47945) +++ System.Globalization/CompareInfo.cs (working copy) @@ -34,12 +34,21 @@ using System.Reflection; using System.Runtime.Serialization; using System.Runtime.CompilerServices; +using Mono.Globalization.Unicode; namespace System.Globalization { [Serializable] public class CompareInfo : IDeserializationCallback { + static readonly bool useManagedCollation = + Environment.GetEnvironmentVariable ("MONO_USE_MANAGED_COLLATION") + == "yes"; + + public static bool UseManagedCollation { + get { return useManagedCollation && MSCompatUnicodeTable.IsReady; } + } + // Keep in synch with MonoCompareInfo in the runtime. private int culture; [NonSerialized] @@ -47,6 +56,9 @@ [NonSerialized] private IntPtr ICU_collator; private int win32LCID; // Unused, but MS.NET serializes this + + [NonSerialized] + SimpleCollator collator; /* Hide the .ctor() */ CompareInfo() {} @@ -57,39 +69,56 @@ internal CompareInfo (CultureInfo ci) { this.culture = ci.LCID; - this.icu_name = ci.IcuName; - this.construct_compareinfo (icu_name); + if (UseManagedCollation) + collator = new SimpleCollator (ci); + else { + this.icu_name = ci.IcuName; + this.construct_compareinfo (icu_name); + } } [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern void free_internal_collator (); - + ~CompareInfo () { free_internal_collator (); } - - + [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern int internal_compare (string str1, int offset1, int length1, string str2, int offset2, int length2, CompareOptions options); + private int internal_compare_managed (string str1, int offset1, + int length1, string str2, + int offset2, int length2, + CompareOptions options) + { + return collator.Compare (str1, offset1, length1, + str2, offset2, length2, options); + } + + private int internal_compare_switch (string str1, int offset1, + int length1, string str2, + int offset2, int length2, + CompareOptions options) + { + return UseManagedCollation ? + internal_compare_managed (str1, offset1, length1, + str2, offset2, length2, options) : + internal_compare (str1, offset1, length1, + str2, offset2, length2, options); + } + public virtual int Compare (string string1, string string2) { - /* Short cuts... */ - if(string1.Length == 0) { - if(string2.Length == 0) { - return(0); - } else { - return(-1); - } - } else if(string2.Length == 0) { - return(1); - } + /* Short cut... */ + if(string1.Length == 0 && string2.Length == 0) + return(0); - return(internal_compare (string1, 0, string1.Length, + return(internal_compare_switch (string1, 0, string1.Length, string2, 0, string2.Length, CompareOptions.None)); } @@ -97,18 +126,11 @@ public virtual int Compare (string string1, string string2, CompareOptions options) { - /* Short cuts... */ - if(string1.Length == 0) { - if(string2.Length == 0) { - return(0); - } else { - return(-1); - } - } else if(string2.Length == 0) { - return(1); - } + /* Short cut... */ + if(string1.Length == 0 && string2.Length == 0) + return(0); - return(internal_compare (string1, 0, string1.Length, + return(internal_compare_switch (string1, 0, string1.Length, string2, 0, string2.Length, options)); } @@ -121,18 +143,9 @@ * the offset >= string length specified check * in the process...) */ - if(string1.Length == 0 || - offset1 == string1.Length) { - if(string2.Length == 0 || - offset2 == string2.Length) { - return(0); - } else { - return(-1); - } - } else if(string2.Length == 0 || - offset2 == string2.Length) { - return(1); - } + if ((string1.Length == 0 || offset1 == string1.Length) && + (string2.Length == 0 || offset2 == string2.Length)) + return(0); if(offset1 < 0 || offset2 < 0) { throw new ArgumentOutOfRangeException ("Offsets must not be less than zero"); @@ -146,7 +159,7 @@ throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2"); } - return(internal_compare (string1, offset1, + return(internal_compare_switch (string1, offset1, string1.Length-offset1, string2, offset2, string2.Length-offset2, @@ -162,18 +175,9 @@ * the offset >= string length specified check * in the process...) */ - if(string1.Length == 0 || - offset1 == string1.Length) { - if(string2.Length == 0 || - offset2 == string2.Length) { - return(0); - } else { - return(-1); - } - } else if(string2.Length == 0 || - offset2 == string2.Length) { - return(1); - } + if((string1.Length == 0 || offset1 == string1.Length) && + (string2.Length == 0 || offset2 == string2.Length)) + return(0); if(offset1 < 0 || offset2 < 0) { throw new ArgumentOutOfRangeException ("Offsets must not be less than zero"); @@ -187,7 +191,7 @@ throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2"); } - return(internal_compare (string1, offset1, + return(internal_compare_switch (string1, offset1, string1.Length-offset1, string2, offset2, string2.Length-offset1, @@ -203,21 +207,13 @@ * the offset >= string length specified check * in the process...) */ - if(string1.Length == 0 || - offset1 == string1.Length || - length1 == 0) { - if(string2.Length == 0 || - offset2 == string2.Length || - length2 == 0) { - return(0); - } else { - return(-1); - } - } else if(string2.Length == 0 || - offset2 == string2.Length || - length2 == 0) { - return(1); - } + if((string1.Length == 0 || + offset1 == string1.Length || + length1 == 0) && + (string2.Length == 0 || + offset2 == string2.Length || + length2 == 0)) + return(0); if(offset1 < 0 || length1 < 0 || offset2 < 0 || length2 < 0) { @@ -240,7 +236,7 @@ throw new ArgumentOutOfRangeException ("Length2 is greater than the number of characters from offset2 to the end of string2"); } - return(internal_compare (string1, offset1, length1, + return(internal_compare_switch (string1, offset1, length1, string2, offset2, length2, CompareOptions.None)); } @@ -255,21 +251,13 @@ * the offset >= string length specified check * in the process...) */ - if(string1.Length == 0 || - offset1 == string1.Length || - length1 == 0) { - if(string2.Length == 0 || - offset2 == string2.Length || - length2 == 0) { + if((string1.Length == 0 || + offset1 == string1.Length || + length1 == 0) && + (string2.Length == 0 || + offset2 == string2.Length || + length2 == 0)) return(0); - } else { - return(-1); - } - } else if(string2.Length == 0 || - offset2 == string2.Length || - length2 == 0) { - return(1); - } if(offset1 < 0 || length1 < 0 || offset2 < 0 || length2 < 0) { @@ -292,7 +280,7 @@ throw new ArgumentOutOfRangeException ("Length2 is greater than the number of characters from offset2 to the end of string2"); } - return(internal_compare (string1, offset1, length1, + return(internal_compare_switch (string1, offset1, length1, string2, offset2, length2, options)); } @@ -372,6 +360,8 @@ public virtual SortKey GetSortKey(string source, CompareOptions options) { + if (UseManagedCollation) + return collator.GetSortKey (source, options); SortKey key=new SortKey (culture, source, options); /* Need to do the icall here instead of in the @@ -460,7 +450,26 @@ int count, char value, CompareOptions options, bool first); - + + private int internal_index_managed (string s, int sindex, + int count, char c, CompareOptions opt, + bool first) + { + return first ? + collator.IndexOf (s, c, sindex, count, opt) : + collator.LastIndexOf (s, c, sindex, count, opt); + } + + private int internal_index_switch (string s, int sindex, + int count, char c, CompareOptions opt, + bool first) + { + return UseManagedCollation && + (CompareOptions.Ordinal & opt) == 0 ? + internal_index_managed (s, sindex, count, c, opt, first) : + internal_index (s, sindex, count, c, opt, first); + } + public virtual int IndexOf (string source, char value, int startIndex, int count, CompareOptions options) @@ -492,7 +501,7 @@ } return(-1); } else { - return (internal_index (source, startIndex, + return (internal_index_switch (source, startIndex, count, value, options, true)); } @@ -503,7 +512,26 @@ int count, string value, CompareOptions options, bool first); - + + private int internal_index_managed (string s1, int sindex, + int count, string s2, CompareOptions opt, + bool first) + { + return first ? + collator.IndexOf (s1, s2, sindex, count, opt) : + collator.LastIndexOf (s1, s2, sindex, count, opt); + } + + private int internal_index_switch (string s1, int sindex, + int count, string s2, CompareOptions opt, + bool first) + { + return UseManagedCollation && + (CompareOptions.Ordinal & opt) == 0 ? + internal_index_managed (s1, sindex, count, s2, opt, first) : + internal_index (s1, sindex, count, s2, opt, first); + } + public virtual int IndexOf (string source, string value, int startIndex, int count, CompareOptions options) @@ -524,7 +552,7 @@ return(-1); } - return (internal_index (source, startIndex, count, + return (internal_index_switch (source, startIndex, count, value, options, true)); } @@ -543,6 +571,9 @@ throw new ArgumentNullException("prefix"); } + if (UseManagedCollation) + return collator.IsPrefix (source, prefix, options); + if(source.Length < prefix.Length) { return(false); } else { @@ -567,6 +598,9 @@ throw new ArgumentNullException("suffix"); } + if (UseManagedCollation) + return collator.IsSuffix (source, suffix, options); + if(source.Length < suffix.Length) { return(false); } else { @@ -682,7 +716,7 @@ } return(-1); } else { - return (internal_index (source, startIndex, + return (internal_index_switch (source, startIndex, count, value, options, false)); } @@ -713,7 +747,7 @@ return(0); } - return(internal_index (source, startIndex, count, + return(internal_index_switch (source, startIndex, count, value, options, false)); } @@ -724,13 +758,17 @@ void IDeserializationCallback.OnDeserialization(object sender) { - /* This will build the ICU collator, and store - * the pointer in ICU_collator - */ - try { - this.construct_compareinfo (icu_name); - } catch { - ICU_collator=IntPtr.Zero; + if (UseManagedCollation) { + collator = new SimpleCollator (new CultureInfo (culture)); + } else { + /* This will build the ICU collator, and store + * the pointer in ICU_collator + */ + try { + this.construct_compareinfo (icu_name); + } catch { + ICU_collator=IntPtr.Zero; + } } }