Author: atsushi
Date: 2005-04-25 04:07:28 -0400 (Mon, 25 Apr 2005)
New Revision: 43534

Added:
   branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/Collator.cs
   
branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/CompareInfoImpl.cs
Modified:
   branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/ChangeLog
Log:
2005-04-25  Atsushi Enomoto  <[EMAIL PROTECTED]>

        * CompareInfoImpl.cs, Collator.cs : conceptual stuff (not working).



Modified: branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/ChangeLog
===================================================================
--- branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/ChangeLog      
2005-04-25 07:26:06 UTC (rev 43533)
+++ branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/ChangeLog      
2005-04-25 08:07:28 UTC (rev 43534)
@@ -1,5 +1,9 @@
 2005-04-25  Atsushi Enomoto  <[EMAIL PROTECTED]>
 
+       * CompareInfoImpl.cs, Collator.cs : conceptual stuff (not working).
+
+2005-04-25  Atsushi Enomoto  <[EMAIL PROTECTED]>
+
        * create-char-mapping-source.cs : Now it generates
          ToWidthInsensitive() from combining category <wide> and <narrow>.
        * MSCompatUnicodeTable.cs : added ToKanaTypeInsensitive() and

Added: branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/Collator.cs
===================================================================
--- branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/Collator.cs    
2005-04-25 07:26:06 UTC (rev 43533)
+++ branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/Collator.cs    
2005-04-25 08:07:28 UTC (rev 43534)
@@ -0,0 +1,368 @@
+//
+// Note that this is just a conceptual source and subject to changes.
+//
+
+using System;
+using System.Globalization;
+using System.Text;
+
+
+namespace Mono.Globalization.Unicode
+{
+       internal class CollatorComparer
+       {
+               struct CompareResult
+               {
+                       public int Result;
+                       public int Advance1;
+                       public int Advance2;
+
+                       public CompareResult (int result, int advance1, int 
advance2)
+                       {
+                               Result = result;
+                               Advance1 = advance1;
+                               Advance2 = advance2;
+                       }
+               }
+
+               public readonly Collator Collator;
+               public readonly CompareOptions Options;
+
+               private char [] nfdBuffer = new char [4];
+
+               public CollatorComparer (
+                       Collator c, CompareOptions opts)
+               {
+                       Collator = c;
+                       Options = opts;
+
+               }
+
+               // Below are normalization matters:
+               // - IgnoreCase -> use culture dependent ToLower()
+               // - IgnoreKanaType -> ToKanaTypeInsensitive().
+               // - IgnoreNonSpace -> IsIgnorableNonSpacing().
+               // - IgnoreSymbols -> IsIgnorableSymbol()
+               // - IgnoreWidth -> ToWidthInsensitive()
+               //
+               // It is independently considered, maybe as a tailored
+               // collation element table.
+               // - StringSort
+               //
+               // Even with CompareOptions.None both of Japanese katakana
+               // with voice mark"included" or "separate", while half-width
+               // katakana are distinguished unless IgnoreWidth is specified.
+               // So maybe canonical normalization is done.
+               public bool IsIgnorable (int i)
+               {
+                       if (MSCompatUnicodeTable.IsIgnorable (i))
+                               return true;
+                       if ((Options & CompareOptions.IgnoreWidth) != 0)
+                               i = MSCompatUnicodeTable.ToWidthInsensitive (i);
+                       if ((Options & CompareOptions.IgnoreKanaType) != 0)
+                               i = MSCompatUnicodeTable.ToKanaTypeInsensitive 
(i);
+                       if ((Options & CompareOptions.IgnoreCase) != 0 && i <= 
char.MaxValue)
+                               i = collator.Culture.ToLower ((char) i);
+                       if ((Options & CompareOptions.IgnoreSymbols) != 0
+                               && MSCompatUnicodeTable.IsIgnorableSymbol (i))
+                               return true;
+                       if ((Options & CompareOptions.IgnoreNonSpace) != 0
+                               && MSCompatUnicodeTable.IsIgnorableNonSpacing 
(i))
+                               return true;
+                       return false;
+               }
+
+               public int Compare (string s1, int start1, int len1,
+                       string s2, int start2, int len2)
+               {
+                       if (s1.Length < start1 + len1 ||
+                               s2.Length < start2 + len2)
+                               throw new ArgumentOutOfRangeException ("start 
and length must not be out of range of the string.");
+
+                       int min = len1 < len2 ? len1 : len2;
+                       int start = 0;
+
+                       while (true) {
+                               int stop = -1;
+                               for (int i = start; i < min; i++) {
+                                       if (s1 [start1 + i] != s2 [start2 + i]) 
{
+                                               stop = i;
+                                               break;
+                                       }
+                               }
+                               if (stop == -1)
+                                       break;
+
+                               // go back to where NFD-normalization should 
start.
+                               for (int i = stop; i >= start1; i--) {
+                                       if (!CharUnicodeInfo.IsUnsafe (s1 [i])) 
{
+                                               start1 = i;
+                                               break;
+                                       }
+                               }
+                               for (int i = stop; i >= start2; i--) {
+                                       if (!CharUnicodeInfo.IsUnsafe (s2 [i])) 
{
+                                               start2 = i;
+                                               break;
+                                       }
+                               }
+
+                               CompareResult ret = ComparePrimary (s1, start1, 
len1, s2, start2, len2);
+                               if (ret.Result == 0 && Strength >= 2)
+                                       ret = CompareSecondary (s1, start1, 
len1, s2, start2, len2);
+                               if (ret.Result == 0 && Strength >= 3)
+                                       ret = CompareThirtiary (s1, start1, 
len1, s2, start2, len2);
+                               if (ret.Result == 0 && Strength >= 4)
+                                       ret = CompareQuaternary (s1, start1, 
len1, s2, start2, len2);
+                               if (ret.Result != 0)
+                                       return ret.Result;
+                               start1 += ret.Advance1;
+                               start2 += ret.Advance2;
+                       }
+
+                       if (len1 == len2)
+                               return 0;
+                       return len2 > len1 ? 1 : -1;
+               }
+
+               public SortKey GetSortKey (string source)
+               {
+                       string n = Norm.Normalize (source, 1);
+
+                       throw new NotImplementedException ();
+               }
+
+               #region Normalization
+
+               //
+               // It handles UAX#15 Normalization, and optionally removal
+               // of ignored characters specified by CompareOptions.
+               //
+               private string Normalize (string source)
+               {
+                       for (int i = 0; i < nfdBuffer.Length; i++)
+                               nfdBuffer [i] = 0;
+
+                       StringBuilder sb = null;
+                       int start = 0;
+                       for (int i = 0; i < source.Length; i++) {
+/* This step is removed in the latest UCA v4.1.0.
+                               // handle Logical Order Exception
+                               char c = source [i];
+                               if ('\u0x0E40' <= c && c <= '\u0x0E44'
+                                       || '\u0x0EC0' <= c && c <= '\u0x0EC4')
+                                       ProcessLogicalException (ref sb,
+                                               source, i, ref start);
+*/
+                               // handle decomposition
+                               if (Norm.IsNoNfd (source, i))
+                                       ProcessNfd (ref sb, source, i, ref 
start);
+                       }
+                       if (sb != null)
+                               sb.Append (source, start, source.Length - 
start);
+                       return sb != null ? sb.ToString () : source);
+               }
+
+               private void ProcessLogicalException (ref StringBuilder sb,
+                       string s, int i, ref int start)
+               {
+                       // If no following character, do nothing.
+                       if (s.Length == i + 1)
+                               return;
+
+                       if (sb == null)
+                               sb = new StringBuilder (nfd.Length + 100);
+                       sb.Append (nfd, start, i);
+                       sb.Append (nfd [i + 1]);
+                       sb.Append (nfd [i++]);
+                       start = i + 1;
+               }
+
+/*
+               private void ProcessNfd (ref StringBuilder sb,
+                       string s, int i, ref int start)
+               {
+                       if (sb == null)
+                               sb = new StringBuilder (s.Length + 100);
+                       sb.Append (s, start, i);
+                       if (!Norm.IsMultiForm (s [i]))
+                               sb.Append (Norm.SingleForm (s [i]));
+                       else {
+                               Norm.MultiForm (s [i], nfdBuffer);
+                               for (int i = 0; i < nfdBuffer.Length; i++) {
+                                       if (nfdBuffer [i] == 0)
+                                               break;
+                                       sb.Append (nfdBuffer [i]);
+                               }
+                       }
+                       start = i + 1;
+               }
+*/
+               #endregion Normalization
+
+               public int IndexOf (string source, char value,
+                       int startIndex, int count)
+               {
+                       return IndexOf (source, new string (value, 1),
+                               startIndex, count);
+               }
+
+               public int IndexOf (string source, string value,
+                       int startIndex, int count)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public int LastIndexOf (string source, char value,
+                       int startIndex, int count)
+               {
+                       return LastIndexOf (source, new string (value, 1),
+                               startIndex, count);
+               }
+
+               public int LastIndexOf (string source, string value,
+                       int startIndex, int count)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public bool IsPrefix (string source, string prefix)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException("source");
+                       if (prefix == null)
+                               throw new ArgumentNullException("prefix");
+
+                       // quick check
+                       if (Compare (source, 0, prefix.Length,
+                               prefix, 0, prefix.Length) == 0)
+                               return true;
+
+                       // FIXME: it could be compared like above, after
+                       // some transliteration. It is sometimes too heavy.
+                       return IndexOf (source, prefix, 0, prefix.Length) == 0;
+               }
+
+               public bool IsSuffix (string source, string suffix)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException("source");
+                       if (suffix == null)
+                               throw new ArgumentNullException("suffix");
+
+                       // quick check
+                       if (Compare (source, source.Length - suffix.Length,
+                               suffix.Length, suffix, 0, suffix.Length) == 0)
+                               return true;
+
+                       // FIXME: it could be compared like above, after
+                       // some transliteration. It is sometimes too heavy.
+                       int i = LastIndexOf (source, suffix, 0, suffix.Length);
+                       // Note that LastIndexOf() might return different
+                       // value than suffix.Length. So we still have to check
+                       // the exact last sequence.
+                       return Compare (source, i, source.Length - i,
+                               suffix, 0, suffix.Length) == 0;
+               }
+       }
+
+       internal abstract class Collator
+       {
+               public abstract int Compare (string s1, int start1, int len1,
+                       string s2, int start2, int len2, CompareOptions 
options);
+               public abstract SortKey GetSortKey (string s, CompareOptions 
options);
+               public abstract int IndexOf (string s1, string value,
+                       int start, int len, CompareOptions options);
+               public abstract int IndexOf (string s1, char value,
+                       int start, int len, CompareOptions options);
+
+               public abstract Collator Clone ();
+       }
+
+       //
+       // Rule-based collator. It does not handle actual comparison, but 
+       // just holds parsed rules. Since comparison depends on options where
+       // we don't want to create CompareInfo instances every time and also
+       // don't want Monitor, it is done by CollatorComparer created with
+       // CultureInfo and CompareOptions.
+       //
+       internal class RuleBasedCollator : Collator
+       {
+               CultureInfo culture;
+               CollatorComparer defaultComparer;
+               CollatorComparer cache;
+
+               string ruleString;
+
+               public RuleBasedCollator (CultureInfo ci)
+               {
+                       culture = ci;
+                       defaultComparer = new CollatorComparer (
+                               this, CompareOptions.None);
+
+                       // FIXME: get tailored collatiojn element table (rule)
+                       // from resource or runtime internal, parse and store.
+               }
+
+               private RuleBasedCollator (RuleBasedCollator other)
+               {
+                       throw new NotImplementedException ();
+
+                       culture = other.culture;
+               }
+
+               public CultureInfo Culture {
+                       get { return culture; }
+               }
+
+               public override Collator Clone ()
+               {
+                       return new RuleBasedCollator (this);
+               }
+
+               private CollatorComparer PopulateComparer (CompareOptions 
options)
+               {
+                       CollatorComparer c = defaultComparer;
+                       if (c.Options != options)
+                               c = new CollatorComparer (this, options);
+                       else {
+                               c = cache;
+                               if (c == null || c.Options == options)
+                                       c = new CollatorComparer (this, 
options);
+                               cache = c;
+                       }
+                       return c;
+               }
+
+               // This must be thread safe.
+               // To avoid lock and consumptive creation, here we use
+               // default comparer instance and additional cache.
+               public override int Compare (string s1, int start1, int len1,
+                       string s2, int start2, int len2, CompareOptions options)
+               {
+                       return PopulateComparer (options)
+                               .Compare (s1, start1, len1, s2, start2, len2);
+               }
+
+               public override SortKey GetSortKey (
+                       string source, CompareOptions options)
+               {
+                       return PopulateComparer (options).GetSortKey (source);
+               }
+
+               public override int IndexOf (string source, char value,
+                       int startIndex, int count, CompareOptions options)
+               {
+                       return PopulateComparer (options).IndexOf (source,
+                               value, startIndex, count);
+               }
+
+               public override int IndexOf (string source, string value,
+                       int startIndex, int count, CompareOptions options)
+               {
+                       return PopulateComparer (options).IndexOf (source,
+                               value, startIndex, count);
+               }
+       }
+}
+

