Author: atsushi
Date: 2005-07-15 01:37:18 -0400 (Fri, 15 Jul 2005)
New Revision: 47327
Modified:
trunk/mcs/class/corlib/Mono.Globalization.Unicode/ChangeLog
trunk/mcs/class/corlib/Mono.Globalization.Unicode/Collation-notes.txt
trunk/mcs/class/corlib/Mono.Globalization.Unicode/SimpleCollator.cs
trunk/mcs/class/corlib/Mono.Globalization.Unicode/TestDriver.cs
trunk/mcs/class/corlib/Test/System.Globalization/ChangeLog
trunk/mcs/class/corlib/Test/System.Globalization/CompareInfoTest.cs
Log:
2005-07-15 Atsushi Enomoto <[EMAIL PROTECTED]>
* SimpleCollator.cs : rewrote LastIndexOf() to handle source extenders.
Some refactoring on IndexOf() code. Removed unused Matches().
* Collation-notes.txt : some methods needed to be reimplemented, so
rewrote the description.
* CompareInfoTest.cs : Uncommented tests that got working. Added two
cornercase notworking LastIndexOf() tests.
Modified: trunk/mcs/class/corlib/Mono.Globalization.Unicode/ChangeLog
===================================================================
--- trunk/mcs/class/corlib/Mono.Globalization.Unicode/ChangeLog 2005-07-15
04:55:23 UTC (rev 47326)
+++ trunk/mcs/class/corlib/Mono.Globalization.Unicode/ChangeLog 2005-07-15
05:37:18 UTC (rev 47327)
@@ -1,3 +1,10 @@
+2005-07-15 Atsushi Enomoto <[EMAIL PROTECTED]>
+
+ * SimpleCollator.cs : rewrote LastIndexOf() to handle source extenders.
+ Some refactoring on IndexOf() code. Removed unused Matches().
+ * Collation-notes.txt : some methods needed to be reimplemented, so
+ rewrote the description.
+
2005-07-14 Atsushi Enomoto <[EMAIL PROTECTED]>
* SimpleCollator.cs : rewrote IsSuffix() to use CompareInternal().
Modified: trunk/mcs/class/corlib/Mono.Globalization.Unicode/Collation-notes.txt
===================================================================
--- trunk/mcs/class/corlib/Mono.Globalization.Unicode/Collation-notes.txt
2005-07-15 04:55:23 UTC (rev 47326)
+++ trunk/mcs/class/corlib/Mono.Globalization.Unicode/Collation-notes.txt
2005-07-15 05:37:18 UTC (rev 47327)
@@ -36,13 +36,13 @@
Find first difference and compare it.
"Larger/smaller" matters (beyond "different").
IsPrefix()
- For each character in the target, examine if it matches from
- the head of the searchee and immediately return false if it
- didn't match.
+ It calls CompareInternal() which also answers if the target
+ is fully consumed, so it just returns true if it says that
+ the target is fully consumed.
IsSuffix()
- For each character in the target, examine if it matches
- form the tail of the searchee and immediately return false if
- it didn't match. It uses reversal element query.
+ It tries CompareInternal() to compare source and target at
+ the end, where source varies from minimum tail to the
+ original args.
IndexOf(), LastIndexOf()
For character search, it finds the matching character element
to the end (or start) of the string to find.
Modified: trunk/mcs/class/corlib/Mono.Globalization.Unicode/SimpleCollator.cs
===================================================================
--- trunk/mcs/class/corlib/Mono.Globalization.Unicode/SimpleCollator.cs
2005-07-15 04:55:23 UTC (rev 47326)
+++ trunk/mcs/class/corlib/Mono.Globalization.Unicode/SimpleCollator.cs
2005-07-15 05:37:18 UTC (rev 47327)
@@ -1251,13 +1251,6 @@
#region IndexOf() / LastIndexOf()
- // IndexOf (string, string, CompareOptions)
- // IndexOf (string, string, int, int, CompareOptions)
- // IndexOf (string, char, int, int, CompareOptions)
- // IndexOfPrimitiveChar (string, int, int, char)
- // IndexOfSortKey (string, int, int, byte[], char, int, bool)
- // IndexOf (string, string, int, int)
-
public int IndexOf (string s, string target, CompareOptions opt)
{
return IndexOf (s, target, 0, s.Length, opt);
@@ -1287,23 +1280,20 @@
(opt &
CompareOptions.StringSort) != 0);
else
return IndexOfSortKey (s, start,
length, ct.SortKey, char.MinValue, -1, true);
+ } else {
+ int ti = FilterOptions ((int) target);
+ charSortKeyIndexTarget [0] = Category (ti);
+ charSortKeyIndexTarget [1] = Level1 (ti);
+ if (!ignoreNonSpace)
+ charSortKeyIndexTarget [2] =
+ Level2 (ti, ExtenderType.None);
+ charSortKeyIndexTarget [3] = Uni.Level3 (ti);
+ return IndexOfSortKey (s, start, length,
+ charSortKeyIndexTarget, target, ti,
+ !Uni.HasSpecialWeight ((char) ti));
}
- else
- return IndexOfPrimitiveChar (s, start, length,
target);
}
- // Searches target char w/o checking contractions
- int IndexOfPrimitiveChar (string s, int start, int length, char
target)
- {
- int ti = FilterOptions ((int) target);
- charSortKeyIndexTarget [0] = Category (ti);
- charSortKeyIndexTarget [1] = Level1 (ti);
- if (!ignoreNonSpace)
- charSortKeyIndexTarget [2] = Level2 (ti,
ExtenderType.None);
- charSortKeyIndexTarget [3] = Uni.Level3 (ti);
- return IndexOfSortKey (s, start, length,
charSortKeyIndexTarget, target, ti, !Uni.HasSpecialWeight ((char) ti));
- }
-
// Searches target byte[] keydata
int IndexOfSortKey (string s, int start, int length, byte []
sortkey, char target, int ti, bool noLv4)
{
@@ -1412,33 +1402,27 @@
if (ct.Replacement != null)
return LastIndexOf (s, ct.Replacement,
start, length, (opt & CompareOptions.StringSort) != 0);
else
- return LastIndexOfSortKey (s, start,
length, ct.SortKey, char.MinValue, -1, true);
+ return LastIndexOfSortKey (s, start,
start, length, ct.SortKey, char.MinValue, -1, true);
}
- else
- return LastIndexOfPrimitiveChar (s, start,
length, target);
+ else {
+ int ti = FilterOptions ((int) target);
+ charSortKeyIndexTarget [0] = Category (ti);
+ charSortKeyIndexTarget [1] = Level1 (ti);
+ if (!ignoreNonSpace)
+ charSortKeyIndexTarget [2] = Level2
(ti, ExtenderType.None);
+ charSortKeyIndexTarget [3] = Uni.Level3 (ti);
+ return LastIndexOfSortKey (s, start, start,
length, charSortKeyIndexTarget, target, ti, !Uni.HasSpecialWeight ((char) ti));
+ }
}
- // Searches target char w/o checking contractions
- int LastIndexOfPrimitiveChar (string s, int start, int length,
char target)
- {
- int ti = FilterOptions ((int) target);
- charSortKey [0] = Category (ti);
- charSortKey [1] = Level1 (ti);
- if (!ignoreNonSpace)
- // FIXME: pass ExtenderType
- charSortKey [2] = Level2 (ti,
ExtenderType.None);
- charSortKey [3] = Uni.Level3 (ti);
- return LastIndexOfSortKey (s, start, length,
charSortKey, target, ti, !Uni.HasSpecialWeight ((char) ti));
- }
-
// Searches target byte[] keydata
- int LastIndexOfSortKey (string s, int start, int length, byte
[] sortkey, char target, int ti, bool noLv4)
+ int LastIndexOfSortKey (string s, int start, int orgStart, int
length, byte [] sortkey, char target, int ti, bool noLv4)
{
int end = start - length;
-
- for (int idx = start; idx > end; idx--) {
+ int idx = start;
+ while (idx > end) {
int cur = idx;
- if (Matches (s, ref idx, end, ti, target,
sortkey, noLv4, true))
+ if (MatchesBackward (s, ref idx, end, orgStart,
ti, sortkey, noLv4))
return cur;
}
return -1;
@@ -1456,20 +1440,47 @@
if (tidx == target.Length)
return start;
Contraction ct = GetContraction (target, tidx,
target.Length - tidx);
- byte [] sortkey = ct != null ? ct.SortKey : null;
string replace = ct != null ? ct.Replacement : null;
+ byte [] sk = replace == null ? charSortKeyIndexTarget :
null;
+ bool noLv4 = true;
+ char tc = char.MinValue;
+ int ti = -1;
+ if (ct != null && sk != null) {
+ for (int i = 0; i < ct.SortKey.Length; i++)
+ sk [i] = ct.SortKey [i];
+ } else if (sk != null) {
+ tc = target [tidx];
+ ti = FilterOptions (target [tidx]);
+ sk [0] = Category (ti);
+ sk [1] = Level1 (ti);
+ if (!ignoreNonSpace)
+ sk [2] = Level2 (ti, ExtenderType.None);
+ sk [3] = Uni.Level3 (ti);
+ noLv4 = !Uni.HasSpecialWeight ((char) ti);
+ }
+ if (sk != null) {
+ for (tidx++; tidx < target.Length; tidx++) {
+ if (Category (target [tidx]) != 1)
+ break;
+ if (sk [2] == 0)
+ sk [2] = 2;
+ sk [2] = (byte) (sk [2] + Level2
(target [tidx], ExtenderType.None));
+ }
+ }
+
do {
int idx = 0;
- if (sortkey != null)
- idx = LastIndexOfSortKey (s, start,
length, ct.SortKey, char.MinValue, -1, true);
- else if (replace != null)
+
+ if (replace != null)
idx = LastIndexOf (s, replace, start,
length, stringSort);
else
- idx = LastIndexOfPrimitiveChar (s,
start, length, target [tidx]);
-
+ idx = LastIndexOfSortKey (s, start,
orgStart, length, sk, tc, ti, noLv4);
if (idx < 0)
return -1;
+ length -= start - idx;
+ start = idx;
+
if (IsPrefix (s, target, idx, orgStart - idx +
1, stringSort, false)) {
for (;idx < orgStart; idx++)
if (!IsIgnorable (s [idx]))
@@ -1488,62 +1499,6 @@
return -1;
}
- private bool Matches (string s, ref int idx, int end, int ti,
char target, byte [] sortkey, bool noLv4, bool lastIndexOf)
- {
- switch (char.GetUnicodeCategory (s [idx])) {
- case UnicodeCategory.PrivateUse:
- case UnicodeCategory.Surrogate:
- if (s [idx] != target)
- return false;
- return true;
- }
-
- char sc = char.MinValue;
- Contraction ct = GetContraction (s, idx, end);
- // if lv4 exists, it never matches contraction
- if (ct != null && noLv4) {
- if (lastIndexOf)
- idx -= ct.Source.Length - 1;
- else
- idx += ct.Source.Length - 1;
- if (ct.SortKey != null) {
- for (int i = 0; i < sortkey.Length; i++)
- if (ct.SortKey [i] != sortkey
[i])
- return false;
- return true;
- }
- // Here is the core of LAMESPEC
- // described at the top of the source.
- sc = ct.Replacement [0];
- }
- else
- sc = s [idx];
-
- if (sc == target)
- return true;
- int si = FilterOptions ((int) sc);
- if (Category (si) != sortkey [0] ||
- Level1 (si) != sortkey [1] ||
- // FIXME: pass ExtenderType
- !ignoreNonSpace && Level2 (si,
ExtenderType.None) != sortkey [2] ||
- Uni.Level3 (si) != sortkey [3])
- return false;
- if (noLv4 && !Uni.HasSpecialWeight ((char) si))
- return true;
- else if (noLv4)
- return false;
- if (Uni.IsJapaneseSmallLetter ((char) si) !=
- Uni.IsJapaneseSmallLetter ((char) ti) ||
- Uni.GetJapaneseDashType ((char) si) !=
- Uni.GetJapaneseDashType ((char) ti) ||
- !Uni.IsHiragana ((char) si) !=
- !Uni.IsHiragana ((char) ti) ||
- IsHalfKana ((char) si) !=
- IsHalfKana ((char) ti))
- return false;
- return true;
- }
-
private bool MatchesForward (string s, ref int idx, int end,
int ti, byte [] sortkey, bool noLv4)
{
int si = -1;
@@ -1551,8 +1506,13 @@
Contraction ct = null;
if (ext == ExtenderType.None)
ct = GetContraction (s, idx, end);
- else if (previousChar < 0)
+ else if (previousChar < 0) {
+ if (previousSortKey == null) {
+ idx++;
+ return false;
+ }
charSortKey = previousSortKey;
+ }
else
si = FilterExtender (previousChar, ext);
// if lv4 exists, it never matches contraction
@@ -1595,6 +1555,11 @@
+ Level2 (s [idx],
ExtenderType.None));
}
+ return MatchesPrimitive (charSortKey, si, ext, sortkey,
ti, noLv4);
+ }
+
+ private bool MatchesPrimitive (byte [] charSortKey, int si,
ExtenderType ext, byte [] sortkey, int ti, bool noLv4)
+ {
if (charSortKey [0] != sortkey [0] ||
charSortKey [1] != sortkey [1] ||
(!ignoreNonSpace && charSortKey [2] != sortkey
[2]) ||
@@ -1610,8 +1575,9 @@
return false;
if (Uni.IsJapaneseSmallLetter ((char) si) !=
Uni.IsJapaneseSmallLetter ((char) ti) ||
- Uni.GetJapaneseDashType ((char) si) !=
- Uni.GetJapaneseDashType ((char) ti) ||
+ ToDashTypeValue (ext) !=
+ // FIXME: we will have to specify correct value
for target
+ ToDashTypeValue (ExtenderType.None) ||
!Uni.IsHiragana ((char) si) !=
!Uni.IsHiragana ((char) ti) ||
IsHalfKana ((char) si) !=
@@ -1619,6 +1585,89 @@
return false;
return true;
}
+
+ private bool MatchesBackward (string s, ref int idx, int end,
int orgStart, int ti, byte [] sortkey, bool noLv4)
+ {
+ int cur = idx;
+ int si = -1;
+ ExtenderType ext = GetExtenderType (s [idx]);
+ // To handle extenders in source, we need to
+ // check next _primary_ character.
+ if (ext != ExtenderType.None) {
+ byte diacritical = 0;
+ for (int tmp = 0; ; tmp--) {
+ if (tmp < 0) // heading extender
+ return false;
+ if (IsIgnorable (s [tmp]))
+ continue;
+ int tmpi = FilterOptions (s [tmp]);
+ byte category = Category (tmpi);
+ if (category == 1) {
+ diacritical = Level2 (tmpi,
ExtenderType.None);
+ continue;
+ }
+ si = FilterExtender (tmpi, ext);
+ charSortKey [0] = category;
+ charSortKey [1] = Level1 (si);
+ if (!ignoreNonSpace)
+ charSortKey [2] = Level2 (si,
ext);
+ charSortKey [3] = Uni.Level3 (si);
+ if (ext != ExtenderType.Conditional &&
+ diacritical != 0)
+ charSortKey [2] =
+ (charSortKey [2] == 0) ?
+ (byte) (diacritical +
2) :
+ diacritical;
+ break;
+ }
+ idx--;
+ }
+ Contraction ct = null;
+ if (ext == ExtenderType.None)
+ ct = GetContraction (s, idx, end);
+ // if lv4 exists, it never matches contraction
+ if (ct != null) {
+ idx -= ct.Source.Length;
+ if (!noLv4)
+ return false;
+ if (ct.SortKey != null) {
+ for (int i = 0; i < sortkey.Length; i++)
+ charSortKey [i] = sortkey [i];
+ previousChar = -1;
+ previousSortKey = charSortKey;
+ } else {
+ // Here is the core of LAMESPEC
+ // described at the top of the source.
+ int dummy = ct.Replacement.Length - 1;
+ return MatchesBackward (ct.Replacement,
+ ref dummy, dummy, -1, ti,
sortkey, noLv4);
+ }
+ } else if (ext == ExtenderType.None) {
+ if (si < 0)
+ si = FilterOptions (s [idx]);
+ charSortKey [0] = Category (si);
+ charSortKey [1] = Level1 (si);
+ if (!ignoreNonSpace)
+ charSortKey [2] = Level2 (si, ext);
+ charSortKey [3] = Uni.Level3 (si);
+ if (charSortKey [0] != 1)
+ previousChar = si;
+ idx--;
+ }
+ if (ext == ExtenderType.None) {
+ for (int tmp = cur + 1; tmp < orgStart; tmp++) {
+ if (Category (s [tmp]) != 1)
+ break;
+ if (ignoreNonSpace)
+ continue;
+ if (charSortKey [2] == 0)
+ charSortKey [2] = 2;
+ charSortKey [2] = (byte) (charSortKey
[2]
+ + Level2 (s [tmp],
ExtenderType.None));
+ }
+ }
+ return MatchesPrimitive (charSortKey, si, ext, sortkey,
ti, noLv4);
+ }
#endregion
}
}
Modified: trunk/mcs/class/corlib/Mono.Globalization.Unicode/TestDriver.cs
===================================================================
--- trunk/mcs/class/corlib/Mono.Globalization.Unicode/TestDriver.cs
2005-07-15 04:55:23 UTC (rev 47326)
+++ trunk/mcs/class/corlib/Mono.Globalization.Unicode/TestDriver.cs
2005-07-15 05:37:18 UTC (rev 47327)
@@ -30,10 +30,7 @@
void Run ()
{
-//IsSuffix ("\u00E6", "ae", CompareOptions.None);
-IsSuffix ("ae", "\u00E6", CompareOptions.None);
-//LastIndexOf ("AE", "A", 1, 2, CompareOptions.None);
-//LastIndexOf ("\u00C6", "AE", CompareOptions.None);
+LastIndexOf ("\u30D1\u30FC", "\u30A2", CompareOptions.IgnoreNonSpace);
return;
/*
DumpSortKey ("AE");
Modified: trunk/mcs/class/corlib/Test/System.Globalization/ChangeLog
===================================================================
--- trunk/mcs/class/corlib/Test/System.Globalization/ChangeLog 2005-07-15
04:55:23 UTC (rev 47326)
+++ trunk/mcs/class/corlib/Test/System.Globalization/ChangeLog 2005-07-15
05:37:18 UTC (rev 47327)
@@ -1,3 +1,8 @@
+2005-07-15 Atsushi Enomoto <[EMAIL PROTECTED]>
+
+ * CompareInfoTest.cs : Uncommented tests that got working. Added two
+ cornercase notworking LastIndexOf() tests.
+
2005-07-14 Atsushi Enomoto <[EMAIL PROTECTED]>
* CompareInfoTest.cs : IsSuffix() extender tests got working.
Modified: trunk/mcs/class/corlib/Test/System.Globalization/CompareInfoTest.cs
===================================================================
--- trunk/mcs/class/corlib/Test/System.Globalization/CompareInfoTest.cs
2005-07-15 04:55:23 UTC (rev 47326)
+++ trunk/mcs/class/corlib/Test/System.Globalization/CompareInfoTest.cs
2005-07-15 05:37:18 UTC (rev 47327)
@@ -868,7 +868,6 @@
AssertIsSuffix ("#10", true, "\uff21\uff21", "\u3007\uff21",
CompareOptions.None);
AssertIsSuffix ("#11", true, "\uff21\uff21", "\uff21\u3007",
CompareOptions.None);
// extender in target
- // FIXME: not working
AssertIsSuffix ("#12", false, "\u30D1\u30A2", "\u30D1\u30FC");
AssertIsSuffix ("#13", true, "\u30D1\u30A2", "\u30D1\u30FC",
CompareOptions.IgnoreNonSpace);
// extender in source
@@ -981,17 +980,20 @@
AssertLastIndexOf ("#1-3", 0, "\u30D1\u30A2", "\u30D1\u30FC",
CompareOptions.IgnoreNonSpace);
// extender in source
AssertLastIndexOf ("#1-4", 0, "\u30D1\u30FC", "\u30D1\u30A2",
CompareOptions.IgnoreNonSpace);
- // FIXME: not working (extender support required)
-// AssertLastIndexOf ("#2", 0, "\u30D1\u30FC\u30B9",
"\uFF8A\uFF9F\uFF70\uFF7D", CompareOptions.IgnoreWidth);
- // FIXME: not working (extender support required)
-// AssertLastIndexOf ("#3", 0, "\uFF80\uFF9E\uFF72\uFF8C\uFF9E",
-// "\u30C0\u30A4\u30D6", CompareOptions.IgnoreWidth);
+ // FIXME: not working (extender support is not complete.
+ // Currently private IsPrefix() cannot handle heading
+ // extenders to consume previous primary char.)
+// AssertLastIndexOf ("#1-5", 1, "\u30D1\u30FC", "\u30A2",
CompareOptions.IgnoreNonSpace);
+ // this shows that Windows accesses beyond the length and
+ // acquires the corresponding character to expand.
+// AssertLastIndexOf ("#1-6", 1, "\u30D1\u30FC", "\u30A2", 1, 1,
CompareOptions.IgnoreNonSpace, invariant);
+ AssertLastIndexOf ("#2", 0, "\u30D1\u30FC\u30B9",
"\uFF8A\uFF9F\uFF70\uFF7D", CompareOptions.IgnoreWidth);
+ AssertLastIndexOf ("#3", 0, "\uFF80\uFF9E\uFF72\uFF8C\uFF9E",
+ "\u30C0\u30A4\u30D6", CompareOptions.IgnoreWidth);
AssertLastIndexOf ("#4", -1, "\u3042\u309D", "\u3042\u3042");
AssertLastIndexOf ("#5", 0, "\u3042\u309D", "\u3042\u3042",
CompareOptions.IgnoreNonSpace);
- // FIXME: not working (extender support required)
-// AssertLastIndexOf ("#6", 0, "\uFF8A\uFF9E\uFF70\uFF99",
-// "\u30D0\u30FC\u30EB", CompareOptions.IgnoreWidth);
-
+ AssertLastIndexOf ("#6", 0, "\uFF8A\uFF9E\uFF70\uFF99",
+ "\u30D0\u30FC\u30EB", CompareOptions.IgnoreWidth);
}
}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches