public int Compare (object o1, object o2) { Contraction c1 = (Contraction) o1; Contraction c2 = (Contraction) o2; char [] a1 = c1.Source; char [] a2 = c2.Source; int min = a1.Length > a2.Length ? a2.Length : a1.Length; for (int i = 0; i < min; i++) if (a1 [i] != a2 [i]) return a1 [i] - a2 [i]; return a1.Length - a2.Length; }
public int Compare (object o1, object o2) { Contraction c1 = (Contraction) o1; Contraction c2 = (Contraction) o2; char [] a1 = c1.Source; char [] a2 = c2.Source; int min = a1.Length > a2.Length ? a2.Length : a1.Length; for (int i = 0; i < min; i++) if (a1 [i] != a2 [i]) return a1 [i] - a2 [i]; if (a1.Length != a2.Length) return a1.Length - a2.Length; // This makes the sorting stable, since we are using Array.Sort () which is // not stable return c1.Index - c2.Index; }
Contraction GetContraction (char c, Contraction [] clist) { for (int i = 0; i < clist.Length; i++) { Contraction ct = clist [i]; if (ct.Source [0] > c) return null; // it's already sorted if (ct.Source [0] == c && ct.Source.Length == 1) return ct; } return null; }
Contraction GetTailContraction (string s, int start, int end, Contraction [] clist) { if (start == end || end < -1 || start >= s.Length || s.Length <= end + 1) throw new SystemException (String.Format ("MONO internal error. Failed to get TailContraction. start = {0} end = {1} string = '{2}'", start, end, s)); for (int i = 0; i < clist.Length; i++) { Contraction ct = clist [i]; char [] chars = ct.Source; if (chars.Length > start - end) continue; if (chars [chars.Length - 1] != s [start]) continue; bool match = true; for (int n = 0, spos = start - chars.Length + 1; n < chars.Length; n++, spos++) { if (s [spos] != chars [n]) { match = false; break; } } if (match) return ct; } return null; }
Contraction GetContraction (string s, int start, int end, Contraction [] clist) { for (int i = 0; i < clist.Length; i++) { Contraction ct = clist [i]; int diff = ct.Source [0] - s [start]; if (diff > 0) return null; // it's already sorted else if (diff < 0) continue; char [] chars = ct.Source; if (end - start < chars.Length) continue; bool match = true; for (int n = 0; n < chars.Length; n++) if (s [start + n] != chars [n]) { match = false; break; } if (match) return ct; } return null; }
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; // To handle extenders in source, we need to // check next _primary_ character. if (ext != ExtenderType.None) { byte diacritical = 0; for (int tmp = idx; ; tmp--) { if (tmp < 0) // heading extender return false; if (IsIgnorable (s [tmp], opt)) continue; int tmpi = FilterOptions (s [tmp], opt); byte category = Category (tmpi); if (category == 1) { diacritical = Level2 (tmpi, ExtenderType.None); continue; } si = FilterExtender (tmpi, ext, opt); 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--; } if (ext == ExtenderType.None) ct = GetTailContraction (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 < 4; i++) charSortKey [i] = sortkey [i]; 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; return 0 <= LastIndexOfSortKey ( ct.Replacement, dummy, dummy, ct.Replacement.Length, sortkey, ti, noLv4, ref ctx); } } else if (ext == ExtenderType.None) { if (si < 0) si = FilterOptions (s [idx], opt); idx--; bool noMatch = false; charSortKey [0] = Category (si); if (charSortKey [0] == sortkey [0]) charSortKey [1] = Level1 (si); else noMatch = true; if (!ignoreNonSpace && charSortKey [1] == sortkey [1]) charSortKey [2] = Level2 (si, ext); else if (!ignoreNonSpace) noMatch = true; if (noMatch) return false; charSortKey [3] = Uni.Level3 (si); if (charSortKey [0] != 1) ctx.PrevCode = si; } 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 (opt, charSortKey, si, ext, sortkey, ti, noLv4); }
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); else if (ctx.PrevCode < 0) { if (ctx.PrevSortKey == null) { idx++; return false; } charSortKey = ctx.PrevSortKey; } else si = FilterExtender (ctx.PrevCode, ext, opt); // 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 < 4; i++) charSortKey [i] = sortkey [i]; ctx.PrevCode = -1; ctx.PrevSortKey = charSortKey; } else { // Here is the core of LAMESPEC // described at the top of the source. int dummy = 0; return MatchesForward (ct.Replacement, ref dummy, ct.Replacement.Length, ti, sortkey, noLv4, ref ctx); } } else { if (si < 0) si = FilterOptions (s [idx], opt); idx++; charSortKey [0] = Category (si); bool noMatch = false; if (sortkey [0] == charSortKey [0]) charSortKey [1] = Level1 (si); else noMatch = true; if (!ignoreNonSpace && sortkey [1] == charSortKey [1]) charSortKey [2] = Level2 (si, ext); else if (!ignoreNonSpace) noMatch = true; if (noMatch) { for (; idx < end; idx++) { if (Category (s [idx]) != 1) break; } return false; } charSortKey [3] = Uni.Level3 (si); if (charSortKey [0] != 1) ctx.PrevCode = si; } for (; idx < end; idx++) { if (Category (s [idx]) != 1) break; if (ignoreNonSpace) continue; if (charSortKey [2] == 0) charSortKey [2] = 2; charSortKey [2] = (byte) (charSortKey [2] + Level2 (s [idx], ExtenderType.None)); } return MatchesPrimitive (opt, charSortKey, si, ext, sortkey, ti, noLv4); }
unsafe public static void BuildTailoringTables (CultureInfo culture, TailoringInfo t, ref Contraction [] contractions, ref Level2Map [] diacriticals) { // collect tailoring entries. ArrayList cmaps = new ArrayList (); ArrayList dmaps = new ArrayList (); fixed (char* tarr = tailoringArr){ int idx = t.TailoringIndex; int end = idx + t.TailoringCount; while (idx < end) { int ss = idx + 1; char [] src = null; switch (tarr [idx]) { case '\x1': // SortKeyMap idx++; while (tarr [ss] != 0) ss++; src = new char [ss - idx]; // Array.Copy (tarr, idx, src, 0, ss - idx); Marshal.Copy ((IntPtr) (tarr + idx), src, 0, ss - idx); byte [] sortkey = new byte [4]; for (int i = 0; i < 4; i++) sortkey [i] = (byte) tarr [ss + 1 + i]; cmaps.Add (new Contraction ( src, null, sortkey)); // it ends with 0 idx = ss + 6; break; case '\x2': // DiacriticalMap dmaps.Add (new Level2Map ( (byte) tarr [idx + 1], (byte) tarr [idx + 2])); idx += 3; break; case '\x3': // ReplacementMap idx++; while (tarr [ss] != 0) ss++; src = new char [ss - idx]; // Array.Copy (tarr, idx, src, 0, ss - idx); Marshal.Copy ((IntPtr) (tarr + idx), src, 0, ss - idx); ss++; int l = ss; while (tarr [l] != 0) l++; string r = new string (tarr, ss, l - ss); cmaps.Add (new Contraction ( src, r, null)); idx = l + 1; break; default: throw new NotImplementedException (String.Format ("Mono INTERNAL ERROR (Should not happen): Collation tailoring table is broken for culture {0} ({1}) at 0x{2:X}", culture.LCID, culture.Name, idx)); } } } cmaps.Sort (ContractionComparer.Instance); dmaps.Sort (Level2MapComparer.Instance); contractions = cmaps.ToArray (typeof (Contraction)) as Contraction []; diacriticals = dmaps.ToArray (typeof (Level2Map)) as Level2Map []; }