| Index: base/i18n/case_conversion.cc
|
| diff --git a/base/i18n/case_conversion.cc b/base/i18n/case_conversion.cc
|
| index 5debc2ec8d662aec1cf347c293686bb1f7a59fbd..d0eceb90920572397ca8d7af0c61005ea8cdfa10 100644
|
| --- a/base/i18n/case_conversion.cc
|
| +++ b/base/i18n/case_conversion.cc
|
| @@ -4,22 +4,91 @@
|
|
|
| #include "base/i18n/case_conversion.h"
|
|
|
| +#include "base/numerics/safe_conversions.h"
|
| #include "base/strings/string16.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "third_party/icu/source/common/unicode/uchar.h"
|
| #include "third_party/icu/source/common/unicode/unistr.h"
|
| +#include "third_party/icu/source/common/unicode/ustring.h"
|
|
|
| namespace base {
|
| namespace i18n {
|
|
|
| -string16 ToLower(const StringPiece16& string) {
|
| - icu::UnicodeString unicode_string(string.data(), string.size());
|
| - unicode_string.toLower();
|
| - return string16(unicode_string.getBuffer(), unicode_string.length());
|
| +namespace {
|
| +
|
| +// Provides a uniform interface for upper/lower/folding which take take
|
| +// slightly varying parameters.
|
| +typedef int32_t (*CaseMapperFunction)(UChar* dest,
|
| + int32_t dest_capacity,
|
| + const UChar* src,
|
| + int32_t src_length,
|
| + UErrorCode* error);
|
| +
|
| +int32_t ToUpperMapper(UChar* dest,
|
| + int32_t dest_capacity,
|
| + const UChar* src,
|
| + int32_t src_length,
|
| + UErrorCode* error) {
|
| + // Use default locale.
|
| + return u_strToUpper(dest, dest_capacity, src, src_length, NULL, error);
|
| +}
|
| +
|
| +int32_t ToLowerMapper(UChar* dest,
|
| + int32_t dest_capacity,
|
| + const UChar* src,
|
| + int32_t src_length,
|
| + UErrorCode* error) {
|
| + // Use default locale.
|
| + return u_strToLower(dest, dest_capacity, src, src_length, NULL, error);
|
| +}
|
| +
|
| +int32_t FoldCaseMapper(UChar* dest,
|
| + int32_t dest_capacity,
|
| + const UChar* src,
|
| + int32_t src_length,
|
| + UErrorCode* error) {
|
| + return u_strFoldCase(dest, dest_capacity, src, src_length,
|
| + U_FOLD_CASE_DEFAULT, error);
|
| +}
|
| +
|
| +// Provides similar functionality as UnicodeString::caseMap but on string16.
|
| +string16 CaseMap(StringPiece16 string, CaseMapperFunction case_mapper) {
|
| + string16 dest;
|
| + if (string.empty())
|
| + return dest;
|
| +
|
| + // Provide an initial guess that the string length won't change. The typical
|
| + // strings we use will very rarely change length in this process, so don't
|
| + // optimize for that case.
|
| + dest.resize(string.size());
|
| +
|
| + UErrorCode error;
|
| + do {
|
| + error = U_ZERO_ERROR;
|
| +
|
| + // ICU won't terminate the string if there's not enough room for the null
|
| + // terminator, but will otherwise. So we don't need to save room for that.
|
| + // Don't use WriteInto, which assumes null terminators.
|
| + int32_t new_length = case_mapper(
|
| + &dest[0], saturated_cast<int32_t>(dest.size()), string.data(),
|
| + saturated_cast<int32_t>(string.size()), &error);
|
| + dest.resize(new_length);
|
| + } while (error == U_BUFFER_OVERFLOW_ERROR);
|
| + return dest;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +string16 ToLower(StringPiece16 string) {
|
| + return CaseMap(string, &ToLowerMapper);
|
| +}
|
| +
|
| +string16 ToUpper(StringPiece16 string) {
|
| + return CaseMap(string, &ToUpperMapper);
|
| }
|
|
|
| -string16 ToUpper(const StringPiece16& string) {
|
| - icu::UnicodeString unicode_string(string.data(), string.size());
|
| - unicode_string.toUpper();
|
| - return string16(unicode_string.getBuffer(), unicode_string.length());
|
| +string16 FoldCase(StringPiece16 string) {
|
| + return CaseMap(string, &FoldCaseMapper);
|
| }
|
|
|
| } // namespace i18n
|
|
|