2005-11-14 Atsushi Enomoto <atsushi@ximian.com>
authorAtsushi Eno <atsushieno@gmail.com>
Mon, 14 Nov 2005 19:39:57 +0000 (19:39 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Mon, 14 Nov 2005 19:39:57 +0000 (19:39 -0000)
        * SimpleCollator.cs :
          Created another struct to reduce method arguments. Created
another
          flags that keeps "once-matched" state (counterpart of
          checkedFlags, now neverMatchFlags).

svn path=/trunk/mcs/; revision=53029

mcs/class/corlib/Mono.Globalization.Unicode/ChangeLog
mcs/class/corlib/Mono.Globalization.Unicode/SimpleCollator.cs

index be1f7345f5b1244ef138ebee350a3633e4f4a6c0..ea3468d7f4e74e37d1264a590f1ffe371c684bd2 100644 (file)
@@ -1,3 +1,10 @@
+2005-11-14  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * SimpleCollator.cs :
+         Created another struct to reduce method arguments. Created another
+         flags that keeps "once-matched" state (counterpart of
+         checkedFlags, now neverMatchFlags).
+
 2005-11-14  Atsushi Enomoto  <atsushi@ximian.com>
 
        * SimpleCollator.cs :
 2005-11-14  Atsushi Enomoto  <atsushi@ximian.com>
 
        * SimpleCollator.cs :
index 51317aefca1990d3fd1319306e032b6c1ffddbb4..a68476e2099c2b618cc77d6e5d6c1250e58d29d0 100644 (file)
@@ -77,6 +77,34 @@ namespace Mono.Globalization.Unicode
 {
        internal class SimpleCollator
        {
 {
        internal class SimpleCollator
        {
+               unsafe internal struct Context
+               {
+                       public Context (CompareOptions opt, byte* alwaysMatchFlags, byte* neverMatchFlags, byte* buffer1, byte* buffer2, byte* prev1)
+                       {
+                               Option = opt;
+                               AlwaysMatchFlags = alwaysMatchFlags;
+                               NeverMatchFlags = neverMatchFlags;
+                               Buffer1 = buffer1;
+                               Buffer2 = buffer2;
+                               PrevSortKey = prev1;
+                               PrevCode = -1;
+                       }
+
+                       public readonly CompareOptions Option;
+                       public readonly byte* NeverMatchFlags;
+                       public readonly byte* AlwaysMatchFlags;
+                       public byte* Buffer1;
+                       public byte* Buffer2;
+                       public int PrevCode;
+                       public byte* PrevSortKey;
+
+                       public void ClearPrevInfo ()
+                       {
+                               PrevCode = -1;
+                               PrevSortKey = null;
+                       }
+               }
+
                unsafe struct PreviousInfo
                {
                        public int Code;
                unsafe struct PreviousInfo
                {
                        public int Code;
@@ -125,7 +153,7 @@ namespace Mono.Globalization.Unicode
                //
                // Now that it should be thread safe, this array is allocated
                // at every time.
                //
                // Now that it should be thread safe, this array is allocated
                // at every time.
-//             byte [] checkedFlags = new byte [128 / 8];
+//             byte [] neverMatchFlags = new byte [128 / 8];
 
                #region .ctor() and split functions
 
 
                #region .ctor() and split functions
 
@@ -500,21 +528,20 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                unsafe void GetSortKey (string s, int start, int end,
                        SortKeyBuffer buf, CompareOptions opt)
                {
                unsafe void GetSortKey (string s, int start, int end,
                        SortKeyBuffer buf, CompareOptions opt)
                {
-                       PreviousInfo prev = new PreviousInfo (false);
                        byte* prevbuf = stackalloc byte [4];
                        ClearBuffer (prevbuf, 4);
                        byte* prevbuf = stackalloc byte [4];
                        ClearBuffer (prevbuf, 4);
-                       prev.SortKey = prevbuf;
+                       Context ctx = new Context (opt, null, null, null, null, prevbuf);
 
                        for (int n = start; n < end; n++) {
                                int i = s [n];
 
                                ExtenderType ext = GetExtenderType (i);
                                if (ext != ExtenderType.None) {
 
                        for (int n = start; n < end; n++) {
                                int i = s [n];
 
                                ExtenderType ext = GetExtenderType (i);
                                if (ext != ExtenderType.None) {
-                                       i = FilterExtender (prev.Code, ext, opt);
+                                       i = FilterExtender (ctx.PrevCode, ext, opt);
                                        if (i >= 0)
                                                FillSortKeyRaw (i, ext, buf, opt);
                                        if (i >= 0)
                                                FillSortKeyRaw (i, ext, buf, opt);
-                                       else if (prev.SortKey != null) {
-                                               byte* b = prev.SortKey;
+                                       else if (ctx.PrevSortKey != null) {
+                                               byte* b = ctx.PrevSortKey;
                                                buf.AppendNormal (
                                                        b [0],
                                                        b [1],
                                                buf.AppendNormal (
                                                        b [0],
                                                        b [1],
@@ -536,7 +563,7 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                        if (ct.Replacement != null) {
                                                GetSortKey (ct.Replacement, 0, ct.Replacement.Length, buf, opt);
                                        } else {
                                        if (ct.Replacement != null) {
                                                GetSortKey (ct.Replacement, 0, ct.Replacement.Length, buf, opt);
                                        } else {
-                                               byte* b = prev.SortKey;
+                                               byte* b = ctx.PrevSortKey;
                                                for (int bi = 0; bi < ct.SortKey.Length; bi++)
                                                        b [bi] = ct.SortKey [bi];
                                                buf.AppendNormal (
                                                for (int bi = 0; bi < ct.SortKey.Length; bi++)
                                                        b [bi] = ct.SortKey [bi];
                                                buf.AppendNormal (
@@ -544,13 +571,13 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                                        b [1],
                                                        b [2] != 1 ? b [2] : Level2 (i, ext),
                                                        b [3] != 1 ? b [3] : Uni.Level3 (i));
                                                        b [1],
                                                        b [2] != 1 ? b [2] : Level2 (i, ext),
                                                        b [3] != 1 ? b [3] : Uni.Level3 (i));
-                                               prev.Code = -1;
+                                               ctx.PrevCode = -1;
                                        }
                                        n += ct.Source.Length - 1;
                                }
                                else {
                                        if (!Uni.IsIgnorableNonSpacing (i))
                                        }
                                        n += ct.Source.Length - 1;
                                }
                                else {
                                        if (!Uni.IsIgnorableNonSpacing (i))
-                                               prev.Code = i;
+                                               ctx.PrevCode = i;
                                        FillSortKeyRaw (i, ExtenderType.None, buf, opt);
                                }
                        }
                                        FillSortKeyRaw (i, ExtenderType.None, buf, opt);
                                }
                        }
@@ -716,13 +743,14 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                        return d1 [i] < d2 [i] ? -1 : 1;
                        return d1.Length == d2.Length ? 0 : d1.Length < d2.Length ? -1 : 1;
 #else
                                        return d1 [i] < d2 [i] ? -1 : 1;
                        return d1.Length == d2.Length ? 0 : d1.Length < d2.Length ? -1 : 1;
 #else
-                       PreviousInfo prev1 = new PreviousInfo (false);
                        byte* sk1 = stackalloc byte [4];
                        byte* sk1 = stackalloc byte [4];
-                       ClearBuffer (sk1, 4);
                        byte* sk2 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
+                       ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
                        ClearBuffer (sk2, 4);
+                       Context ctx = new Context (options, null, null, sk1, sk2, null);
+
                        bool dummy, dummy2;
                        bool dummy, dummy2;
-                       int ret = CompareInternal (options, s1, idx1, len1, s2, idx2, len2, out dummy, out dummy2, true, ref prev1, sk1, sk2);
+                       int ret = CompareInternal (s1, idx1, len1, s2, idx2, len2, out dummy, out dummy2, true, false, ref ctx);
                        return ret == 0 ? 0 : ret < 0 ? -1 : 1;
 #endif
                }
                        return ret == 0 ? 0 : ret < 0 ? -1 : 1;
 #endif
                }
@@ -733,12 +761,13 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                buffer [i] = 0;
                }
 
                                buffer [i] = 0;
                }
 
-               unsafe int CompareInternal (COpt opt, string s1, int idx1, int len1, string s2,
+               unsafe int CompareInternal (string s1, int idx1, int len1, string s2,
                        int idx2, int len2,
                        out bool targetConsumed, out bool sourceConsumed,
                        int idx2, int len2,
                        out bool targetConsumed, out bool sourceConsumed,
-                       bool skipHeadingExtenders, ref PreviousInfo prev1,
-                       byte* charSortKey, byte* charSortKey2)
+                       bool skipHeadingExtenders, bool immediatelyBreakup,
+                       ref Context ctx)
                {
                {
+                       COpt opt = ctx.Option;
                        int start1 = idx1;
                        int start2 = idx2;
                        int end1 = idx1 + len1;
                        int start1 = idx1;
                        int start2 = idx2;
                        int end1 = idx1 + len1;
@@ -865,16 +894,16 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                // repeat the previous character.
                                ext1 = GetExtenderType (i1);
                                if (ext1 != ExtenderType.None) {
                                // repeat the previous character.
                                ext1 = GetExtenderType (i1);
                                if (ext1 != ExtenderType.None) {
-                                       if (prev1.Code < 0) {
-                                               if (prev1.SortKey == null) {
+                                       if (ctx.PrevCode < 0) {
+                                               if (ctx.PrevSortKey == null) {
                                                        // nothing to extend
                                                        idx1++;
                                                        continue;
                                                }
                                                        // nothing to extend
                                                        idx1++;
                                                        continue;
                                                }
-                                               sk1 = prev1.SortKey;
+                                               sk1 = ctx.PrevSortKey;
                                        }
                                        else
                                        }
                                        else
-                                               i1 = FilterExtender (prev1.Code, ext1, opt);
+                                               i1 = FilterExtender (ctx.PrevCode, ext1, opt);
                                }
                                ext2 = GetExtenderType (i2);
                                if (ext2 != ExtenderType.None) {
                                }
                                ext2 = GetExtenderType (i2);
                                if (ext2 != ExtenderType.None) {
@@ -902,7 +931,7 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                                // here Windows has a bug that it does
                                                // not consider thirtiary weight.
                                                lv5Value1 = Level1 (i1) << 8 + Uni.Level3 (i1);
                                                // here Windows has a bug that it does
                                                // not consider thirtiary weight.
                                                lv5Value1 = Level1 (i1) << 8 + Uni.Level3 (i1);
-                                               prev1.Code = i1;
+                                               ctx.PrevCode = i1;
                                                idx1++;
                                        }
                                        if (cat2 == 6) {
                                                idx1++;
                                        }
                                        if (cat2 == 6) {
@@ -931,11 +960,11 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                else if (ct1 != null) {
                                        offset1 = ct1.Source.Length;
                                        if (ct1.SortKey != null) {
                                else if (ct1 != null) {
                                        offset1 = ct1.Source.Length;
                                        if (ct1.SortKey != null) {
-                                               sk1 = charSortKey;
+                                               sk1 = ctx.Buffer1;
                                                for (int i = 0; i < ct1.SortKey.Length; i++)
                                                        sk1 [i] = ct1.SortKey [i];
                                                for (int i = 0; i < ct1.SortKey.Length; i++)
                                                        sk1 [i] = ct1.SortKey [i];
-                                               prev1.Code = -1;
-                                               prev1.SortKey = sk1;
+                                               ctx.PrevCode = -1;
+                                               ctx.PrevSortKey = sk1;
                                        }
                                        else if (escape1.Source == null) {
                                                escape1.Source = s1;
                                        }
                                        else if (escape1.Source == null) {
                                                escape1.Source = s1;
@@ -952,7 +981,7 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                        }
                                }
                                else {
                                        }
                                }
                                else {
-                                       sk1 = charSortKey;
+                                       sk1 = ctx.Buffer1;
                                        sk1 [0] = cat1;
                                        sk1 [1] = Level1 (i1);
                                        if (!ignoreNonSpace && currentLevel > 1)
                                        sk1 [0] = cat1;
                                        sk1 [1] = Level1 (i1);
                                        if (!ignoreNonSpace && currentLevel > 1)
@@ -962,7 +991,7 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                        if (currentLevel > 3)
                                                special1 = Uni.HasSpecialWeight ((char) i1);
                                        if (cat1 > 1)
                                        if (currentLevel > 3)
                                                special1 = Uni.HasSpecialWeight ((char) i1);
                                        if (cat1 > 1)
-                                               prev1.Code = i1;
+                                               ctx.PrevCode = i1;
                                }
 
                                Contraction ct2 = null;
                                }
 
                                Contraction ct2 = null;
@@ -974,7 +1003,7 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                else if (ct2 != null) {
                                        idx2 += ct2.Source.Length;
                                        if (ct2.SortKey != null) {
                                else if (ct2 != null) {
                                        idx2 += ct2.Source.Length;
                                        if (ct2.SortKey != null) {
-                                               sk2 = charSortKey2;
+                                               sk2 = ctx.Buffer2;
                                                for (int i = 0; i < ct2.SortKey.Length; i++)
                                                        sk2 [i] = ct2.SortKey [i];
                                                prev2.Code = -1;
                                                for (int i = 0; i < ct2.SortKey.Length; i++)
                                                        sk2 [i] = ct2.SortKey [i];
                                                prev2.Code = -1;
@@ -995,7 +1024,7 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                        }
                                }
                                else {
                                        }
                                }
                                else {
-                                       sk2 = charSortKey2;
+                                       sk2 = ctx.Buffer2;
                                        sk2 [0] = cat2;
                                        sk2 [1] = Level1 (i2);
                                        if (!ignoreNonSpace && currentLevel > 1)
                                        sk2 [0] = cat2;
                                        sk2 [1] = Level1 (i2);
                                        if (!ignoreNonSpace && currentLevel > 1)
@@ -1047,6 +1076,8 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                        ret = sk1 [2] - sk2 [2];
                                        if (ret != 0) {
                                                finalResult = ret;
                                        ret = sk1 [2] - sk2 [2];
                                        if (ret != 0) {
                                                finalResult = ret;
+                                               if (immediatelyBreakup)
+                                                       return -1; // different
                                                currentLevel = frenchSort ? 2 : 1;
                                                continue;
                                        }
                                                currentLevel = frenchSort ? 2 : 1;
                                                continue;
                                        }
@@ -1056,12 +1087,16 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                ret = sk1 [3] - sk2 [3];
                                if (ret != 0) {
                                        finalResult = ret;
                                ret = sk1 [3] - sk2 [3];
                                if (ret != 0) {
                                        finalResult = ret;
+                                       if (immediatelyBreakup)
+                                               return -1; // different
                                        currentLevel = 2;
                                        continue;
                                }
                                if (currentLevel == 3)
                                        continue;
                                if (special1 != special2) {
                                        currentLevel = 2;
                                        continue;
                                }
                                if (currentLevel == 3)
                                        continue;
                                if (special1 != special2) {
+                                       if (immediatelyBreakup)
+                                               return -1; // different
                                        finalResult = special1 ? 1 : -1;
                                        currentLevel = 3;
                                        continue;
                                        finalResult = special1 ? 1 : -1;
                                        currentLevel = 3;
                                        continue;
@@ -1080,6 +1115,8 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                                                !IsHalfKana ((char) i1, opt),
                                                !IsHalfKana ((char) i2, opt));
                                        if (ret != 0) {
                                                !IsHalfKana ((char) i1, opt),
                                                !IsHalfKana ((char) i2, opt));
                                        if (ret != 0) {
+                                               if (immediatelyBreakup)
+                                                       return -1; // different
                                                finalResult = ret;
                                                currentLevel = 3;
                                                continue;
                                                finalResult = ret;
                                                currentLevel = 3;
                                                continue;
@@ -1154,21 +1191,21 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
                {
                        if (target.Length == 0)
                                return true;
                {
                        if (target.Length == 0)
                                return true;
-                       PreviousInfo prev = new PreviousInfo (false);
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
-                       return IsPrefix (opt, s, target, start, length, true, ref prev, sk1, sk2);
+                       Context ctx = new Context (opt, null, null, sk1, sk2, null);
+                       return IsPrefix (s, target, start, length, true, ref ctx);
                }
 
                }
 
-               unsafe bool IsPrefix (COpt opt, string s, string target, int start, int length, bool skipHeadingExtenders, ref PreviousInfo prev, byte* sk1, byte* sk2)
+               unsafe bool IsPrefix (string s, string target, int start, int length, bool skipHeadingExtenders, ref Context ctx)
                {
                        bool consumed, dummy;
                {
                        bool consumed, dummy;
-                       CompareInternal (opt, s, start, length,
+                       CompareInternal (s, start, length,
                                target, 0, target.Length,
                                out consumed, out dummy, skipHeadingExtenders,
                                target, 0, target.Length,
                                out consumed, out dummy, skipHeadingExtenders,
-                               ref prev, sk1, sk2);
+                               true, ref ctx);
                        return consumed;
                }
 
                        return consumed;
                }
 
@@ -1206,9 +1243,11 @@ Console.WriteLine (" -> '{0}'", c.Replacement);
 */
                }
 
 */
                }
 
-               unsafe bool IsSuffix (COpt opt, string s, string t, int start, int length, ref PreviousInfo prev, byte* sk1, byte* sk2)
+               unsafe bool IsSuffix (string s, string t, int start, int length, ref Context ctx)
                {
                        int tstart = 0;
                {
                        int tstart = 0;
+                       COpt opt = ctx.Option;
+
                        for (;tstart < t.Length; tstart++)
                                if (!IsIgnorable (t [tstart], opt))
                                        break;
                        for (;tstart < t.Length; tstart++)
                                if (!IsIgnorable (t [tstart], opt))
                                        break;
@@ -1259,13 +1298,13 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                        bool sourceConsumed, targetConsumed;
                        int mismatchCount = 0;
                        for (int i = 0; i < length; i++) {
                        bool sourceConsumed, targetConsumed;
                        int mismatchCount = 0;
                        for (int i = 0; i < length; i++) {
-                               prev = new PreviousInfo (false); // prev.Reset();
+                               ctx.ClearPrevInfo ();
 
 
-                               int ret = CompareInternal (opt, s, start - i, i + 1,
+                               int ret = CompareInternal (s, start - i, i + 1,
                                        t, tstart, t.Length - tstart,
                                        out targetConsumed,
                                        t, tstart, t.Length - tstart,
                                        out targetConsumed,
-                                       out sourceConsumed, true, ref prev,
-                                       sk1, sk2);
+                                       // FIXME: could immediately breakup
+                                       out sourceConsumed, true, true, ref ctx);
                                if (ret == 0)
                                        return true;
                                if (!sourceConsumed && targetConsumed)
                                if (ret == 0)
                                        return true;
                                if (!sourceConsumed && targetConsumed)
@@ -1296,18 +1335,20 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
 
                public unsafe int IndexOf (string s, string target, int start, int length, CompareOptions opt)
                {
 
                public unsafe int IndexOf (string s, string target, int start, int length, CompareOptions opt)
                {
-                       PreviousInfo prev = new PreviousInfo (false);
-                       byte* checkedFlags = stackalloc byte [16];
+                       byte* alwaysMatchFlags = stackalloc byte [16];
+                       byte* neverMatchFlags = stackalloc byte [16];
                        byte* targetSortKey = stackalloc byte [4];
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
                        byte* targetSortKey = stackalloc byte [4];
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
-                       ClearBuffer (checkedFlags, 16);
+                       ClearBuffer (alwaysMatchFlags, 16);
+                       ClearBuffer (neverMatchFlags, 16);
                        ClearBuffer (targetSortKey, 4);
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
                        ClearBuffer (targetSortKey, 4);
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
+                       Context ctx = new Context (opt, alwaysMatchFlags, neverMatchFlags, sk1, sk2, null);
 
 
-                       return IndexOf (opt, s, target, start, length,
-                               checkedFlags, targetSortKey, ref prev, sk1, sk2);
+                       return IndexOf (s, target, start, length,
+                               targetSortKey, ref ctx);
                }
 
                public int IndexOf (string s, char target, CompareOptions opt)
                }
 
                public int IndexOf (string s, char target, CompareOptions opt)
@@ -1317,26 +1358,28 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
 
                public unsafe int IndexOf (string s, char target, int start, int length, CompareOptions opt)
                {
 
                public unsafe int IndexOf (string s, char target, int start, int length, CompareOptions opt)
                {
-                       PreviousInfo prev = new PreviousInfo (false);
-                       byte* checkedFlags = stackalloc byte [16];
+                       byte* alwaysMatchFlags = stackalloc byte [16];
+                       byte* neverMatchFlags = stackalloc byte [16];
                        byte* targetSortKey = stackalloc byte [4];
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
                        byte* targetSortKey = stackalloc byte [4];
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
-                       ClearBuffer (checkedFlags, 16);
+                       ClearBuffer (alwaysMatchFlags, 16);
+                       ClearBuffer (neverMatchFlags, 16);
                        ClearBuffer (targetSortKey, 4);
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
                        ClearBuffer (targetSortKey, 4);
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
+                       Context ctx = new Context (opt, alwaysMatchFlags, neverMatchFlags, sk1, sk2, null);
 
                        // If target is contraction, then use string search.
                        Contraction ct = GetContraction (target);
                        if (ct != null) {
                                if (ct.Replacement != null)
 
                        // If target is contraction, then use string search.
                        Contraction ct = GetContraction (target);
                        if (ct != null) {
                                if (ct.Replacement != null)
-                                       return IndexOf (opt, s, ct.Replacement,
-                                               start, length, checkedFlags, targetSortKey, ref prev, sk1, sk2);
+                                       return IndexOf (s, ct.Replacement,
+                                               start, length, targetSortKey, ref ctx);
                                else {
                                        for (int i = 0; i < ct.SortKey.Length; i++)
                                                sk2 [i] = ct.SortKey [i];
                                else {
                                        for (int i = 0; i < ct.SortKey.Length; i++)
                                                sk2 [i] = ct.SortKey [i];
-                                       return IndexOfSortKey (opt, s, start, length, sk2, char.MinValue, -1, true, checkedFlags, ref prev, sk1);
+                                       return IndexOfSortKey (s, start, length, sk2, char.MinValue, -1, true, ref ctx);
                                }
                        } else {
                                int ti = FilterOptions ((int) target, opt);
                                }
                        } else {
                                int ti = FilterOptions ((int) target, opt);
@@ -1346,21 +1389,21 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                                        targetSortKey [2] =
                                                Level2 (ti, ExtenderType.None);
                                targetSortKey [3] = Uni.Level3 (ti);
                                        targetSortKey [2] =
                                                Level2 (ti, ExtenderType.None);
                                targetSortKey [3] = Uni.Level3 (ti);
-                               return IndexOfSortKey (opt, s, start, length,
+                               return IndexOfSortKey (s, start, length,
                                        targetSortKey, target, ti,
                                        targetSortKey, target, ti,
-                                       !Uni.HasSpecialWeight ((char) ti), checkedFlags, ref prev, sk1);
+                                       !Uni.HasSpecialWeight ((char) ti), ref ctx);
                        }
                }
 
                // Searches target byte[] keydata
                        }
                }
 
                // Searches target byte[] keydata
-               unsafe int IndexOfSortKey (COpt opt, string s, int start, int length, byte* sortkey, char target, int ti, bool noLv4, byte* checkedFlags, ref PreviousInfo prev, byte* sk)
+               unsafe int IndexOfSortKey (string s, int start, int length, byte* sortkey, char target, int ti, bool noLv4, ref Context ctx)
                {
                        int end = start + length;
                        int idx = start;
 
                        while (idx < end) {
                                int cur = idx;
                {
                        int end = start + length;
                        int idx = start;
 
                        while (idx < end) {
                                int cur = idx;
-                               if (MatchesForward (opt, s, ref idx, end, ti, sortkey, noLv4, checkedFlags, ref prev, sk))
+                               if (MatchesForward (s, ref idx, end, ti, sortkey, noLv4, ref ctx))
                                        return cur;
                        }
                        return -1;
                                        return cur;
                        }
                        return -1;
@@ -1368,8 +1411,9 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
 
                // Searches string. Search head character (or keydata when
                // the head is contraction sortkey) and try IsPrefix().
 
                // Searches string. Search head character (or keydata when
                // the head is contraction sortkey) and try IsPrefix().
-               unsafe int IndexOf (COpt opt, string s, string target, int start, int length, byte* checkedFlags, byte* targetSortKey, ref PreviousInfo prev, byte* sk1, byte* sk2)
+               unsafe int IndexOf (string s, string target, int start, int length, byte* targetSortKey, ref Context ctx)
                {
                {
+                       COpt opt = ctx.Option;
                        int tidx = 0;
                        for (; tidx < target.Length; tidx++)
                                if (!IsIgnorable (target [tidx], opt))
                        int tidx = 0;
                        for (; tidx < target.Length; tidx++)
                                if (!IsIgnorable (target [tidx], opt))
@@ -1408,14 +1452,14 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                        do {
                                int idx = 0;
                                if (replace != null)
                        do {
                                int idx = 0;
                                if (replace != null)
-                                       idx = IndexOf (opt, s, replace, start, length, checkedFlags, targetSortKey, ref prev, sk1, sk2);
+                                       idx = IndexOf (s, replace, start, length, targetSortKey, ref ctx);
                                else
                                else
-                                       idx = IndexOfSortKey (opt, s, start, length, sk, tc, ti, noLv4, checkedFlags, ref prev, sk1);
+                                       idx = IndexOfSortKey (s, start, length, sk, tc, ti, noLv4, ref ctx);
                                if (idx < 0)
                                        return -1;
                                length -= idx - start;
                                start = idx;
                                if (idx < 0)
                                        return -1;
                                length -= idx - start;
                                start = idx;
-                               if (IsPrefix (opt, s, target, start, length, false, ref prev, sk1, sk2))
+                               if (IsPrefix (s, target, start, length, false, ref ctx))
                                        return idx;
                                Contraction cts = GetContraction (s, start, length);
                                if (cts != null) {
                                        return idx;
                                Contraction cts = GetContraction (s, start, length);
                                if (cts != null) {
@@ -1441,17 +1485,19 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
 
                public unsafe int LastIndexOf (string s, string target, int start, int length, CompareOptions opt)
                {
 
                public unsafe int LastIndexOf (string s, string target, int start, int length, CompareOptions opt)
                {
-                       PreviousInfo prev = new PreviousInfo (false);
-                       byte* checkedFlags = stackalloc byte [16];
+                       byte* alwaysMatchFlags = stackalloc byte [16];
+                       byte* neverMatchFlags = stackalloc byte [16];
                        byte* targetSortKey = stackalloc byte [4];
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
                        byte* targetSortKey = stackalloc byte [4];
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
-                       ClearBuffer (checkedFlags, 16);
+                       ClearBuffer (alwaysMatchFlags, 16);
+                       ClearBuffer (neverMatchFlags, 16);
                        ClearBuffer (targetSortKey, 4);
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
                        ClearBuffer (targetSortKey, 4);
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
-                       return LastIndexOf (opt, s, target, start, length,
-                               checkedFlags, targetSortKey, ref prev, sk1, sk2);
+                       Context ctx = new Context (opt, alwaysMatchFlags, neverMatchFlags, sk1, sk2, null);
+                       return LastIndexOf (s, target, start, length,
+                               targetSortKey, ref ctx);
                }
 
                public int LastIndexOf (string s, char target, CompareOptions opt)
                }
 
                public int LastIndexOf (string s, char target, CompareOptions opt)
@@ -1461,31 +1507,32 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
 
                public unsafe int LastIndexOf (string s, char target, int start, int length, CompareOptions opt)
                {
 
                public unsafe int LastIndexOf (string s, char target, int start, int length, CompareOptions opt)
                {
-                       PreviousInfo prev = new PreviousInfo (false);
-                       byte* checkedFlags = stackalloc byte [16];
+                       byte* alwaysMatchFlags = stackalloc byte [16];
+                       byte* neverMatchFlags = stackalloc byte [16];
                        byte* targetSortKey = stackalloc byte [4];
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
                        byte* targetSortKey = stackalloc byte [4];
                        byte* sk1 = stackalloc byte [4];
                        byte* sk2 = stackalloc byte [4];
-                       ClearBuffer (checkedFlags, 16);
+                       ClearBuffer (alwaysMatchFlags, 16);
+                       ClearBuffer (neverMatchFlags, 16);
                        ClearBuffer (targetSortKey, 4);
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
                        ClearBuffer (targetSortKey, 4);
                        ClearBuffer (sk1, 4);
                        ClearBuffer (sk2, 4);
+                       Context ctx = new Context (opt, alwaysMatchFlags, neverMatchFlags, sk1, sk2, null);
 
                        // If target is a replacement contraction, then use 
                        // string search.
                        Contraction ct = GetContraction (target);
                        if (ct != null) {
                                if (ct.Replacement != null)
 
                        // If target is a replacement contraction, then use 
                        // string search.
                        Contraction ct = GetContraction (target);
                        if (ct != null) {
                                if (ct.Replacement != null)
-                                       return LastIndexOf (opt, s,
+                                       return LastIndexOf (s,
                                                ct.Replacement, start, length,
                                                ct.Replacement, start, length,
-                                               checkedFlags, targetSortKey, ref prev, sk1, sk2);
+                                               targetSortKey, ref ctx);
                                else {
                                        for (int bi = 0; bi < ct.SortKey.Length; bi++)
                                                sk2 [bi] = ct.SortKey [bi];
                                else {
                                        for (int bi = 0; bi < ct.SortKey.Length; bi++)
                                                sk2 [bi] = ct.SortKey [bi];
-                                       return LastIndexOfSortKey (opt, s, start,
+                                       return LastIndexOfSortKey (s, start,
                                                start, length, sk2,
                                                start, length, sk2,
-                                               -1, true,
-                                               checkedFlags, ref prev, sk1);
+                                               -1, true, ref ctx);
                                }
                        }
                        else {
                                }
                        }
                        else {
@@ -1495,22 +1542,22 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                                if ((opt & COpt.IgnoreNonSpace) == 0)
                                        targetSortKey [2] = Level2 (ti, ExtenderType.None);
                                targetSortKey [3] = Uni.Level3 (ti);
                                if ((opt & COpt.IgnoreNonSpace) == 0)
                                        targetSortKey [2] = Level2 (ti, ExtenderType.None);
                                targetSortKey [3] = Uni.Level3 (ti);
-                               return LastIndexOfSortKey (opt, s, start, start,
+                               return LastIndexOfSortKey (s, start, start,
                                        length, targetSortKey,
                                        ti, !Uni.HasSpecialWeight ((char) ti),
                                        length, targetSortKey,
                                        ti, !Uni.HasSpecialWeight ((char) ti),
-                                       checkedFlags, ref prev, sk1);
+                                       ref ctx);
                        }
                }
 
                // Searches target byte[] keydata
                        }
                }
 
                // Searches target byte[] keydata
-               unsafe int LastIndexOfSortKey (COpt opt, string s, int start, int orgStart, int length, byte* sortkey, int ti, bool noLv4, byte* checkedFlags, ref PreviousInfo prev, byte* sk)
+               unsafe int LastIndexOfSortKey (string s, int start, int orgStart, int length, byte* sortkey, int ti, bool noLv4, ref Context ctx)
                {
                        int end = start - length;
                        int idx = start;
                        while (idx > end) {
                                int cur = idx;
                {
                        int end = start - length;
                        int idx = start;
                        while (idx > end) {
                                int cur = idx;
-                               if (MatchesBackward (opt, s, ref idx, end, orgStart,
-                                       ti, sortkey, noLv4, checkedFlags, ref prev, sk))
+                               if (MatchesBackward (s, ref idx, end, orgStart,
+                                       ti, sortkey, noLv4, ref ctx))
                                        return cur;
                        }
                        return -1;
                                        return cur;
                        }
                        return -1;
@@ -1518,8 +1565,9 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
 
                // Searches string. Search head character (or keydata when
                // the head is contraction sortkey) and try IsPrefix().
 
                // Searches string. Search head character (or keydata when
                // the head is contraction sortkey) and try IsPrefix().
-               unsafe int LastIndexOf (COpt opt, string s, string target, int start, int length, byte* checkedFlags, byte* targetSortKey, ref PreviousInfo prev, byte* sk1, byte* sk2)
+               unsafe int LastIndexOf (string s, string target, int start, int length, byte* targetSortKey, ref Context ctx)
                {
                {
+                       COpt opt = ctx.Option;
                        int orgStart = start;
                        int tidx = 0;
                        for (; tidx < target.Length; tidx++)
                        int orgStart = start;
                        int tidx = 0;
                        for (; tidx < target.Length; tidx++)
@@ -1532,13 +1580,11 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                        byte* sk = replace == null ? targetSortKey : null;
 
                        bool noLv4 = true;
                        byte* sk = replace == null ? targetSortKey : 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) {
                        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], opt);
                                sk [0] = Category (ti);
                                sk [1] = Level1 (ti);
                                ti = FilterOptions (target [tidx], opt);
                                sk [0] = Category (ti);
                                sk [1] = Level1 (ti);
@@ -1561,17 +1607,17 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                                int idx = 0;
 
                                if (replace != null)
                                int idx = 0;
 
                                if (replace != null)
-                                       idx = LastIndexOf (opt, s, replace,
-                                               start, length, checkedFlags,
-                                               targetSortKey, ref prev, sk1, sk2);
+                                       idx = LastIndexOf (s, replace,
+                                               start, length,
+                                               targetSortKey, ref ctx);
                                else
                                else
-                                       idx = LastIndexOfSortKey (opt, s, start, orgStart, length, sk, ti, noLv4, checkedFlags, ref prev, sk1);
+                                       idx = LastIndexOfSortKey (s, start, orgStart, length, sk, ti, noLv4, ref ctx);
                                if (idx < 0)
                                        return -1;
                                length -= start - idx;
                                start = idx;
 
                                if (idx < 0)
                                        return -1;
                                length -= start - idx;
                                start = idx;
 
-                               if (IsPrefix (opt, s, target, idx, orgStart - idx + 1, false, ref prev, sk1, sk2)) {
+                               if (IsPrefix (s, target, idx, orgStart - idx + 1, false, ref ctx)) {
                                        for (;idx < orgStart; idx++)
                                                if (!IsIgnorable (s [idx], opt))
                                                        break;
                                        for (;idx < orgStart; idx++)
                                                if (!IsIgnorable (s [idx], opt))
                                                        break;
@@ -1589,38 +1635,47 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                        return -1;
                }
 
                        return -1;
                }
 
-               unsafe bool MatchesForward (COpt opt, string s, ref int idx, int end, int ti, byte* sortkey, bool noLv4, byte* checkedFlags, ref PreviousInfo prev, byte* sk)
+               unsafe bool MatchesForward (string s, ref int idx, int end, int ti, byte* sortkey, bool noLv4, ref Context ctx)
                {
                {
+                       COpt opt = ctx.Option;
                        int si = s [idx];
                        int si = s [idx];
-                       if (checkedFlags != null && si < 128 && (checkedFlags [si / 8] & (1 << (si % 8))) != 0) {
+                       if (ctx.AlwaysMatchFlags != null && si < 128 && (ctx.AlwaysMatchFlags [si / 8] & (1 << (si % 8))) != 0)
+                               return true;
+                       if (ctx.NeverMatchFlags != null &&
+                                       si < 128 &&
+                                       (ctx.NeverMatchFlags [si / 8] & (1 << (si % 8))) != 0) {
                                idx++;
                                return false;
                        }
                        ExtenderType ext = GetExtenderType (s [idx]);
                        Contraction ct = null;
                                idx++;
                                return false;
                        }
                        ExtenderType ext = GetExtenderType (s [idx]);
                        Contraction ct = null;
-                       if (MatchesForwardCore (opt, s, ref idx, end, ti, sortkey, noLv4, ext, ref ct, checkedFlags, ref prev, sk))
+                       if (MatchesForwardCore (s, ref idx, end, ti, sortkey, noLv4, ext, ref ct, ref ctx)) {
+                               if (ctx.AlwaysMatchFlags != null && ct == null && ext == ExtenderType.None && si < 128)
+                                       ctx.AlwaysMatchFlags [si / 8] |= (byte) (1 << (si % 8));
                                return true;
                                return true;
-                       if (checkedFlags != null && ct == null && ext == ExtenderType.None && si < 128) {
-                               checkedFlags [si / 8] |= (byte) (1 << (si % 8));
                        }
                        }
+                       if (ctx.NeverMatchFlags != null && ct == null && ext == ExtenderType.None && si < 128)
+                               ctx.NeverMatchFlags [si / 8] |= (byte) (1 << (si % 8));
                        return false;
                }
 
                        return false;
                }
 
-               unsafe bool MatchesForwardCore (COpt opt, string s, ref int idx, int end, int ti, byte* sortkey, bool noLv4, ExtenderType ext, ref Contraction ct, byte* checkedFlags, ref PreviousInfo prev, byte* charSortKey)
+               unsafe bool MatchesForwardCore (string s, ref int idx, int end, int ti, byte* sortkey, bool noLv4, ExtenderType ext, ref Contraction ct, ref Context ctx)
                {
                {
+                       COpt opt = ctx.Option;
+                       byte* charSortKey = ctx.Buffer1;
                        bool ignoreNonSpace = (opt & COpt.IgnoreNonSpace) != 0;
                        int si = -1;
                        if (ext == ExtenderType.None)
                                ct = GetContraction (s, idx, end);
                        bool ignoreNonSpace = (opt & COpt.IgnoreNonSpace) != 0;
                        int si = -1;
                        if (ext == ExtenderType.None)
                                ct = GetContraction (s, idx, end);
-                       else if (prev.Code < 0) {
-                               if (prev.SortKey == null) {
+                       else if (ctx.PrevCode < 0) {
+                               if (ctx.PrevSortKey == null) {
                                        idx++;
                                        return false;
                                }
                                        idx++;
                                        return false;
                                }
-                               charSortKey = prev.SortKey;
+                               charSortKey = ctx.PrevSortKey;
                        }
                        else
                        }
                        else
-                               si = FilterExtender (prev.Code, ext, opt);
+                               si = FilterExtender (ctx.PrevCode, ext, opt);
                        // if lv4 exists, it never matches contraction
                        if (ct != null) {
                                idx += ct.Source.Length;
                        // if lv4 exists, it never matches contraction
                        if (ct != null) {
                                idx += ct.Source.Length;
@@ -1629,14 +1684,14 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                                if (ct.SortKey != null) {
                                        for (int i = 0; i < 4; i++)
                                                charSortKey [i] = sortkey [i];
                                if (ct.SortKey != null) {
                                        for (int i = 0; i < 4; i++)
                                                charSortKey [i] = sortkey [i];
-                                       prev.Code = -1;
-                                       prev.SortKey = charSortKey;
+                                       ctx.PrevCode = -1;
+                                       ctx.PrevSortKey = charSortKey;
                                } else {
                                        // Here is the core of LAMESPEC
                                        // described at the top of the source.
                                        int dummy = 0;
                                } else {
                                        // Here is the core of LAMESPEC
                                        // described at the top of the source.
                                        int dummy = 0;
-                                       return MatchesForward (opt, ct.Replacement, ref dummy,
-                                               ct.Replacement.Length, ti, sortkey, noLv4, checkedFlags, ref prev, charSortKey);
+                                       return MatchesForward (ct.Replacement, ref dummy,
+                                               ct.Replacement.Length, ti, sortkey, noLv4, ref ctx);
                                }
                        } else {
                                if (si < 0)
                                }
                        } else {
                                if (si < 0)
@@ -1661,7 +1716,7 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                                }
                                charSortKey [3] = Uni.Level3 (si);
                                if (charSortKey [0] != 1)
                                }
                                charSortKey [3] = Uni.Level3 (si);
                                if (charSortKey [0] != 1)
-                                       prev.Code = si;
+                                       ctx.PrevCode = si;
                        }
                        for (; idx < end; idx++) {
                                if (Category (s [idx]) != 1)
                        }
                        for (; idx < end; idx++) {
                                if (Category (s [idx]) != 1)
@@ -1706,25 +1761,32 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                        return true;
                }
 
                        return true;
                }
 
-               unsafe bool MatchesBackward (COpt opt, string s, ref int idx, int end, int orgStart, int ti, byte* sortkey, bool noLv4, byte* checkedFlags, ref PreviousInfo prev, byte* sk)
+               unsafe bool MatchesBackward (string s, ref int idx, int end, int orgStart, int ti, byte* sortkey, bool noLv4, ref Context ctx)
                {
                        int si = s [idx];
                {
                        int si = s [idx];
-                       if (checkedFlags != null && si < 128 && (checkedFlags [si / 8] & (1 << (si % 8))) != 0) {
+                       if (ctx.AlwaysMatchFlags != null && si < 128 && (ctx.AlwaysMatchFlags [si / 8] & (1 << (si % 8))) != 0)
+                               return true;
+                       if (ctx.NeverMatchFlags != null && si < 128 && (ctx.NeverMatchFlags [si / 8] & (1 << (si % 8))) != 0) {
                                idx--;
                                return false;
                        }
                        ExtenderType ext = GetExtenderType (s [idx]);
                        Contraction ct = null;
                                idx--;
                                return false;
                        }
                        ExtenderType ext = GetExtenderType (s [idx]);
                        Contraction ct = null;
-                       if (MatchesBackwardCore (opt, s, ref idx, end, orgStart, ti, sortkey, noLv4, ext, ref ct, checkedFlags, ref prev, sk))
+                       if (MatchesBackwardCore (s, ref idx, end, orgStart, ti, sortkey, noLv4, ext, ref ct, ref ctx)) {
+                               if (ctx.AlwaysMatchFlags != null && ct == null && ext == ExtenderType.None && si < 128)
+                                       ctx.AlwaysMatchFlags [si / 8] |= (byte) (1 << (si % 8));
                                return true;
                                return true;
-                       if (checkedFlags != null && ct == null && ext == ExtenderType.None && si < 128) {
-                               checkedFlags [si / 8] |= (byte) (1 << (si % 8));
+                       }
+                       if (ctx.NeverMatchFlags != null && ct == null && ext == ExtenderType.None && si < 128) {
+                               ctx.NeverMatchFlags [si / 8] |= (byte) (1 << (si % 8));
                        }
                        return false;
                }
 
                        }
                        return false;
                }
 
-               unsafe bool MatchesBackwardCore (COpt opt, string s, ref int idx, int end, int orgStart, int ti, byte* sortkey, bool noLv4, ExtenderType ext, ref Contraction ct, byte* checkedFlags, ref PreviousInfo prev, byte* charSortKey)
+               unsafe bool MatchesBackwardCore (string s, ref int idx, int end, int orgStart, int ti, byte* sortkey, bool noLv4, ExtenderType ext, ref Contraction ct, ref Context ctx)
                {
                {
+                       COpt opt = ctx.Option;
+                       byte* charSortKey = ctx.Buffer1;
                        bool ignoreNonSpace = (opt & COpt.IgnoreNonSpace) != 0;
                        int cur = idx;
                        int si = -1;
                        bool ignoreNonSpace = (opt & COpt.IgnoreNonSpace) != 0;
                        int cur = idx;
                        int si = -1;
@@ -1769,17 +1831,16 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                                if (ct.SortKey != null) {
                                        for (int i = 0; i < 4; i++)
                                                charSortKey [i] = sortkey [i];
                                if (ct.SortKey != null) {
                                        for (int i = 0; i < 4; i++)
                                                charSortKey [i] = sortkey [i];
-                                       prev.Code = -1;
-                                       prev.SortKey = charSortKey;
+                                       ctx.PrevCode = -1;
+                                       ctx.PrevSortKey = charSortKey;
                                } else {
                                        // Here is the core of LAMESPEC
                                        // described at the top of the source.
                                        int dummy = ct.Replacement.Length - 1;
                                } else {
                                        // Here is the core of LAMESPEC
                                        // described at the top of the source.
                                        int dummy = ct.Replacement.Length - 1;
-                                       return 0 <= LastIndexOfSortKey (opt,
+                                       return 0 <= LastIndexOfSortKey (
                                                ct.Replacement, dummy, dummy,
                                                ct.Replacement.Length, sortkey,
                                                ct.Replacement, dummy, dummy,
                                                ct.Replacement.Length, sortkey,
-                                               ti, noLv4, checkedFlags,
-                                               ref prev, charSortKey);
+                                               ti, noLv4, ref ctx);
                                }
                        } else if (ext == ExtenderType.None) {
                                if (si < 0)
                                }
                        } else if (ext == ExtenderType.None) {
                                if (si < 0)
@@ -1799,7 +1860,7 @@ Console.WriteLine ("==== {0} {1} {2} {3} {4} {5} {6} {7} {8}", s, si, send, leng
                                        return false;
                                charSortKey [3] = Uni.Level3 (si);
                                if (charSortKey [0] != 1)
                                        return false;
                                charSortKey [3] = Uni.Level3 (si);
                                if (charSortKey [0] != 1)
-                                       prev.Code = si;
+                                       ctx.PrevCode = si;
                        }
                        if (ext == ExtenderType.None) {
                                for (int tmp = cur + 1; tmp < orgStart; tmp++) {
                        }
                        if (ext == ExtenderType.None) {
                                for (int tmp = cur + 1; tmp < orgStart; tmp++) {