X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem.Globalization%2FCompareInfo.cs;h=cb894d969f1d37d2f389a79fe4d39dde10254254;hb=f4774442eaf92333012ae8b0a431739b4efe22bf;hp=9cdee5fab7a070126ebf08fa8678bd0f684f7d1c;hpb=f84f760a1c8a8c0ec6ae16b7f38d14a49d329ad7;p=mono.git diff --git a/mcs/class/corlib/System.Globalization/CompareInfo.cs b/mcs/class/corlib/System.Globalization/CompareInfo.cs index 9cdee5fab7a..cb894d969f1 100644 --- a/mcs/class/corlib/System.Globalization/CompareInfo.cs +++ b/mcs/class/corlib/System.Globalization/CompareInfo.cs @@ -1,5 +1,5 @@ // -// System.Globalization.CompareInfo +// System.Globalization.CompareInfo.cs // // Authors: // Rodrigo Moya (rodrigo@ximian.com) @@ -32,65 +32,142 @@ // using System.Reflection; +using System.Collections; using System.Runtime.Serialization; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Mono.Globalization.Unicode; namespace System.Globalization { [Serializable] - public class CompareInfo : IDeserializationCallback - { + [StructLayout (LayoutKind.Sequential)] +#if !MOONLIGHT + [ComVisible (true)] + public class CompareInfo : IDeserializationCallback { + static readonly bool useManagedCollation = Environment.internalGetEnvironmentVariable ("MONO_DISABLE_MANAGED_COLLATION") - != "yes"; + != "yes" && MSCompatUnicodeTable.IsReady; internal static bool UseManagedCollation { - get { return useManagedCollation && MSCompatUnicodeTable.IsReady; } + get { return useManagedCollation; } } + void IDeserializationCallback.OnDeserialization(object sender) + { + 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; + } + */ + } + } + + //[MethodImplAttribute (MethodImplOptions.InternalCall)] + //private extern void construct_compareinfo (string locale); + + //[MethodImplAttribute (MethodImplOptions.InternalCall)] + //private extern void 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); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + private extern void assign_sortkey (object key, string source, + CompareOptions options); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + private extern int internal_index (string source, int sindex, + int count, char value, + CompareOptions options, + bool first); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + private extern int internal_index (string source, int sindex, + int count, string value, + CompareOptions options, + bool first); + +#else + public class CompareInfo { + internal static bool UseManagedCollation { + get { return true; } + } +#endif + const CompareOptions ValidCompareOptions_NoStringSort = + CompareOptions.None | CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | + CompareOptions.IgnoreSymbols | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | + CompareOptions.OrdinalIgnoreCase | CompareOptions.Ordinal; + + const CompareOptions ValidCompareOptions = ValidCompareOptions_NoStringSort | CompareOptions.StringSort; + // Keep in synch with MonoCompareInfo in the runtime. private int culture; - [NonSerialized] - private string icu_name; - [NonSerialized] - private IntPtr ICU_collator; +// [NonSerialized] +// private string icu_name; +// [NonSerialized] +// private IntPtr ICU_collator; + +#pragma warning disable 169 private int win32LCID; // Unused, but MS.NET serializes this +#pragma warning restore 169 + + readonly string m_name; // MS.NET serializes this [NonSerialized] SimpleCollator collator; - - /* Hide the .ctor() */ - CompareInfo() {} - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - private extern void construct_compareinfo (string locale); + + // Maps culture IDs to SimpleCollator objects + private static Hashtable collators; + + [NonSerialized] + // Protects access to 'collators' + private static object monitor = new Object (); internal CompareInfo (CultureInfo ci) { this.culture = ci.LCID; - if (UseManagedCollation) - collator = new SimpleCollator (ci); - else { + this.m_name = ci.Name; + if (UseManagedCollation) { + lock (monitor) { + if (collators == null) + collators = new Hashtable (); + collator = (SimpleCollator)collators [ci.LCID]; + if (collator == null) { + collator = new SimpleCollator (ci); + collators [ci.LCID] = collator; + } + } + } else { +/* +#if !MOONLIGHT this.icu_name = ci.IcuName; this.construct_compareinfo (icu_name); +#endif +*/ } } - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - private extern void free_internal_collator (); - +/* ~CompareInfo () { +#if !MOONLIGHT free_internal_collator (); +#endif } - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - private extern int internal_compare (string str1, int offset1, - int length1, string str2, - int offset2, int length2, - CompareOptions options); - +*/ +#if !MOONLIGHT private int internal_compare_managed (string str1, int offset1, int length1, string str2, int offset2, int length2, @@ -111,21 +188,35 @@ namespace System.Globalization internal_compare (str1, offset1, length1, str2, offset2, length2, options); } - +#else + private int internal_compare_switch (string str1, int offset1, + int length1, string str2, + int offset2, int length2, + CompareOptions options) + { + return collator.Compare (str1, offset1, length1, + str2, offset2, length2, options); + } +#endif public virtual int Compare (string string1, string string2) { - /* Short cut... */ - if(string1.Length == 0 && string2.Length == 0) - return(0); - - return(internal_compare_switch (string1, 0, string1.Length, - string2, 0, string2.Length, - CompareOptions.None)); + return Compare (string1, string2, CompareOptions.None); } public virtual int Compare (string string1, string string2, CompareOptions options) { + if ((options & ValidCompareOptions) != options) + throw new ArgumentException ("options"); + + if (string1 == null) { + if (string2 == null) + return 0; + return -1; + } + if (string2 == null) + return 1; + /* Short cut... */ if(string1.Length == 0 && string2.Length == 0) return(0); @@ -138,38 +229,24 @@ namespace System.Globalization public virtual int Compare (string string1, int offset1, string string2, int offset2) { - /* Not in the spec, but ms does these short - * cuts before checking the offsets (breaking - * the offset >= string length specified check - * in the process...) - */ - 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"); - } - - if(offset1 > string1.Length) { - throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1"); - } - - if(offset2 > string2.Length) { - throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2"); - } - - return(internal_compare_switch (string1, offset1, - string1.Length-offset1, - string2, offset2, - string2.Length-offset2, - CompareOptions.None)); + return Compare (string1, offset1, string2, offset2, CompareOptions.None); } public virtual int Compare (string string1, int offset1, string string2, int offset2, CompareOptions options) { + if ((options & ValidCompareOptions) != options) + throw new ArgumentException ("options"); + + if (string1 == null) { + if (string2 == null) + return 0; + return -1; + } + if (string2 == null) + return 1; + /* Not in the spec, but ms does these short * cuts before checking the offsets (breaking * the offset >= string length specified check @@ -194,7 +271,7 @@ namespace System.Globalization return(internal_compare_switch (string1, offset1, string1.Length-offset1, string2, offset2, - string2.Length-offset1, + string2.Length-offset2, options)); } @@ -202,51 +279,25 @@ namespace System.Globalization int length1, string string2, int offset2, int length2) { - /* Not in the spec, but ms does these short - * cuts before checking the offsets (breaking - * the offset >= string length specified check - * in the process...) - */ - 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) { - throw new ArgumentOutOfRangeException ("Offsets and lengths must not be less than zero"); - } - - if(offset1 > string1.Length) { - throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1"); - } - - if(offset2 > string2.Length) { - throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2"); - } - - if(length1 > string1.Length-offset1) { - throw new ArgumentOutOfRangeException ("Length1 is greater than the number of characters from offset1 to the end of string1"); - } - - if(length2 > string2.Length-offset2) { - throw new ArgumentOutOfRangeException ("Length2 is greater than the number of characters from offset2 to the end of string2"); - } - - return(internal_compare_switch (string1, offset1, length1, - string2, offset2, length2, - CompareOptions.None)); + return Compare (string1, offset1, length1, string2, offset2, length2, CompareOptions.None); } - [MonoTODO("Add support for CompareOptions.OrdinalIgnoreCase")] public virtual int Compare (string string1, int offset1, int length1, string string2, int offset2, int length2, CompareOptions options) { + if ((options & ValidCompareOptions) != options) + throw new ArgumentException ("options"); + + if (string1 == null) { + if (string2 == null) + return 0; + return -1; + } + if (string2 == null) + return 1; + /* Not in the spec, but ms does these short * cuts before checking the offsets (breaking * the offset >= string length specified check @@ -348,10 +399,6 @@ namespace System.Globalization { return(LCID); } - - [MethodImplAttribute (MethodImplOptions.InternalCall)] - private extern void assign_sortkey (object key, string source, - CompareOptions options); public virtual SortKey GetSortKey(string source) { @@ -361,6 +408,12 @@ namespace System.Globalization public virtual SortKey GetSortKey(string source, CompareOptions options) { + switch (options) { + case CompareOptions.Ordinal: + case CompareOptions.OrdinalIgnoreCase: + throw new ArgumentException ("Now allowed CompareOptions.", "options"); + } +#if !MOONLIGHT if (UseManagedCollation) return collator.GetSortKey (source, options); SortKey key=new SortKey (culture, source, options); @@ -372,6 +425,9 @@ namespace System.Globalization assign_sortkey (key, source, options); return(key); +#else + return collator.GetSortKey (source, options); +#endif } public virtual int IndexOf (string source, char value) @@ -446,12 +502,7 @@ namespace System.Globalization CompareOptions.None)); } - [MethodImplAttribute (MethodImplOptions.InternalCall)] - private extern int internal_index (string source, int sindex, - int count, char value, - CompareOptions options, - bool first); - +#if !MOONLIGHT private int internal_index_managed (string s, int sindex, int count, char c, CompareOptions opt, bool first) @@ -465,18 +516,25 @@ namespace System.Globalization int count, char c, CompareOptions opt, bool first) { - return UseManagedCollation && -#if NET_2_0 - ((CompareOptions.Ordinal & opt) == 0 || - (CompareOptions.OrdinalIgnoreCase & opt) == 0) ? -#else - (CompareOptions.Ordinal & opt) == 0 ? -#endif + // - forward IndexOf() icall is much faster than + // manged version, so always use icall. However, + // it does not work for OrdinalIgnoreCase, so + // do not avoid managed collator for that option. + return UseManagedCollation && ! (first && opt == CompareOptions.Ordinal) ? internal_index_managed (s, sindex, count, c, opt, first) : internal_index (s, sindex, count, c, opt, first); } +#else + private int internal_index_switch (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); + } +#endif - [MonoTODO("Add support for CompareOptions.OrdinalIgnoreCase")] public virtual int IndexOf (string source, char value, int startIndex, int count, CompareOptions options) @@ -490,9 +548,8 @@ namespace System.Globalization if(count<0 || (source.Length - startIndex) < count) { throw new ArgumentOutOfRangeException ("count"); } - if((options & CompareOptions.StringSort)!=0) { - throw new ArgumentException ("StringSort is not a valid CompareOption for this method"); - } + if ((options & ValidCompareOptions_NoStringSort) != options) + throw new ArgumentException ("options"); if(count==0) { return(-1); @@ -514,12 +571,7 @@ namespace System.Globalization } } - [MethodImplAttribute (MethodImplOptions.InternalCall)] - private extern int internal_index (string source, int sindex, - int count, string value, - CompareOptions options, - bool first); - +#if !MOONLIGHT private int internal_index_managed (string s1, int sindex, int count, string s2, CompareOptions opt, bool first) @@ -533,18 +585,25 @@ namespace System.Globalization int count, string s2, CompareOptions opt, bool first) { - return UseManagedCollation && -#if NET_2_0 - ((CompareOptions.Ordinal & opt) == 0 || - (CompareOptions.OrdinalIgnoreCase & opt) == 0) ? -#else - (CompareOptions.Ordinal & opt) == 0 ? -#endif + // - forward IndexOf() icall is much faster than + // manged version, so always use icall. However, + // it does not work for OrdinalIgnoreCase, so + // do not avoid managed collator for that option. + return UseManagedCollation && ! (first && opt == CompareOptions.Ordinal) ? internal_index_managed (s1, sindex, count, s2, opt, first) : internal_index (s1, sindex, count, s2, opt, first); } +#else + private int internal_index_switch (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); + } +#endif - [MonoTODO("Add support for CompareOptions.OrdinalIgnoreCase")] public virtual int IndexOf (string source, string value, int startIndex, int count, CompareOptions options) @@ -561,6 +620,11 @@ namespace System.Globalization if(count<0 || (source.Length - startIndex) < count) { throw new ArgumentOutOfRangeException ("count"); } + if ((options & ValidCompareOptions_NoStringSort) != options) + throw new ArgumentException ("options"); + if(value.Length==0) { + return(startIndex); + } if(count==0) { return(-1); } @@ -584,6 +648,9 @@ namespace System.Globalization throw new ArgumentNullException("prefix"); } + if ((options & ValidCompareOptions_NoStringSort) != options) + throw new ArgumentException ("options"); + if (UseManagedCollation) return collator.IsPrefix (source, prefix, options); @@ -611,6 +678,9 @@ namespace System.Globalization throw new ArgumentNullException("suffix"); } + if ((options & ValidCompareOptions_NoStringSort) != options) + throw new ArgumentException ("options"); + if (UseManagedCollation) return collator.IsSuffix (source, suffix, options); @@ -698,7 +768,6 @@ namespace System.Globalization CompareOptions.None)); } - [MonoTODO("Add support for CompareOptions.OrdinalIgnoreCase")] public virtual int LastIndexOf(string source, char value, int startIndex, int count, CompareOptions options) @@ -712,9 +781,8 @@ namespace System.Globalization if(count < 0 || (startIndex - count) < -1) { throw new ArgumentOutOfRangeException("count"); } - if((options & CompareOptions.StringSort)!=0) { - throw new ArgumentException ("StringSort is not a valid CompareOption for this method"); - } + if ((options & ValidCompareOptions_NoStringSort) != options) + throw new ArgumentException ("options"); if(count==0) { return(-1); @@ -752,61 +820,51 @@ namespace System.Globalization if(count < 0 || (startIndex - count) < -1) { throw new ArgumentOutOfRangeException("count"); } + if ((options & ValidCompareOptions_NoStringSort) != options) + throw new ArgumentException ("options"); if(count == 0) { return(-1); } int valuelen=value.Length; if(valuelen==0) { - return(0); + return(startIndex); } return(internal_index_switch (source, startIndex, count, value, options, false)); } -#if NET_2_0 - public static bool IsSortable (char c) + [ComVisible (false)] + public static bool IsSortable (char ch) { - return MSCompatUnicodeTable.IsSortable (c); + return MSCompatUnicodeTable.IsSortable (ch); } - public static bool IsSortable (string s) + [ComVisible (false)] + public static bool IsSortable (string text) { - return MSCompatUnicodeTable.IsSortable (s); + return MSCompatUnicodeTable.IsSortable (text); } -#endif public override string ToString() { return("CompareInfo - "+culture); } - void IDeserializationCallback.OnDeserialization(object sender) - { - 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; - } - } - } - /* LAMESPEC: not mentioned in the spec, but corcompare * shows it. Some documentation about what it does * would be nice. */ - public int LCID - { + public int LCID { get { - return(culture); + return culture; } } + + [ComVisible (false)] + public virtual string Name { + get { return m_name; } + } } }