/// <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); }