Chromium Code Reviews| Index: src/runtime.cc |
| diff --git a/src/runtime.cc b/src/runtime.cc |
| index c43a1ab327c5e4952f454b2bb5d20f070e1fcb30..2e82c558c172c2d3b5fba8266e5d1b7912582b5c 100644 |
| --- a/src/runtime.cc |
| +++ b/src/runtime.cc |
| @@ -4524,6 +4524,163 @@ static MaybeObject* Runtime_URIUnescape(Arguments args) { |
| } |
| +static const char* const JsonQuotes[128] = { |
| + "\\u0000", "\\u0001", "\\u0002", "\\u0003", |
| + "\\u0004", "\\u0005", "\\u0006", "\\u0007", |
| + "\\b", "\\t", "\\n", "\\u000b", |
| + "\\f", "\\r", "\\u000e", "\\u000f", |
| + "\\u0010", "\\u0011", "\\u0012", "\\u0013", |
| + "\\u0014", "\\u0015", "\\u0016", "\\u0017", |
| + "\\u0018", "\\u0019", "\\u001a", "\\u001b", |
| + "\\u001c", "\\u001d", "\\u001e", "\\u001f", |
| + NULL, NULL, "\\\"", NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + "\\\\", NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| + NULL, NULL, NULL, NULL, |
| +}; |
| + |
| + |
| +static const byte JsonQuoteLengths[128] = { |
| + 6, 6, 6, 6, 6, 6, 6, 6, |
| + 2, 2, 2, 6, 2, 2, 6, 6, |
| + 6, 6, 6, 6, 6, 6, 6, 6, |
| + 6, 6, 6, 6, 6, 6, 6, 6, |
| + 1, 1, 2, 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, 2, 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, |
| +}; |
| + |
| + |
| +template <typename Char> |
| +Char* WriteString(Char* dst, const char* src_string) { |
| + char c; |
| + for (c = *src_string; c; c = *src_string) { |
| + *dst = c; |
| + dst++; |
| + src_string++; |
| + } |
| + return dst; |
| +} |
| + |
| + |
| +template <typename StringType> |
| +MaybeObject* AllocateRawString(int length); |
| + |
| + |
| +template <> |
| +MaybeObject* AllocateRawString<SeqTwoByteString>(int length) { |
| + return Heap::AllocateRawTwoByteString(length); |
| +} |
| + |
| + |
| +template <> |
| +MaybeObject* AllocateRawString<SeqAsciiString>(int length) { |
| + return Heap::AllocateRawAsciiString(length); |
| +} |
| + |
| + |
| +template <typename Char, typename StringType> |
| +static MaybeObject* QuoteJsonString(String* original, |
| + Vector<const Char> characters) { |
| + int length = characters.length(); |
| + int quoted_length = 0; |
| + for (int i = 0; i < length; i++) { |
| + unsigned int c = characters[i]; |
| + if (sizeof(Char) > 1) { |
|
William Hesse
2010/12/01 09:34:58
1u?
Lasse Reichstein
2010/12/01 10:02:47
Done.
|
| + quoted_length += |
| + (c >= sizeof(JsonQuoteLengths)) ? 1 : JsonQuoteLengths[c]; |
| + } else { |
| + quoted_length += JsonQuoteLengths[c]; |
| + } |
| + } |
| + if (quoted_length == length) { |
| + return original; |
| + } |
| + |
| + MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length); |
| + Object* new_object; |
| + if (!new_alloc->ToObject(&new_object)) { |
| + // TODO(lrn): Better handling of allocation errors. Try harder |
|
William Hesse
2010/12/01 09:34:58
I'm not sure this should be a TODO. It may be bet
Kevin Millikin (Chromium)
2010/12/01 09:44:51
If you leave it as a TODO, please file an issue in
Lasse Reichstein
2010/12/01 10:02:47
I'll remove it, and make a counter to count the ex
|
| + // to allocate (allowing GCs) and the re-extract the characters |
| + // Vector before continuing. |
| + return new_alloc; |
| + } |
| + StringType* new_string = StringType::cast(new_object); |
| + |
| + |
| + STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
| + Char* write_cursor = reinterpret_cast<Char*>( |
| + new_string->address() + SeqAsciiString::kHeaderSize); |
| + const Char* read_cursor = characters.start(); |
| + const Char* end = read_cursor + length; |
| + while (read_cursor < end) { |
| + Char c = *(read_cursor++); |
| + if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= sizeof(JsonQuotes)) { |
| + *(write_cursor++) = c; |
| + } else { |
| + const char* replacement = JsonQuotes[static_cast<unsigned>(c)]; |
| + if (!replacement) { |
| + *(write_cursor++) = c; |
| + } else { |
| + write_cursor = WriteString(write_cursor, replacement); |
| + } |
| + } |
| + } |
| + ASSERT_EQ(SeqAsciiString::kHeaderSize + quoted_length * sizeof(Char), |
| + reinterpret_cast<Address>(write_cursor) - new_string->address()); |
| + return new_string; |
| +} |
| + |
| + |
| +static MaybeObject* Runtime_QuoteJSONString(Arguments args) { |
| + NoHandleAllocation ha; |
| + CONVERT_CHECKED(String, str, args[0]); |
| + if (!str->IsFlat()) { |
| + MaybeObject* try_flatten = str->TryFlatten(); |
| + Object* flat; |
| + if (!try_flatten->ToObject(&flat)) { |
| + return try_flatten; |
| + } |
| + str = String::cast(flat); |
| + ASSERT(str->IsFlat()); |
| + } |
| + if (str->IsTwoByteRepresentation()) { |
| + return QuoteJsonString<uc16, SeqTwoByteString>(str, str->ToUC16Vector()); |
| + } else { |
| + return QuoteJsonString<char, SeqAsciiString>(str, str->ToAsciiVector()); |
| + } |
| +} |
| + |
| + |
| static MaybeObject* Runtime_StringParseInt(Arguments args) { |
| NoHandleAllocation ha; |