| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812 |
- //
- // System.Globalization.CompareInfo
- //
- // Authors:
- // Rodrigo Moya ([email protected])
- // Dick Porter ([email protected])
- //
- // (C) Ximian, Inc. 2002
- //
- //
- // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- 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.internalGetEnvironmentVariable ("MONO_DISABLE_MANAGED_COLLATION")
- != "yes";
- internal static bool UseManagedCollation {
- get { return useManagedCollation && MSCompatUnicodeTable.IsReady; }
- }
- // Keep in synch with MonoCompareInfo in the runtime.
- private int culture;
- [NonSerialized]
- private string icu_name;
- [NonSerialized]
- private IntPtr ICU_collator;
- private int win32LCID; // Unused, but MS.NET serializes this
- [NonSerialized]
- SimpleCollator collator;
-
- /* Hide the .ctor() */
- CompareInfo() {}
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern void construct_compareinfo (string locale);
-
- internal CompareInfo (CultureInfo ci)
- {
- this.culture = ci.LCID;
- 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 cut... */
- if(string1.Length == 0 && string2.Length == 0)
- return(0);
- return(internal_compare_switch (string1, 0, string1.Length,
- string2, 0, string2.Length,
- CompareOptions.None));
- }
- public virtual int Compare (string string1, string string2,
- CompareOptions options)
- {
- /* Short cut... */
- if(string1.Length == 0 && string2.Length == 0)
- return(0);
- return(internal_compare_switch (string1, 0, string1.Length,
- string2, 0, string2.Length,
- options));
- }
- 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));
- }
- public virtual int Compare (string string1, int offset1,
- string string2, int offset2,
- CompareOptions options)
- {
- /* 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-offset1,
- options));
- }
- public virtual int Compare (string string1, int offset1,
- 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));
- }
- [MonoTODO("Add support for CompareOptions.OrdinalIgnoreCase")]
- public virtual int Compare (string string1, int offset1,
- int length1, string string2,
- int offset2, int length2,
- CompareOptions options)
- {
- /* 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,
- options));
- }
- public override bool Equals(object value)
- {
- CompareInfo other=value as CompareInfo;
- if(other==null) {
- return(false);
- }
-
- return(other.culture==culture);
- }
- public static CompareInfo GetCompareInfo(int culture)
- {
- return(new CultureInfo (culture).CompareInfo);
- }
- public static CompareInfo GetCompareInfo(string name)
- {
- if(name == null) {
- throw new ArgumentNullException("name");
- }
- return(new CultureInfo (name).CompareInfo);
- }
- public static CompareInfo GetCompareInfo(int culture,
- Assembly assembly)
- {
- /* The assembly parameter is supposedly there
- * to allow some sort of compare algorithm
- * versioning.
- */
- if(assembly == null) {
- throw new ArgumentNullException("assembly");
- }
- if(assembly!=typeof (Object).Module.Assembly) {
- throw new ArgumentException ("Assembly is an invalid type");
- }
- return(GetCompareInfo (culture));
- }
- public static CompareInfo GetCompareInfo(string name,
- Assembly assembly)
- {
- /* The assembly parameter is supposedly there
- * to allow some sort of compare algorithm
- * versioning.
- */
- if(name == null) {
- throw new ArgumentNullException("name");
- }
- if(assembly == null) {
- throw new ArgumentNullException("assembly");
- }
- if(assembly!=typeof (Object).Module.Assembly) {
- throw new ArgumentException ("Assembly is an invalid type");
- }
- return(GetCompareInfo (name));
- }
- public override int GetHashCode()
- {
- return(LCID);
- }
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern void assign_sortkey (object key, string source,
- CompareOptions options);
-
- public virtual SortKey GetSortKey(string source)
- {
- return(GetSortKey (source, CompareOptions.None));
- }
- 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
- * SortKey constructor, as we need access to
- * this instance's collator.
- */
- assign_sortkey (key, source, options);
-
- return(key);
- }
- public virtual int IndexOf (string source, char value)
- {
- return(IndexOf (source, value, 0, source.Length,
- CompareOptions.None));
- }
- public virtual int IndexOf (string source, string value)
- {
- return(IndexOf (source, value, 0, source.Length,
- CompareOptions.None));
- }
- public virtual int IndexOf (string source, char value,
- CompareOptions options)
- {
- return(IndexOf (source, value, 0, source.Length,
- options));
- }
- public virtual int IndexOf (string source, char value,
- int startIndex)
- {
- return(IndexOf (source, value, startIndex,
- source.Length - startIndex,
- CompareOptions.None));
- }
-
- public virtual int IndexOf (string source, string value,
- CompareOptions options)
- {
- return(IndexOf (source, value, 0, source.Length,
- options));
- }
- public virtual int IndexOf (string source, string value,
- int startIndex)
- {
- return(IndexOf (source, value, startIndex,
- source.Length - startIndex,
- CompareOptions.None));
- }
- public virtual int IndexOf (string source, char value,
- int startIndex,
- CompareOptions options)
- {
- return(IndexOf (source, value, startIndex,
- source.Length - startIndex, options));
- }
- public virtual int IndexOf (string source, char value,
- int startIndex, int count)
- {
- return IndexOf (source, value, startIndex, count,
- CompareOptions.None);
- }
- public virtual int IndexOf (string source, string value,
- int startIndex,
- CompareOptions options)
- {
- return(IndexOf (source, value, startIndex,
- source.Length - startIndex, options));
- }
- public virtual int IndexOf (string source, string value,
- int startIndex, int count)
- {
- return(IndexOf (source, value, startIndex, count,
- CompareOptions.None));
- }
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern int internal_index (string source, int sindex,
- 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 &&
- #if NET_2_0
- ((CompareOptions.Ordinal & opt) == 0 ||
- (CompareOptions.OrdinalIgnoreCase & opt) == 0) ?
- #else
- (CompareOptions.Ordinal & opt) == 0 ?
- #endif
- internal_index_managed (s, sindex, count, c, opt, first) :
- internal_index (s, sindex, count, c, opt, first);
- }
- [MonoTODO("Add support for CompareOptions.OrdinalIgnoreCase")]
- public virtual int IndexOf (string source, char value,
- int startIndex, int count,
- CompareOptions options)
- {
- if(source==null) {
- throw new ArgumentNullException ("source");
- }
- if(startIndex<0) {
- throw new ArgumentOutOfRangeException ("startIndex");
- }
- 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(count==0) {
- return(-1);
- }
- if((options & CompareOptions.Ordinal)!=0) {
- for(int pos=startIndex;
- pos < startIndex + count;
- pos++) {
- if(source[pos]==value) {
- return(pos);
- }
- }
- return(-1);
- } else {
- return (internal_index_switch (source, startIndex,
- count, value, options,
- true));
- }
- }
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern int internal_index (string source, int sindex,
- 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 &&
- #if NET_2_0
- ((CompareOptions.Ordinal & opt) == 0 ||
- (CompareOptions.OrdinalIgnoreCase & opt) == 0) ?
- #else
- (CompareOptions.Ordinal & opt) == 0 ?
- #endif
- internal_index_managed (s1, sindex, count, s2, opt, first) :
- internal_index (s1, sindex, count, s2, opt, first);
- }
- [MonoTODO("Add support for CompareOptions.OrdinalIgnoreCase")]
- public virtual int IndexOf (string source, string value,
- int startIndex, int count,
- CompareOptions options)
- {
- if(source==null) {
- throw new ArgumentNullException ("source");
- }
- if(value==null) {
- throw new ArgumentNullException ("value");
- }
- if(startIndex<0) {
- throw new ArgumentOutOfRangeException ("startIndex");
- }
- if(count<0 || (source.Length - startIndex) < count) {
- throw new ArgumentOutOfRangeException ("count");
- }
- if(count==0) {
- return(-1);
- }
- return (internal_index_switch (source, startIndex, count,
- value, options, true));
- }
- public virtual bool IsPrefix(string source, string prefix)
- {
- return(IsPrefix (source, prefix, CompareOptions.None));
- }
- public virtual bool IsPrefix(string source, string prefix,
- CompareOptions options)
- {
- if(source == null) {
- throw new ArgumentNullException("source");
- }
- if(prefix == null) {
- throw new ArgumentNullException("prefix");
- }
- if (UseManagedCollation)
- return collator.IsPrefix (source, prefix, options);
- if(source.Length < prefix.Length) {
- return(false);
- } else {
- return(Compare (source, 0, prefix.Length,
- prefix, 0, prefix.Length,
- options)==0);
- }
- }
- public virtual bool IsSuffix(string source, string suffix)
- {
- return(IsSuffix (source, suffix, CompareOptions.None));
- }
- public virtual bool IsSuffix(string source, string suffix,
- CompareOptions options)
- {
- if(source == null) {
- throw new ArgumentNullException("source");
- }
- if(suffix == null) {
- throw new ArgumentNullException("suffix");
- }
- if (UseManagedCollation)
- return collator.IsSuffix (source, suffix, options);
- if(source.Length < suffix.Length) {
- return(false);
- } else {
- return(Compare (source,
- source.Length - suffix.Length,
- suffix.Length, suffix, 0,
- suffix.Length, options)==0);
- }
- }
- public virtual int LastIndexOf(string source, char value)
- {
- return(LastIndexOf (source, value, source.Length - 1,
- source.Length, CompareOptions.None));
- }
- public virtual int LastIndexOf(string source, string value)
- {
- return(LastIndexOf (source, value, source.Length - 1,
- source.Length, CompareOptions.None));
- }
- public virtual int LastIndexOf(string source, char value,
- CompareOptions options)
- {
- return(LastIndexOf (source, value, source.Length - 1,
- source.Length, options));
- }
- public virtual int LastIndexOf(string source, char value,
- int startIndex)
- {
- return(LastIndexOf (source, value, startIndex,
- startIndex + 1,
- CompareOptions.None));
- }
- public virtual int LastIndexOf(string source, string value,
- CompareOptions options)
- {
- return(LastIndexOf (source, value, source.Length - 1,
- source.Length, options));
- }
- public virtual int LastIndexOf(string source, string value,
- int startIndex)
- {
- return(LastIndexOf (source, value, startIndex,
- startIndex + 1,
- CompareOptions.None));
- }
- public virtual int LastIndexOf(string source, char value,
- int startIndex,
- CompareOptions options)
- {
- return(LastIndexOf (source, value, startIndex,
- startIndex + 1,
- options));
- }
- public virtual int LastIndexOf(string source, char value,
- int startIndex, int count)
- {
- return(LastIndexOf (source, value, startIndex, count,
- CompareOptions.None));
- }
- public virtual int LastIndexOf(string source, string value,
- int startIndex,
- CompareOptions options)
- {
- return(LastIndexOf (source, value, startIndex,
- startIndex + 1,
- options));
- }
- public virtual int LastIndexOf(string source, string value,
- int startIndex, int count)
- {
- return(LastIndexOf (source, value, startIndex, count,
- CompareOptions.None));
- }
- [MonoTODO("Add support for CompareOptions.OrdinalIgnoreCase")]
- public virtual int LastIndexOf(string source, char value,
- int startIndex, int count,
- CompareOptions options)
- {
- if(source == null) {
- throw new ArgumentNullException("source");
- }
- if(startIndex < 0) {
- throw new ArgumentOutOfRangeException ("startIndex");
- }
- 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(count==0) {
- return(-1);
- }
- if((options & CompareOptions.Ordinal)!=0) {
- for(int pos=startIndex;
- pos > startIndex - count;
- pos--) {
- if(source[pos]==value) {
- return(pos);
- }
- }
- return(-1);
- } else {
- return (internal_index_switch (source, startIndex,
- count, value, options,
- false));
- }
- }
- public virtual int LastIndexOf(string source, string value,
- int startIndex, int count,
- CompareOptions options)
- {
- if(source == null) {
- throw new ArgumentNullException("source");
- }
- if(value == null) {
- throw new ArgumentNullException("value");
- }
- if(startIndex < 0) {
- throw new ArgumentOutOfRangeException ("startIndex");
- }
- if(count < 0 || (startIndex - count) < -1) {
- throw new ArgumentOutOfRangeException("count");
- }
- if(count == 0) {
- return(-1);
- }
- int valuelen=value.Length;
- if(valuelen==0) {
- return(0);
- }
- return(internal_index_switch (source, startIndex, count,
- value, options, false));
- }
- #if NET_2_0
- public bool IsSortable (char c)
- {
- return MSCompatUnicodeTable.IsSortable (c);
- }
- public bool IsSortable (string s)
- {
- return MSCompatUnicodeTable.IsSortable (s);
- }
- #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
- {
- get {
- return(culture);
- }
- }
- }
- }
|