diff --git a/icu4c/source/i18n/tolowtrn.cpp b/icu4c/source/i18n/tolowtrn.cpp index a0e1380e79..954d880f13 100644 --- a/icu4c/source/i18n/tolowtrn.cpp +++ b/icu4c/source/i18n/tolowtrn.cpp @@ -75,32 +75,35 @@ void LowercaseTransliterator::handleTransliterate(Replaceable& text, UnicodeString original; text.extractBetween(offsets.contextStart, offsets.contextLimit, original); + UCharIterator iter; + uiter_setReplaceable(&iter, &text); + iter.start = offsets.contextStart; + iter.limit = offsets.contextLimit; + // Walk through original string // If there is a case change, modify corresponding position in replaceable int32_t i = textPos - offsets.contextStart; int32_t limit = offsets.limit - offsets.contextStart; - UChar32 cp, bufferCH; + UChar32 cp; int32_t oldLen; for (; i < limit; ) { UErrorCode status = U_ZERO_ERROR; int32_t s = i; - bufferCH = original.char32At(s); UTF_GET_CHAR(original.getBuffer(), 0, i, original.length(), cp); oldLen = UTF_CHAR_LENGTH(cp); i += oldLen; - int32_t len = u_strToLower(buffer, u_getMaxCaseExpansion(), original.getBuffer()+s, i-s, loc.getName(), &status); - /* Skip checking of status code here because the buffer should not have overflowed. */ - UTF_GET_CHAR(buffer, 0, 0, len, cp); - if ( bufferCH != cp ) { - UnicodeString temp(buffer); + iter.index = i; // Point _past_ current char + int32_t newLen = u_internalToLower(cp, &iter, buffer, u_getMaxCaseExpansion(), loc.getName()); + if (newLen >= 0) { + UnicodeString temp(buffer, newLen); text.handleReplaceBetween(textPos, textPos + oldLen, temp); - if (len != oldLen) { - textPos += len; - offsets.limit += len - oldLen; - offsets.contextLimit += len - oldLen; + if (newLen != oldLen) { + textPos += newLen; + offsets.limit += newLen - oldLen; + offsets.contextLimit += newLen - oldLen; continue; } } diff --git a/icu4c/source/i18n/toupptrn.cpp b/icu4c/source/i18n/toupptrn.cpp index 2f215c2704..b0ae0cc896 100644 --- a/icu4c/source/i18n/toupptrn.cpp +++ b/icu4c/source/i18n/toupptrn.cpp @@ -77,33 +77,36 @@ void UppercaseTransliterator::handleTransliterate(Replaceable& text, UnicodeString original; text.extractBetween(offsets.contextStart, offsets.contextLimit, original); + + UCharIterator iter; + uiter_setReplaceable(&iter, &text); + iter.start = offsets.contextStart; + iter.limit = offsets.contextLimit; // Walk through original string // If there is a case change, modify corresponding position in replaceable int32_t i = textPos - offsets.contextStart; int32_t limit = offsets.limit - offsets.contextStart; - UChar32 cp, bufferCH; + UChar32 cp; int32_t oldLen; for (; i < limit; ) { UErrorCode status = U_ZERO_ERROR; int32_t s = i; - bufferCH = original.char32At(s); UTF_GET_CHAR(original.getBuffer(), 0, i, original.length(), cp); oldLen = UTF_CHAR_LENGTH(cp); i += oldLen; - int32_t len = u_strToUpper(buffer, u_getMaxCaseExpansion(), original.getBuffer()+s, i-s, loc.getName(), &status); - /* Skip checking of status code here because the buffer should not have overflowed. */ - UTF_GET_CHAR(buffer, 0, 0, len, cp); - if (bufferCH != cp) { - UnicodeString temp(buffer); + iter.index = i; // Point _past_ current char + int32_t newLen = u_internalToUpper(cp, &iter, buffer, u_getMaxCaseExpansion(), loc.getName()); + if (newLen >= 0) { + UnicodeString temp(buffer, newLen); text.handleReplaceBetween(textPos, textPos + oldLen, temp); - if (len != oldLen) { - textPos += len; - offsets.limit += len - oldLen; - offsets.contextLimit += len - oldLen; + if (newLen != oldLen) { + textPos += newLen; + offsets.limit += newLen - oldLen; + offsets.contextLimit += newLen - oldLen; continue; } }