/// <summary> /// Implements <see cref="M:IBM.ICU.Text.Transliterator.HandleTransliterate(IBM.ICU.Text.Replaceable, null, System.Boolean)"/>. /// </summary> /// protected internal override void HandleTransliterate(Replaceable text, Transliterator.Position offsets, bool isIncremental) { if (csp == null) { return; } if (offsets.start >= offsets.limit) { return; } iter.SetText(text); result.Length = 0; int c, delta; // Walk through original string // If there is a case change, modify corresponding position in // replaceable iter.SetIndex(offsets.start); iter.SetLimit(offsets.limit); iter.SetContextLimits(offsets.contextStart, offsets.contextLimit); while ((c = iter.NextCaseMapCP()) >= 0) { c = csp.ToFullUpper(c, iter, result, locale, locCache); if (iter.DidReachLimit() && isIncremental) { // the case mapping function tried to look beyond the context // limit // wait for more input offsets.start = iter.GetCaseMapCPStart(); return; } /* decode the result */ if (c < 0) { /* c mapped to itself, no change */ continue; } else if (c <= IBM.ICU.Impl.UCaseProps.MAX_STRING_LENGTH) { /* replace by the mapping string */ delta = iter.Replace(result.ToString()); result.Length = 0; } else { /* replace by single-code point mapping */ delta = iter.Replace(IBM.ICU.Text.UTF16.ValueOf(c)); } if (delta != 0) { offsets.limit += delta; offsets.contextLimit += delta; } } offsets.start = offsets.limit; }
/// <summary> /// Implements <see cref="M:IBM.ICU.Text.Transliterator.HandleTransliterate(IBM.ICU.Text.Replaceable, null, System.Boolean)"/>. /// </summary> /// protected internal override void HandleTransliterate(Replaceable text, Transliterator.Position offsets, bool isIncremental) { // TODO reimplement, see ustrcase.c // using a real word break iterator // instead of just looking for a transition between cased and uncased // characters // call CaseMapTransliterator::handleTransliterate() for lowercasing? // (set fMap) // needs to take isIncremental into account because case mappings are // context-sensitive // also detect when lowercasing function did not finish because of // context if (offsets.start >= offsets.limit) { return; } // case type: >0 cased (UCaseProps.LOWER etc.) ==0 uncased <0 // case-ignorable int type; // Our mode; we are either converting letter toTitle or // toLower. bool doTitle = true; // Determine if there is a preceding context of cased case-ignorable*, // in which case we want to start in toLower mode. If the // prior context is anything else (including empty) then start // in toTitle mode. int c, start; for (start = offsets.start - 1; start >= offsets.contextStart; start -= IBM.ICU.Text.UTF16 .GetCharCount(c)) { c = text.Char32At(start); type = csp.GetTypeOrIgnorable(c); if (type > 0) // cased { doTitle = false; break; } else if (type == 0) // uncased but not ignorable { break; } // else (type<0) case-ignorable: continue } // Convert things after a cased character toLower; things // after a uncased, non-case-ignorable character toTitle. Case-ignorable // characters are copied directly and do not change the mode. iter.SetText(text); iter.SetIndex(offsets.start); iter.SetLimit(offsets.limit); iter.SetContextLimits(offsets.contextStart, offsets.contextLimit); result.Length = 0; // Walk through original string // If there is a case change, modify corresponding position in // replaceable int delta; while ((c = iter.NextCaseMapCP()) >= 0) { type = csp.GetTypeOrIgnorable(c); if (type >= 0) // not case-ignorable { if (doTitle) { c = csp.ToFullTitle(c, iter, result, locale, locCache); } else { c = csp.ToFullLower(c, iter, result, locale, locCache); } doTitle = type == 0; // doTitle=isUncased if (iter.DidReachLimit() && isIncremental) { // the case mapping function tried to look beyond the // context limit // wait for more input offsets.start = iter.GetCaseMapCPStart(); return; } /* decode the result */ if (c < 0) { /* c mapped to itself, no change */ continue; } else if (c <= IBM.ICU.Impl.UCaseProps.MAX_STRING_LENGTH) { /* replace by the mapping string */ delta = iter.Replace(result.ToString()); result.Length = 0; } else { /* replace by single-code point mapping */ delta = iter.Replace(IBM.ICU.Text.UTF16.ValueOf(c)); } if (delta != 0) { offsets.limit += delta; offsets.contextLimit += delta; } } } offsets.start = offsets.limit; }