OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_JSON_STRINGIFIER_H_ | 5 #include "src/json-stringifier.h" |
6 #define V8_JSON_STRINGIFIER_H_ | |
7 | 6 |
8 #include "src/conversions.h" | 7 #include "src/conversions.h" |
9 #include "src/lookup.h" | 8 #include "src/lookup.h" |
10 #include "src/messages.h" | 9 #include "src/messages.h" |
11 #include "src/string-builder.h" | 10 #include "src/objects-inl.h" |
12 #include "src/utils.h" | 11 #include "src/utils.h" |
13 | 12 |
14 namespace v8 { | 13 namespace v8 { |
15 namespace internal { | 14 namespace internal { |
16 | 15 |
17 class BasicJsonStringifier BASE_EMBEDDED { | |
18 public: | |
19 BasicJsonStringifier(Isolate* isolate, Handle<String> gap); | |
20 | |
21 ~BasicJsonStringifier() { DeleteArray(gap_); } | |
22 | |
23 MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object); | |
24 | |
25 MUST_USE_RESULT INLINE(static MaybeHandle<Object> StringifyString( | |
26 Isolate* isolate, | |
27 Handle<String> object)); | |
28 | |
29 private: | |
30 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; | |
31 | |
32 MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction( | |
33 Handle<Object> object, | |
34 Handle<Object> key); | |
35 | |
36 // Entry point to serialize the object. | |
37 INLINE(Result SerializeObject(Handle<Object> obj)) { | |
38 return Serialize_<false>(obj, false, factory()->empty_string()); | |
39 } | |
40 | |
41 // Serialize an array element. | |
42 // The index may serve as argument for the toJSON function. | |
43 INLINE(Result SerializeElement(Isolate* isolate, | |
44 Handle<Object> object, | |
45 int i)) { | |
46 return Serialize_<false>(object, | |
47 false, | |
48 Handle<Object>(Smi::FromInt(i), isolate)); | |
49 } | |
50 | |
51 // Serialize a object property. | |
52 // The key may or may not be serialized depending on the property. | |
53 // The key may also serve as argument for the toJSON function. | |
54 INLINE(Result SerializeProperty(Handle<Object> object, | |
55 bool deferred_comma, | |
56 Handle<String> deferred_key)) { | |
57 DCHECK(!deferred_key.is_null()); | |
58 return Serialize_<true>(object, deferred_comma, deferred_key); | |
59 } | |
60 | |
61 template <bool deferred_string_key> | |
62 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); | |
63 | |
64 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { | |
65 Separator(!deferred_comma); | |
66 SerializeString(Handle<String>::cast(deferred_key)); | |
67 builder_.AppendCharacter(':'); | |
68 if (gap_ != nullptr) builder_.AppendCharacter(' '); | |
69 } | |
70 | |
71 Result SerializeSmi(Smi* object); | |
72 | |
73 Result SerializeDouble(double number); | |
74 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { | |
75 return SerializeDouble(object->value()); | |
76 } | |
77 | |
78 Result SerializeJSValue(Handle<JSValue> object); | |
79 | |
80 INLINE(Result SerializeJSArray(Handle<JSArray> object)); | |
81 INLINE(Result SerializeJSObject(Handle<JSObject> object)); | |
82 | |
83 Result SerializeJSProxy(Handle<JSProxy> object); | |
84 Result SerializeJSReceiverSlow(Handle<JSReceiver> object); | |
85 Result SerializeArrayLikeSlow(Handle<JSReceiver> object, uint32_t start, | |
86 uint32_t length); | |
87 | |
88 void SerializeString(Handle<String> object); | |
89 | |
90 template <typename SrcChar, typename DestChar> | |
91 INLINE(static void SerializeStringUnchecked_( | |
92 Vector<const SrcChar> src, | |
93 IncrementalStringBuilder::NoExtend<DestChar>* dest)); | |
94 | |
95 template <typename SrcChar, typename DestChar> | |
96 INLINE(void SerializeString_(Handle<String> string)); | |
97 | |
98 template <typename Char> | |
99 INLINE(static bool DoNotEscape(Char c)); | |
100 | |
101 INLINE(void NewLine()); | |
102 INLINE(void Indent() { indent_++; }); | |
103 INLINE(void Unindent() { indent_--; }); | |
104 INLINE(void Separator(bool first) { | |
105 if (!first) builder_.AppendCharacter(','); | |
106 NewLine(); | |
107 }) | |
108 | |
109 Result StackPush(Handle<Object> object); | |
110 void StackPop(); | |
111 | |
112 Factory* factory() { return isolate_->factory(); } | |
113 | |
114 Isolate* isolate_; | |
115 IncrementalStringBuilder builder_; | |
116 Handle<String> tojson_string_; | |
117 Handle<JSArray> stack_; | |
118 Handle<String> gap_string_; | |
119 uc16* gap_; | |
120 int indent_; | |
121 | |
122 static const int kJsonEscapeTableEntrySize = 8; | |
123 static const char* const JsonEscapeTable; | |
124 }; | |
125 | |
126 | |
127 // Translation table to escape Latin1 characters. | 16 // Translation table to escape Latin1 characters. |
128 // Table entries start at a multiple of 8 and are null-terminated. | 17 // Table entries start at a multiple of 8 and are null-terminated. |
129 const char* const BasicJsonStringifier::JsonEscapeTable = | 18 const char* const BasicJsonStringifier::JsonEscapeTable = |
130 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " | 19 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " |
131 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " | 20 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " |
132 "\\b\0 \\t\0 \\n\0 \\u000b\0 " | 21 "\\b\0 \\t\0 \\n\0 \\u000b\0 " |
133 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " | 22 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " |
134 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " | 23 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " |
135 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " | 24 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " |
136 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " | 25 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 CopyChars(gap_, flat.ToOneByteVector().start(), gap_length); | 96 CopyChars(gap_, flat.ToOneByteVector().start(), gap_length); |
208 } else { | 97 } else { |
209 CopyChars(gap_, flat.ToUC16Vector().start(), gap_length); | 98 CopyChars(gap_, flat.ToUC16Vector().start(), gap_length); |
210 } | 99 } |
211 gap_[gap_length] = '\0'; | 100 gap_[gap_length] = '\0'; |
212 } else { | 101 } else { |
213 gap_ = nullptr; | 102 gap_ = nullptr; |
214 } | 103 } |
215 } | 104 } |
216 | 105 |
217 | |
218 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { | 106 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { |
219 Result result = SerializeObject(object); | 107 Result result = SerializeObject(object); |
220 if (result == UNCHANGED) return factory()->undefined_value(); | 108 if (result == UNCHANGED) return factory()->undefined_value(); |
221 if (result == SUCCESS) return builder_.Finish(); | 109 if (result == SUCCESS) return builder_.Finish(); |
222 DCHECK(result == EXCEPTION); | 110 DCHECK(result == EXCEPTION); |
223 return MaybeHandle<Object>(); | 111 return MaybeHandle<Object>(); |
224 } | 112 } |
225 | 113 |
226 | |
227 MaybeHandle<Object> BasicJsonStringifier::StringifyString( | 114 MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
228 Isolate* isolate, Handle<String> object) { | 115 Isolate* isolate, Handle<String> object) { |
229 static const int kJsonQuoteWorstCaseBlowup = 6; | 116 static const int kJsonQuoteWorstCaseBlowup = 6; |
230 static const int kSpaceForQuotes = 2; | 117 static const int kSpaceForQuotes = 2; |
231 int worst_case_length = | 118 int worst_case_length = |
232 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 119 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
233 | 120 |
234 if (worst_case_length > 32 * KB) { // Slow path if too large. | 121 if (worst_case_length > 32 * KB) { // Slow path if too large. |
235 BasicJsonStringifier stringifier(isolate, | 122 BasicJsonStringifier stringifier(isolate, |
236 isolate->factory()->empty_string()); | 123 isolate->factory()->empty_string()); |
237 return stringifier.Stringify(object); | 124 return stringifier.Stringify(object); |
238 } | 125 } |
(...skipping 19 matching lines...) Expand all Loading... |
258 IncrementalStringBuilder::NoExtendString<uc16> no_extend(result, | 145 IncrementalStringBuilder::NoExtendString<uc16> no_extend(result, |
259 worst_case_length); | 146 worst_case_length); |
260 no_extend.Append('\"'); | 147 no_extend.Append('\"'); |
261 SerializeStringUnchecked_(object->GetFlatContent().ToUC16Vector(), | 148 SerializeStringUnchecked_(object->GetFlatContent().ToUC16Vector(), |
262 &no_extend); | 149 &no_extend); |
263 no_extend.Append('\"'); | 150 no_extend.Append('\"'); |
264 return no_extend.Finalize(); | 151 return no_extend.Finalize(); |
265 } | 152 } |
266 } | 153 } |
267 | 154 |
268 | |
269 MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction( | 155 MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction( |
270 Handle<Object> object, Handle<Object> key) { | 156 Handle<Object> object, Handle<Object> key) { |
271 LookupIterator it(object, tojson_string_, | 157 LookupIterator it(object, tojson_string_, |
272 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); | 158 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); |
273 Handle<Object> fun; | 159 Handle<Object> fun; |
274 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); | 160 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); |
275 if (!fun->IsCallable()) return object; | 161 if (!fun->IsCallable()) return object; |
276 | 162 |
277 // Call toJSON function. | 163 // Call toJSON function. |
278 if (key->IsSmi()) key = factory()->NumberToString(key); | 164 if (key->IsSmi()) key = factory()->NumberToString(key); |
279 Handle<Object> argv[] = { key }; | 165 Handle<Object> argv[] = {key}; |
280 HandleScope scope(isolate_); | 166 HandleScope scope(isolate_); |
281 ASSIGN_RETURN_ON_EXCEPTION( | 167 ASSIGN_RETURN_ON_EXCEPTION(isolate_, object, |
282 isolate_, object, | 168 Execution::Call(isolate_, fun, object, 1, argv), |
283 Execution::Call(isolate_, fun, object, 1, argv), | 169 Object); |
284 Object); | |
285 return scope.CloseAndEscape(object); | 170 return scope.CloseAndEscape(object); |
286 } | 171 } |
287 | 172 |
288 | |
289 BasicJsonStringifier::Result BasicJsonStringifier::StackPush( | 173 BasicJsonStringifier::Result BasicJsonStringifier::StackPush( |
290 Handle<Object> object) { | 174 Handle<Object> object) { |
291 StackLimitCheck check(isolate_); | 175 StackLimitCheck check(isolate_); |
292 if (check.HasOverflowed()) { | 176 if (check.HasOverflowed()) { |
293 isolate_->StackOverflow(); | 177 isolate_->StackOverflow(); |
294 return EXCEPTION; | 178 return EXCEPTION; |
295 } | 179 } |
296 | 180 |
297 int length = Smi::cast(stack_->length())->value(); | 181 int length = Smi::cast(stack_->length())->value(); |
298 { | 182 { |
299 DisallowHeapAllocation no_allocation; | 183 DisallowHeapAllocation no_allocation; |
300 FixedArray* elements = FixedArray::cast(stack_->elements()); | 184 FixedArray* elements = FixedArray::cast(stack_->elements()); |
301 for (int i = 0; i < length; i++) { | 185 for (int i = 0; i < length; i++) { |
302 if (elements->get(i) == *object) { | 186 if (elements->get(i) == *object) { |
303 AllowHeapAllocation allow_to_return_error; | 187 AllowHeapAllocation allow_to_return_error; |
304 Handle<Object> error = | 188 Handle<Object> error = |
305 factory()->NewTypeError(MessageTemplate::kCircularStructure); | 189 factory()->NewTypeError(MessageTemplate::kCircularStructure); |
306 isolate_->Throw(*error); | 190 isolate_->Throw(*error); |
307 return EXCEPTION; | 191 return EXCEPTION; |
308 } | 192 } |
309 } | 193 } |
310 } | 194 } |
311 JSArray::SetLength(stack_, length + 1); | 195 JSArray::SetLength(stack_, length + 1); |
312 FixedArray::cast(stack_->elements())->set(length, *object); | 196 FixedArray::cast(stack_->elements())->set(length, *object); |
313 return SUCCESS; | 197 return SUCCESS; |
314 } | 198 } |
315 | 199 |
316 | |
317 void BasicJsonStringifier::StackPop() { | 200 void BasicJsonStringifier::StackPop() { |
318 int length = Smi::cast(stack_->length())->value(); | 201 int length = Smi::cast(stack_->length())->value(); |
319 stack_->set_length(Smi::FromInt(length - 1)); | 202 stack_->set_length(Smi::FromInt(length - 1)); |
320 } | 203 } |
321 | 204 |
322 | |
323 template <bool deferred_string_key> | 205 template <bool deferred_string_key> |
324 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_( | 206 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_( |
325 Handle<Object> object, bool comma, Handle<Object> key) { | 207 Handle<Object> object, bool comma, Handle<Object> key) { |
326 if (object->IsJSReceiver()) { | 208 if (object->IsJSReceiver()) { |
327 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 209 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
328 isolate_, object, | 210 isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION); |
329 ApplyToJsonFunction(object, key), | |
330 EXCEPTION); | |
331 } | 211 } |
332 | 212 |
333 if (object->IsSmi()) { | 213 if (object->IsSmi()) { |
334 if (deferred_string_key) SerializeDeferredKey(comma, key); | 214 if (deferred_string_key) SerializeDeferredKey(comma, key); |
335 return SerializeSmi(Smi::cast(*object)); | 215 return SerializeSmi(Smi::cast(*object)); |
336 } | 216 } |
337 | 217 |
338 switch (HeapObject::cast(*object)->map()->instance_type()) { | 218 switch (HeapObject::cast(*object)->map()->instance_type()) { |
339 case HEAP_NUMBER_TYPE: | 219 case HEAP_NUMBER_TYPE: |
340 case MUTABLE_HEAP_NUMBER_TYPE: | 220 case MUTABLE_HEAP_NUMBER_TYPE: |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 return SerializeJSProxy(Handle<JSProxy>::cast(object)); | 260 return SerializeJSProxy(Handle<JSProxy>::cast(object)); |
381 } | 261 } |
382 return SerializeJSObject(Handle<JSObject>::cast(object)); | 262 return SerializeJSObject(Handle<JSObject>::cast(object)); |
383 } | 263 } |
384 } | 264 } |
385 | 265 |
386 UNREACHABLE(); | 266 UNREACHABLE(); |
387 return UNCHANGED; | 267 return UNCHANGED; |
388 } | 268 } |
389 | 269 |
390 | |
391 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( | 270 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( |
392 Handle<JSValue> object) { | 271 Handle<JSValue> object) { |
393 String* class_name = object->class_name(); | 272 String* class_name = object->class_name(); |
394 if (class_name == isolate_->heap()->String_string()) { | 273 if (class_name == isolate_->heap()->String_string()) { |
395 Handle<Object> value; | 274 Handle<Object> value; |
396 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 275 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
397 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); | 276 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); |
398 SerializeString(Handle<String>::cast(value)); | 277 SerializeString(Handle<String>::cast(value)); |
399 } else if (class_name == isolate_->heap()->Number_string()) { | 278 } else if (class_name == isolate_->heap()->Number_string()) { |
400 Handle<Object> value; | 279 Handle<Object> value; |
401 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), | 280 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), |
402 EXCEPTION); | 281 EXCEPTION); |
403 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); | 282 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); |
404 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); | 283 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); |
405 } else if (class_name == isolate_->heap()->Boolean_string()) { | 284 } else if (class_name == isolate_->heap()->Boolean_string()) { |
406 Object* value = JSValue::cast(*object)->value(); | 285 Object* value = JSValue::cast(*object)->value(); |
407 DCHECK(value->IsBoolean()); | 286 DCHECK(value->IsBoolean()); |
408 builder_.AppendCString(value->IsTrue() ? "true" : "false"); | 287 builder_.AppendCString(value->IsTrue() ? "true" : "false"); |
409 } else { | 288 } else { |
410 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. | 289 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. |
411 return SerializeJSObject(object); | 290 return SerializeJSObject(object); |
412 } | 291 } |
413 return SUCCESS; | 292 return SUCCESS; |
414 } | 293 } |
415 | 294 |
416 | |
417 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { | 295 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { |
418 static const int kBufferSize = 100; | 296 static const int kBufferSize = 100; |
419 char chars[kBufferSize]; | 297 char chars[kBufferSize]; |
420 Vector<char> buffer(chars, kBufferSize); | 298 Vector<char> buffer(chars, kBufferSize); |
421 builder_.AppendCString(IntToCString(object->value(), buffer)); | 299 builder_.AppendCString(IntToCString(object->value(), buffer)); |
422 return SUCCESS; | 300 return SUCCESS; |
423 } | 301 } |
424 | 302 |
425 | |
426 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( | 303 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( |
427 double number) { | 304 double number) { |
428 if (std::isinf(number) || std::isnan(number)) { | 305 if (std::isinf(number) || std::isnan(number)) { |
429 builder_.AppendCString("null"); | 306 builder_.AppendCString("null"); |
430 return SUCCESS; | 307 return SUCCESS; |
431 } | 308 } |
432 static const int kBufferSize = 100; | 309 static const int kBufferSize = 100; |
433 char chars[kBufferSize]; | 310 char chars[kBufferSize]; |
434 Vector<char> buffer(chars, kBufferSize); | 311 Vector<char> buffer(chars, kBufferSize); |
435 builder_.AppendCString(DoubleToCString(number, buffer)); | 312 builder_.AppendCString(DoubleToCString(number, buffer)); |
436 return SUCCESS; | 313 return SUCCESS; |
437 } | 314 } |
438 | 315 |
439 | |
440 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( | 316 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
441 Handle<JSArray> object) { | 317 Handle<JSArray> object) { |
442 HandleScope handle_scope(isolate_); | 318 HandleScope handle_scope(isolate_); |
443 Result stack_push = StackPush(object); | 319 Result stack_push = StackPush(object); |
444 if (stack_push != SUCCESS) return stack_push; | 320 if (stack_push != SUCCESS) return stack_push; |
445 uint32_t length = 0; | 321 uint32_t length = 0; |
446 CHECK(object->length()->ToArrayLength(&length)); | 322 CHECK(object->length()->ToArrayLength(&length)); |
447 DCHECK(!object->IsAccessCheckNeeded()); | 323 DCHECK(!object->IsAccessCheckNeeded()); |
448 builder_.AppendCharacter('['); | 324 builder_.AppendCharacter('['); |
449 Indent(); | 325 Indent(); |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 if (length > 0) NewLine(); | 527 if (length > 0) NewLine(); |
652 builder_.AppendCharacter(']'); | 528 builder_.AppendCharacter(']'); |
653 } else { | 529 } else { |
654 Result result = SerializeJSReceiverSlow(object); | 530 Result result = SerializeJSReceiverSlow(object); |
655 if (result != SUCCESS) return result; | 531 if (result != SUCCESS) return result; |
656 } | 532 } |
657 StackPop(); | 533 StackPop(); |
658 return SUCCESS; | 534 return SUCCESS; |
659 } | 535 } |
660 | 536 |
661 | |
662 template <typename SrcChar, typename DestChar> | 537 template <typename SrcChar, typename DestChar> |
663 void BasicJsonStringifier::SerializeStringUnchecked_( | 538 void BasicJsonStringifier::SerializeStringUnchecked_( |
664 Vector<const SrcChar> src, | 539 Vector<const SrcChar> src, |
665 IncrementalStringBuilder::NoExtend<DestChar>* dest) { | 540 IncrementalStringBuilder::NoExtend<DestChar>* dest) { |
666 // Assert that uc16 character is not truncated down to 8 bit. | 541 // Assert that uc16 character is not truncated down to 8 bit. |
667 // The <uc16, char> version of this method must not be called. | 542 // The <uc16, char> version of this method must not be called. |
668 DCHECK(sizeof(DestChar) >= sizeof(SrcChar)); | 543 DCHECK(sizeof(DestChar) >= sizeof(SrcChar)); |
669 | 544 |
670 for (int i = 0; i < src.length(); i++) { | 545 for (int i = 0; i < src.length(); i++) { |
671 SrcChar c = src[i]; | 546 SrcChar c = src[i]; |
672 if (DoNotEscape(c)) { | 547 if (DoNotEscape(c)) { |
673 dest->Append(c); | 548 dest->Append(c); |
674 } else { | 549 } else { |
675 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 550 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
676 } | 551 } |
677 } | 552 } |
678 } | 553 } |
679 | 554 |
680 | |
681 template <typename SrcChar, typename DestChar> | 555 template <typename SrcChar, typename DestChar> |
682 void BasicJsonStringifier::SerializeString_(Handle<String> string) { | 556 void BasicJsonStringifier::SerializeString_(Handle<String> string) { |
683 int length = string->length(); | 557 int length = string->length(); |
684 builder_.Append<uint8_t, DestChar>('"'); | 558 builder_.Append<uint8_t, DestChar>('"'); |
685 // We make a rough estimate to find out if the current string can be | 559 // We make a rough estimate to find out if the current string can be |
686 // serialized without allocating a new string part. The worst case length of | 560 // serialized without allocating a new string part. The worst case length of |
687 // an escaped character is 6. Shifting the remainin string length right by 3 | 561 // an escaped character is 6. Shifting the remainin string length right by 3 |
688 // is a more pessimistic estimate, but faster to calculate. | 562 // is a more pessimistic estimate, but faster to calculate. |
689 int worst_case_length = length << 3; | 563 int worst_case_length = length << 3; |
690 if (builder_.CurrentPartCanFit(worst_case_length)) { | 564 if (builder_.CurrentPartCanFit(worst_case_length)) { |
(...skipping 10 matching lines...) Expand all Loading... |
701 builder_.Append<SrcChar, DestChar>(c); | 575 builder_.Append<SrcChar, DestChar>(c); |
702 } else { | 576 } else { |
703 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 577 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
704 } | 578 } |
705 } | 579 } |
706 } | 580 } |
707 | 581 |
708 builder_.Append<uint8_t, DestChar>('"'); | 582 builder_.Append<uint8_t, DestChar>('"'); |
709 } | 583 } |
710 | 584 |
711 | |
712 template <> | 585 template <> |
713 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { | 586 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { |
714 return c >= '#' && c <= '~' && c != '\\'; | 587 return c >= '#' && c <= '~' && c != '\\'; |
715 } | 588 } |
716 | 589 |
717 | |
718 template <> | 590 template <> |
719 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { | 591 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { |
720 return c >= '#' && c != '\\' && c != 0x7f; | 592 return c >= '#' && c != '\\' && c != 0x7f; |
721 } | 593 } |
722 | 594 |
723 void BasicJsonStringifier::NewLine() { | 595 void BasicJsonStringifier::NewLine() { |
724 if (gap_ == nullptr) return; | 596 if (gap_ == nullptr) return; |
725 builder_.AppendCharacter('\n'); | 597 builder_.AppendCharacter('\n'); |
726 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); | 598 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); |
727 } | 599 } |
728 | 600 |
| 601 void BasicJsonStringifier::Separator(bool first) { |
| 602 if (!first) builder_.AppendCharacter(','); |
| 603 NewLine(); |
| 604 } |
| 605 |
| 606 void BasicJsonStringifier::SerializeDeferredKey(bool deferred_comma, |
| 607 Handle<Object> deferred_key) { |
| 608 Separator(!deferred_comma); |
| 609 SerializeString(Handle<String>::cast(deferred_key)); |
| 610 builder_.AppendCharacter(':'); |
| 611 if (gap_ != nullptr) builder_.AppendCharacter(' '); |
| 612 } |
| 613 |
729 void BasicJsonStringifier::SerializeString(Handle<String> object) { | 614 void BasicJsonStringifier::SerializeString(Handle<String> object) { |
730 object = String::Flatten(object); | 615 object = String::Flatten(object); |
731 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { | 616 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { |
732 if (object->IsOneByteRepresentationUnderneath()) { | 617 if (object->IsOneByteRepresentationUnderneath()) { |
733 SerializeString_<uint8_t, uint8_t>(object); | 618 SerializeString_<uint8_t, uint8_t>(object); |
734 } else { | 619 } else { |
735 builder_.ChangeEncoding(); | 620 builder_.ChangeEncoding(); |
736 SerializeString(object); | 621 SerializeString(object); |
737 } | 622 } |
738 } else { | 623 } else { |
739 if (object->IsOneByteRepresentationUnderneath()) { | 624 if (object->IsOneByteRepresentationUnderneath()) { |
740 SerializeString_<uint8_t, uc16>(object); | 625 SerializeString_<uint8_t, uc16>(object); |
741 } else { | 626 } else { |
742 SerializeString_<uc16, uc16>(object); | 627 SerializeString_<uc16, uc16>(object); |
743 } | 628 } |
744 } | 629 } |
745 } | 630 } |
746 | 631 |
747 } // namespace internal | 632 } // namespace internal |
748 } // namespace v8 | 633 } // namespace v8 |
749 | |
750 #endif // V8_JSON_STRINGIFIER_H_ | |
OLD | NEW |