Added: 
branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/CompareInfoImpl.cs
===================================================================
--- 
branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/CompareInfoImpl.cs 
    2005-04-25 07:26:06 UTC (rev 43533)
+++ 
branches/atsushi/mcs/class/corlib/Mono.Globalization.Unicode/CompareInfoImpl.cs 
    2005-04-25 08:07:28 UTC (rev 43534)
@@ -0,0 +1,69 @@
+//
+// Note that this is just a conceptual source and subject to changes.
+//
+
+using System;
+using System.Text;
+
+using Mono.Globalization.Collation;
+
+namespace System.Globalization
+{
+       internal class CompareInfo
+       {
+               CultureInfo culture;
+               Collator collator;
+
+               internal CompareInfo (CultureInfo ci)
+               {
+                       culture = ci;
+                       collator = new RuleBasedCollator (ci);
+               }
+
+               public override int Compare (
+                       string string1, int offset1, int length1,
+                       string string2, int offset2, int length2,
+                       CompareOptions options)
+               {
+                       // FIXME: check allowed flags here.
+                       // FIXME: check array range
+
+                       // quick ordinal comparison
+                       if (options == CompareOptions.Ordinal) {
+                               int min = length1 < length2 ? length1 : length2;
+                               for (int i = 0; i < min; i++)
+                                       if (string1 [offset1 + i] != string2 
[offset2 + i])
+                                               return ((int) string1 [offset1 
+ i]) 
+                                                       - ((int) string2 
[offset2 + i]);
+                               return (length1 > min) ?
+                                       1 :
+                                       (length2 > min) ? -1 : 0;
+                       }
+
+                       return collator.Compare (string1, offset1, length1,
+                               string2, offset2, length2, options);
+               }
+
+               public override SortKey GetSortKey (
+                       string source, CompareOptions options)
+               {
+                       // FIXME: check allowed flags here.
+
+                       return collator.GetSortKey (source, options);
+               }
+
+               public override int IndexOf (string source, char value,
+                       int startIndex, int count, CompareOptions options)
+               {
+                       return IndexOf (source, value.ToString (this.culture),
+                               startIndex, count, options);
+               }
+
+               public override int IndexOf (string source, string value,
+                       int startIndex, int count, CompareOptions options)
+               {
+                       return collator.IndexOf (
+                               source, value, startIndex, count, options);
+               }
+       }
+}

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to