/// <summary> /// Transliterate the given text with the given UTransPosition /// indices. Return TRUE if the transliteration should continue /// or FALSE if it should halt (because of a U_PARTIAL_MATCH match). /// Note that FALSE is only ever returned if isIncremental is TRUE. /// </summary> /// <param name="text">The text to be transliterated.</param> /// <param name="pos">The position indices, which will be updated.</param> /// <param name="incremental">If TRUE, assume new text may be inserted /// at index.Limit, and return FALSE if thre is a partial match.</param> /// <returns>TRUE unless a U_PARTIAL_MATCH has been obtained, /// indicating that transliteration should stop until more text /// arrives.</returns> public virtual bool Transliterate(IReplaceable text, TransliterationPosition pos, bool incremental) { int indexByte = text.Char32At(pos.Start) & 0xFF; for (int i = index[indexByte]; i < index[indexByte + 1]; ++i) { MatchDegree m = rules[i].MatchAndReplace(text, pos, incremental); switch (m) { case MatchDegree.Match: if (Transliterator.DEBUG) { Console.Out.WriteLine((incremental ? "Rule.i: match " : "Rule: match ") + rules[i].ToRule(true) + " => " + UtilityExtensions.FormatInput(text, pos)); } return(true); case MatchDegree.PartialMatch: if (Transliterator.DEBUG) { Console.Out.WriteLine((incremental ? "Rule.i: partial match " : "Rule: partial match ") + rules[i].ToRule(true) + " => " + UtilityExtensions.FormatInput(text, pos)); } return(false); default: if (Transliterator.DEBUG) { Console.Out.WriteLine("Rule: no match " + rules[i]); } break; } } // No match or partial match from any rule pos.Start += UTF16.GetCharCount(text.Char32At(pos.Start)); if (Transliterator.DEBUG) { Console.Out.WriteLine((incremental ? "Rule.i: no match => " : "Rule: no match => ") + UtilityExtensions.FormatInput(text, pos)); } return(true); }
/// <summary> /// Implement <see cref="IUnicodeMatcher"/> API. /// </summary> public virtual MatchDegree Matches(IReplaceable text, int[] offset, int limit, bool incremental) { int start = offset[0]; int count = 0; while (count < maxCount) { int pos = offset[0]; MatchDegree m = matcher.Matches(text, offset, limit, incremental); if (m == MatchDegree.Match) { ++count; if (pos == offset[0]) { // If offset has not moved we have a zero-width match. // Don't keep matching it infinitely. break; } } else if (incremental && m == MatchDegree.PartialMatch) { return(MatchDegree.PartialMatch); } else { break; } } if (incremental && offset[0] == limit) { return(MatchDegree.PartialMatch); } if (count >= minCount) { return(MatchDegree.Match); } offset[0] = start; return(MatchDegree.Mismatch); }
/// <summary> /// Implement <see cref="IUnicodeMatcher"/> /// </summary> public virtual MatchDegree Matches(IReplaceable text, int[] offset, int limit, bool incremental) { // Note (1): We process text in 16-bit code units, rather than // 32-bit code points. This works because stand-ins are // always in the BMP and because we are doing a literal match // operation, which can be done 16-bits at a time. int i; int[] cursor = new int[] { offset[0] }; if (limit < cursor[0]) { // Match in the reverse direction for (i = pattern.Length - 1; i >= 0; --i) { char keyChar = pattern[i]; // OK; see note (1) above IUnicodeMatcher subm = data.LookupMatcher(keyChar); if (subm == null) { if (cursor[0] > limit && keyChar == text[cursor[0]]) { // OK; see note (1) above --cursor[0]; } else { return(MatchDegree.Mismatch); } } else { MatchDegree m = subm.Matches(text, cursor, limit, incremental); if (m != MatchDegree.Match) { return(m); } } } // Record the match position, but adjust for a normal // forward start, limit, and only if a prior match does not // exist -- we want the rightmost match. if (matchStart < 0) { matchStart = cursor[0] + 1; matchLimit = offset[0] + 1; } } else { for (i = 0; i < pattern.Length; ++i) { if (incremental && cursor[0] == limit) { // We've reached the context limit without a mismatch and // without completing our match. return(MatchDegree.PartialMatch); } char keyChar = pattern[i]; // OK; see note (1) above IUnicodeMatcher subm = data.LookupMatcher(keyChar); if (subm == null) { // Don't need the cursor < limit check if // incremental is true (because it's done above); do need // it otherwise. if (cursor[0] < limit && keyChar == text[cursor[0]]) { // OK; see note (1) above ++cursor[0]; } else { return(MatchDegree.Mismatch); } } else { MatchDegree m = subm.Matches(text, cursor, limit, incremental); if (m != MatchDegree.Match) { return(m); } } } // Record the match position matchStart = offset[0]; matchLimit = cursor[0]; } offset[0] = cursor[0]; return(MatchDegree.Match); }