| 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;
|
| +
|
| +
|
| +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
|
|
|