Chromium Code Reviews| Index: runtime/platform/json.cc |
| diff --git a/runtime/platform/json.cc b/runtime/platform/json.cc |
| index a406e7a5728bf96303387fbaa070c0e2af6f55a0..cc57a4b5bd72b676c8794c7977021ff86ec094cd 100644 |
| --- a/runtime/platform/json.cc |
| +++ b/runtime/platform/json.cc |
| @@ -642,6 +642,23 @@ void TextBuffer::AddEscapedString(const char* s) { |
| } |
| +void TextBuffer::AddEscapedUTF8String(const char* s) { |
| + intptr_t len = strlen(s); |
| + const uint8_t* s8 = reinterpret_cast<const uint8_t*>(s); |
| + intptr_t i = 0; |
| + for (; i < len; ) { |
| + // Extract next UTF8 character. |
| + uint32_t ch = 0; |
| + uint32_t ch_len = Utf8Decode(&s8[i], len - i, &ch); |
| + ASSERT(ch_len != 0); |
| + AddEscapedChar(ch); |
| + // Move i forward. |
| + i += ch_len; |
| + } |
| + ASSERT(i == len); |
| +} |
| + |
| + |
| void TextBuffer::EnsureCapacity(intptr_t len) { |
| intptr_t remaining = buf_size_ - msg_len_; |
| if (remaining <= len) { |
| @@ -658,4 +675,100 @@ void TextBuffer::EnsureCapacity(intptr_t len) { |
| } |
| } |
| + |
| +static const uint32_t kMaxCodePoint = 0x10FFFF; |
|
turnidge
2014/03/10 21:03:28
I don't like duplicating the existing unicode deco
|
| + |
| + |
| +static const int8_t kTrailBytes[256] = { |
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 |
| +}; |
| + |
| + |
| +static const uint32_t kMagicBits[7] = { |
| + 0, // Padding. |
| + 0x00000000, |
| + 0x00003080, |
| + 0x000E2080, |
| + 0x03C82080, |
| + 0xFA082080, |
| + 0x82082080 |
| +}; |
| + |
| + |
| +// Minimum values of code points used to check shortest form. |
| +static const uint32_t kOverlongMinimum[7] = { |
| + 0, // Padding. |
| + 0x0, |
| + 0x80, |
| + 0x800, |
| + 0x10000, |
| + 0xFFFFFFFF, |
| + 0xFFFFFFFF |
| +}; |
| + |
| + |
| +static bool IsTrailByte(uint8_t code_unit) { |
| + return (code_unit & 0xC0) == 0x80; |
| +} |
| + |
| +static bool IsOutOfRange(uint32_t code_point) { |
| + return code_point > kMaxCodePoint; |
| +} |
| + |
| + |
| +static bool IsNonShortestForm(uint32_t code_point, size_t num_code_units) { |
| + return code_point < kOverlongMinimum[num_code_units]; |
| +} |
| + |
| +static bool IsSurrogate(int32_t ch) { |
| + return (ch & 0xFFFFF800) == 0xD800; |
| +} |
| + |
| +uint32_t TextBuffer::Utf8Decode( |
| + const uint8_t* utf8_array, intptr_t array_len, uint32_t* dst) { |
| + uint32_t ch = utf8_array[0] & 0xFF; |
| + intptr_t i = 1; |
| + if (ch >= 0x80) { |
| + intptr_t num_trail_bytes = kTrailBytes[ch]; |
| + bool is_malformed = false; |
| + for (; i < num_trail_bytes; ++i) { |
| + if (i < array_len) { |
| + uint8_t code_unit = utf8_array[i]; |
| + is_malformed |= !IsTrailByte(code_unit); |
| + ch = (ch << 6) + code_unit; |
| + } else { |
| + *dst = -1; |
| + return 0; |
| + } |
| + } |
| + ch -= kMagicBits[num_trail_bytes]; |
| + if (!((is_malformed == false) && |
| + (i == num_trail_bytes) && |
| + !IsOutOfRange(ch) && |
| + !IsNonShortestForm(ch, i) && |
| + !IsSurrogate(ch))) { |
| + *dst = -1; |
| + return 0; |
| + } |
| + } |
| + *dst = ch; |
| + return i; |
| +} |
| + |
| + |
| } // namespace dart |