Commit 9c0f5be8 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Correctly convert micro-sign to its upper case.

R=dcarney@chromium.org
BUG=355485
LOG=N

Review URL: https://codereview.chromium.org/209323007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20197 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2c8229f6
......@@ -6312,6 +6312,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
}
static inline bool ToUpperOverflows(uc32 character) {
// y with umlauts and the micro sign are the only characters that stop
// fitting into one-byte when converting to uppercase.
static const uc32 yuml_code = 0xff;
static const uc32 micro_code = 0xb5;
return (character == yuml_code || character == micro_code);
}
template <class Converter>
MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
Isolate* isolate,
......@@ -6339,10 +6348,7 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
unibrow::uchar chars[Converter::kMaxWidth];
// We can assume that the string is not empty
uc32 current = stream.GetNext();
// y with umlauts is the only character that stops fitting into one-byte
// when converting to uppercase.
static const uc32 yuml_code = 0xff;
bool ignore_yuml = result->IsSeqTwoByteString() || Converter::kIsToLower;
bool ignore_overflow = Converter::kIsToLower || result->IsSeqTwoByteString();
for (int i = 0; i < result_length;) {
bool has_next = stream.HasMore();
uc32 next = has_next ? stream.GetNext() : 0;
......@@ -6351,14 +6357,15 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
// The case conversion of this character is the character itself.
result->Set(i, current);
i++;
} else if (char_length == 1 && (ignore_yuml || current != yuml_code)) {
} else if (char_length == 1 &&
(ignore_overflow || !ToUpperOverflows(current))) {
// Common case: converting the letter resulted in one character.
ASSERT(static_cast<uc32>(chars[0]) != current);
result->Set(i, chars[0]);
has_changed_character = true;
i++;
} else if (result_length == string->length()) {
bool found_yuml = (current == yuml_code);
bool overflows = ToUpperOverflows(current);
// We've assumed that the result would be as long as the
// input but here is a character that converts to several
// characters. No matter, we calculate the exact length
......@@ -6378,7 +6385,7 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
int current_length = i + char_length + next_length;
while (stream.HasMore()) {
current = stream.GetNext();
found_yuml |= (current == yuml_code);
overflows |= ToUpperOverflows(current);
// NOTE: we use 0 as the next character here because, while
// the next character may affect what a character converts to,
// it does not in any case affect the length of what it convert
......@@ -6392,9 +6399,9 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
}
}
// Try again with the real length. Return signed if we need
// to allocate a two-byte string for y-umlaut to uppercase.
return (found_yuml && !ignore_yuml) ? Smi::FromInt(-current_length)
: Smi::FromInt(current_length);
// to allocate a two-byte string for to uppercase.
return (overflows && !ignore_overflow) ? Smi::FromInt(-current_length)
: Smi::FromInt(current_length);
} else {
for (int j = 0; j < char_length; j++) {
result->Set(i, chars[j]);
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
assertEquals("\u039c", "\u00b5".toUpperCase());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment