OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #ifndef V8_JSON_STRINGIFIER_H_ |
6 #define V8_JSON_STRINGIFIER_H_ | 6 #define V8_JSON_STRINGIFIER_H_ |
7 | 7 |
8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
9 #include "src/lookup.h" | 9 #include "src/lookup.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
11 #include "src/string-builder.h" | 11 #include "src/string-builder.h" |
12 #include "src/utils.h" | 12 #include "src/utils.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 class BasicJsonStringifier BASE_EMBEDDED { | 17 class BasicJsonStringifier BASE_EMBEDDED { |
18 public: | 18 public: |
19 explicit BasicJsonStringifier(Isolate* isolate); | 19 BasicJsonStringifier(Isolate* isolate, Handle<String> gap); |
| 20 |
| 21 ~BasicJsonStringifier() { DeleteArray(gap_); } |
20 | 22 |
21 MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object); | 23 MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object); |
22 | 24 |
23 MUST_USE_RESULT INLINE(static MaybeHandle<Object> StringifyString( | 25 MUST_USE_RESULT INLINE(static MaybeHandle<Object> StringifyString( |
24 Isolate* isolate, | 26 Isolate* isolate, |
25 Handle<String> object)); | 27 Handle<String> object)); |
26 | 28 |
27 private: | 29 private: |
28 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; | 30 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; |
29 | 31 |
(...skipping 28 matching lines...) Expand all Loading... |
58 bool deferred_comma, | 60 bool deferred_comma, |
59 Handle<String> deferred_key)) { | 61 Handle<String> deferred_key)) { |
60 DCHECK(!deferred_key.is_null()); | 62 DCHECK(!deferred_key.is_null()); |
61 return Serialize_<true>(object, deferred_comma, deferred_key); | 63 return Serialize_<true>(object, deferred_comma, deferred_key); |
62 } | 64 } |
63 | 65 |
64 template <bool deferred_string_key> | 66 template <bool deferred_string_key> |
65 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); | 67 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); |
66 | 68 |
67 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { | 69 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { |
68 if (deferred_comma) builder_.AppendCharacter(','); | 70 Separator(!deferred_comma); |
69 SerializeString(Handle<String>::cast(deferred_key)); | 71 SerializeString(Handle<String>::cast(deferred_key)); |
70 builder_.AppendCharacter(':'); | 72 builder_.AppendCharacter(':'); |
| 73 if (gap_ != nullptr) builder_.AppendCharacter(' '); |
71 } | 74 } |
72 | 75 |
73 Result SerializeSmi(Smi* object); | 76 Result SerializeSmi(Smi* object); |
74 | 77 |
75 Result SerializeDouble(double number); | 78 Result SerializeDouble(double number); |
76 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { | 79 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { |
77 return SerializeDouble(object->value()); | 80 return SerializeDouble(object->value()); |
78 } | 81 } |
79 | 82 |
80 Result SerializeJSValue(Handle<JSValue> object); | 83 Result SerializeJSValue(Handle<JSValue> object); |
(...skipping 10 matching lines...) Expand all Loading... |
91 INLINE(static void SerializeStringUnchecked_( | 94 INLINE(static void SerializeStringUnchecked_( |
92 Vector<const SrcChar> src, | 95 Vector<const SrcChar> src, |
93 IncrementalStringBuilder::NoExtend<DestChar>* dest)); | 96 IncrementalStringBuilder::NoExtend<DestChar>* dest)); |
94 | 97 |
95 template <typename SrcChar, typename DestChar> | 98 template <typename SrcChar, typename DestChar> |
96 INLINE(void SerializeString_(Handle<String> string)); | 99 INLINE(void SerializeString_(Handle<String> string)); |
97 | 100 |
98 template <typename Char> | 101 template <typename Char> |
99 INLINE(static bool DoNotEscape(Char c)); | 102 INLINE(static bool DoNotEscape(Char c)); |
100 | 103 |
| 104 INLINE(void NewLine()); |
| 105 INLINE(void Indent() { indent_++; }); |
| 106 INLINE(void Unindent() { indent_--; }); |
| 107 INLINE(void Separator(bool first) { |
| 108 if (!first) builder_.AppendCharacter(','); |
| 109 NewLine(); |
| 110 }) |
| 111 |
101 Result StackPush(Handle<Object> object); | 112 Result StackPush(Handle<Object> object); |
102 void StackPop(); | 113 void StackPop(); |
103 | 114 |
104 Factory* factory() { return isolate_->factory(); } | 115 Factory* factory() { return isolate_->factory(); } |
105 | 116 |
106 Isolate* isolate_; | 117 Isolate* isolate_; |
107 IncrementalStringBuilder builder_; | 118 IncrementalStringBuilder builder_; |
108 Handle<String> tojson_string_; | 119 Handle<String> tojson_string_; |
109 Handle<JSArray> stack_; | 120 Handle<JSArray> stack_; |
| 121 Handle<String> gap_string_; |
| 122 uc16* gap_; |
| 123 int indent_; |
110 | 124 |
111 static const int kJsonEscapeTableEntrySize = 8; | 125 static const int kJsonEscapeTableEntrySize = 8; |
112 static const char* const JsonEscapeTable; | 126 static const char* const JsonEscapeTable; |
113 }; | 127 }; |
114 | 128 |
115 | 129 |
116 // Translation table to escape Latin1 characters. | 130 // Translation table to escape Latin1 characters. |
117 // Table entries start at a multiple of 8 and are null-terminated. | 131 // Table entries start at a multiple of 8 and are null-terminated. |
118 const char* const BasicJsonStringifier::JsonEscapeTable = | 132 const char* const BasicJsonStringifier::JsonEscapeTable = |
119 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " | 133 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 "\334\0 \335\0 \336\0 \337\0 " | 188 "\334\0 \335\0 \336\0 \337\0 " |
175 "\340\0 \341\0 \342\0 \343\0 " | 189 "\340\0 \341\0 \342\0 \343\0 " |
176 "\344\0 \345\0 \346\0 \347\0 " | 190 "\344\0 \345\0 \346\0 \347\0 " |
177 "\350\0 \351\0 \352\0 \353\0 " | 191 "\350\0 \351\0 \352\0 \353\0 " |
178 "\354\0 \355\0 \356\0 \357\0 " | 192 "\354\0 \355\0 \356\0 \357\0 " |
179 "\360\0 \361\0 \362\0 \363\0 " | 193 "\360\0 \361\0 \362\0 \363\0 " |
180 "\364\0 \365\0 \366\0 \367\0 " | 194 "\364\0 \365\0 \366\0 \367\0 " |
181 "\370\0 \371\0 \372\0 \373\0 " | 195 "\370\0 \371\0 \372\0 \373\0 " |
182 "\374\0 \375\0 \376\0 \377\0 "; | 196 "\374\0 \375\0 \376\0 \377\0 "; |
183 | 197 |
184 | 198 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate, Handle<String> gap) |
185 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) | 199 : isolate_(isolate), builder_(isolate), gap_string_(gap), indent_(0) { |
186 : isolate_(isolate), builder_(isolate) { | |
187 tojson_string_ = factory()->toJSON_string(); | 200 tojson_string_ = factory()->toJSON_string(); |
188 stack_ = factory()->NewJSArray(8); | 201 stack_ = factory()->NewJSArray(8); |
| 202 int gap_length = gap->length(); |
| 203 if (gap_length != 0) { |
| 204 String::Flatten(gap); |
| 205 DisallowHeapAllocation no_gc; |
| 206 String::FlatContent flat = gap->GetFlatContent(); |
| 207 gap_ = NewArray<uc16>(gap_length + 1); |
| 208 if (flat.IsOneByte()) { |
| 209 CopyChars(gap_, flat.ToOneByteVector().start(), gap_length); |
| 210 } else { |
| 211 CopyChars(gap_, flat.ToUC16Vector().start(), gap_length); |
| 212 builder_.ChangeEncoding(); |
| 213 } |
| 214 gap_[gap_length] = '\0'; |
| 215 } else { |
| 216 gap_ = nullptr; |
| 217 } |
189 } | 218 } |
190 | 219 |
191 | 220 |
192 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { | 221 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { |
193 Result result = SerializeObject(object); | 222 Result result = SerializeObject(object); |
194 if (result == UNCHANGED) return factory()->undefined_value(); | 223 if (result == UNCHANGED) return factory()->undefined_value(); |
195 if (result == SUCCESS) return builder_.Finish(); | 224 if (result == SUCCESS) return builder_.Finish(); |
196 DCHECK(result == EXCEPTION); | 225 DCHECK(result == EXCEPTION); |
197 return MaybeHandle<Object>(); | 226 return MaybeHandle<Object>(); |
198 } | 227 } |
199 | 228 |
200 | 229 |
201 MaybeHandle<Object> BasicJsonStringifier::StringifyString( | 230 MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
202 Isolate* isolate, Handle<String> object) { | 231 Isolate* isolate, Handle<String> object) { |
203 static const int kJsonQuoteWorstCaseBlowup = 6; | 232 static const int kJsonQuoteWorstCaseBlowup = 6; |
204 static const int kSpaceForQuotes = 2; | 233 static const int kSpaceForQuotes = 2; |
205 int worst_case_length = | 234 int worst_case_length = |
206 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 235 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
207 | 236 |
208 if (worst_case_length > 32 * KB) { // Slow path if too large. | 237 if (worst_case_length > 32 * KB) { // Slow path if too large. |
209 BasicJsonStringifier stringifier(isolate); | 238 BasicJsonStringifier stringifier(isolate, |
| 239 isolate->factory()->empty_string()); |
210 return stringifier.Stringify(object); | 240 return stringifier.Stringify(object); |
211 } | 241 } |
212 | 242 |
213 object = String::Flatten(object); | 243 object = String::Flatten(object); |
214 DCHECK(object->IsFlat()); | 244 DCHECK(object->IsFlat()); |
215 Handle<SeqString> result; | 245 Handle<SeqString> result; |
216 if (object->IsOneByteRepresentationUnderneath()) { | 246 if (object->IsOneByteRepresentationUnderneath()) { |
217 result = isolate->factory() | 247 result = isolate->factory() |
218 ->NewRawOneByteString(worst_case_length) | 248 ->NewRawOneByteString(worst_case_length) |
219 .ToHandleChecked(); | 249 .ToHandleChecked(); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 return SerializeGeneric(object, key, comma, deferred_string_key); | 384 return SerializeGeneric(object, key, comma, deferred_string_key); |
355 } | 385 } |
356 | 386 |
357 | 387 |
358 BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric( | 388 BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric( |
359 Handle<Object> object, | 389 Handle<Object> object, |
360 Handle<Object> key, | 390 Handle<Object> key, |
361 bool deferred_comma, | 391 bool deferred_comma, |
362 bool deferred_key) { | 392 bool deferred_key) { |
363 Handle<JSFunction> fun = isolate_->json_serialize_adapter(); | 393 Handle<JSFunction> fun = isolate_->json_serialize_adapter(); |
364 Handle<Object> argv[] = { key, object }; | 394 Handle<Object> indent(Smi::FromInt(indent_), isolate_); |
| 395 Handle<Object> argv[] = {key, object, indent, gap_string_}; |
365 Handle<Object> result; | 396 Handle<Object> result; |
366 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 397 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
367 isolate_, result, Execution::Call(isolate_, fun, object, 2, argv), | 398 isolate_, result, |
368 EXCEPTION); | 399 Execution::Call(isolate_, fun, object, arraysize(argv), argv), EXCEPTION); |
369 if (result->IsUndefined()) return UNCHANGED; | 400 if (result->IsUndefined()) return UNCHANGED; |
370 if (deferred_key) { | 401 if (deferred_key) { |
371 if (key->IsSmi()) key = factory()->NumberToString(key); | 402 if (key->IsSmi()) key = factory()->NumberToString(key); |
372 SerializeDeferredKey(deferred_comma, key); | 403 SerializeDeferredKey(deferred_comma, key); |
373 } | 404 } |
374 | 405 |
375 builder_.AppendString(Handle<String>::cast(result)); | 406 builder_.AppendString(Handle<String>::cast(result)); |
376 return SUCCESS; | 407 return SUCCESS; |
377 } | 408 } |
378 | 409 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 | 460 |
430 | 461 |
431 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( | 462 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
432 Handle<JSArray> object) { | 463 Handle<JSArray> object) { |
433 HandleScope handle_scope(isolate_); | 464 HandleScope handle_scope(isolate_); |
434 Result stack_push = StackPush(object); | 465 Result stack_push = StackPush(object); |
435 if (stack_push != SUCCESS) return stack_push; | 466 if (stack_push != SUCCESS) return stack_push; |
436 uint32_t length = 0; | 467 uint32_t length = 0; |
437 CHECK(object->length()->ToArrayLength(&length)); | 468 CHECK(object->length()->ToArrayLength(&length)); |
438 builder_.AppendCharacter('['); | 469 builder_.AppendCharacter('['); |
| 470 Indent(); |
439 switch (object->GetElementsKind()) { | 471 switch (object->GetElementsKind()) { |
440 case FAST_SMI_ELEMENTS: { | 472 case FAST_SMI_ELEMENTS: { |
441 Handle<FixedArray> elements(FixedArray::cast(object->elements()), | 473 Handle<FixedArray> elements(FixedArray::cast(object->elements()), |
442 isolate_); | 474 isolate_); |
443 for (uint32_t i = 0; i < length; i++) { | 475 for (uint32_t i = 0; i < length; i++) { |
444 if (i > 0) builder_.AppendCharacter(','); | 476 Separator(i == 0); |
445 SerializeSmi(Smi::cast(elements->get(i))); | 477 SerializeSmi(Smi::cast(elements->get(i))); |
446 } | 478 } |
447 break; | 479 break; |
448 } | 480 } |
449 case FAST_DOUBLE_ELEMENTS: { | 481 case FAST_DOUBLE_ELEMENTS: { |
450 // Empty array is FixedArray but not FixedDoubleArray. | 482 // Empty array is FixedArray but not FixedDoubleArray. |
451 if (length == 0) break; | 483 if (length == 0) break; |
452 Handle<FixedDoubleArray> elements( | 484 Handle<FixedDoubleArray> elements( |
453 FixedDoubleArray::cast(object->elements()), isolate_); | 485 FixedDoubleArray::cast(object->elements()), isolate_); |
454 for (uint32_t i = 0; i < length; i++) { | 486 for (uint32_t i = 0; i < length; i++) { |
455 if (i > 0) builder_.AppendCharacter(','); | 487 Separator(i == 0); |
456 SerializeDouble(elements->get_scalar(i)); | 488 SerializeDouble(elements->get_scalar(i)); |
457 } | 489 } |
458 break; | 490 break; |
459 } | 491 } |
460 case FAST_ELEMENTS: { | 492 case FAST_ELEMENTS: { |
461 Handle<Object> old_length(object->length(), isolate_); | 493 Handle<Object> old_length(object->length(), isolate_); |
462 for (uint32_t i = 0; i < length; i++) { | 494 for (uint32_t i = 0; i < length; i++) { |
463 if (object->length() != *old_length || | 495 if (object->length() != *old_length || |
464 object->GetElementsKind() != FAST_ELEMENTS) { | 496 object->GetElementsKind() != FAST_ELEMENTS) { |
465 Result result = SerializeJSArraySlow(object, i, length); | 497 Result result = SerializeJSArraySlow(object, i, length); |
466 if (result != SUCCESS) return result; | 498 if (result != SUCCESS) return result; |
467 break; | 499 break; |
468 } | 500 } |
469 if (i > 0) builder_.AppendCharacter(','); | 501 Separator(i == 0); |
470 Result result = SerializeElement( | 502 Result result = SerializeElement( |
471 isolate_, | 503 isolate_, |
472 Handle<Object>(FixedArray::cast(object->elements())->get(i), | 504 Handle<Object>(FixedArray::cast(object->elements())->get(i), |
473 isolate_), | 505 isolate_), |
474 i); | 506 i); |
475 if (result == SUCCESS) continue; | 507 if (result == SUCCESS) continue; |
476 if (result == UNCHANGED) { | 508 if (result == UNCHANGED) { |
477 builder_.AppendCString("null"); | 509 builder_.AppendCString("null"); |
478 } else { | 510 } else { |
479 return result; | 511 return result; |
480 } | 512 } |
481 } | 513 } |
482 break; | 514 break; |
483 } | 515 } |
484 // The FAST_HOLEY_* cases could be handled in a faster way. They resemble | 516 // The FAST_HOLEY_* cases could be handled in a faster way. They resemble |
485 // the non-holey cases except that a lookup is necessary for holes. | 517 // the non-holey cases except that a lookup is necessary for holes. |
486 default: { | 518 default: { |
487 Result result = SerializeJSArraySlow(object, 0, length); | 519 Result result = SerializeJSArraySlow(object, 0, length); |
488 if (result != SUCCESS) return result; | 520 if (result != SUCCESS) return result; |
489 break; | 521 break; |
490 } | 522 } |
491 } | 523 } |
| 524 Unindent(); |
| 525 if (length > 0) NewLine(); |
492 builder_.AppendCharacter(']'); | 526 builder_.AppendCharacter(']'); |
493 StackPop(); | 527 StackPop(); |
494 return SUCCESS; | 528 return SUCCESS; |
495 } | 529 } |
496 | 530 |
497 | 531 |
498 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow( | 532 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow( |
499 Handle<JSArray> object, uint32_t start, uint32_t length) { | 533 Handle<JSArray> object, uint32_t start, uint32_t length) { |
500 for (uint32_t i = start; i < length; i++) { | 534 for (uint32_t i = start; i < length; i++) { |
501 if (i > 0) builder_.AppendCharacter(','); | 535 Separator(i == 0); |
502 Handle<Object> element; | 536 Handle<Object> element; |
503 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 537 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
504 isolate_, element, JSReceiver::GetElement(isolate_, object, i), | 538 isolate_, element, JSReceiver::GetElement(isolate_, object, i), |
505 EXCEPTION); | 539 EXCEPTION); |
506 if (element->IsUndefined()) { | 540 if (element->IsUndefined()) { |
507 builder_.AppendCString("null"); | 541 builder_.AppendCString("null"); |
508 } else { | 542 } else { |
509 Result result = SerializeElement(isolate_, element, i); | 543 Result result = SerializeElement(isolate_, element, i); |
510 if (result == SUCCESS) continue; | 544 if (result == SUCCESS) continue; |
511 if (result == UNCHANGED) { | 545 if (result == UNCHANGED) { |
512 builder_.AppendCString("null"); | 546 builder_.AppendCString("null"); |
513 } else { | 547 } else { |
514 return result; | 548 return result; |
515 } | 549 } |
516 } | 550 } |
517 } | 551 } |
518 return SUCCESS; | 552 return SUCCESS; |
519 } | 553 } |
520 | 554 |
521 | 555 |
522 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( | 556 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
523 Handle<JSObject> object) { | 557 Handle<JSObject> object) { |
524 HandleScope handle_scope(isolate_); | 558 HandleScope handle_scope(isolate_); |
525 Result stack_push = StackPush(object); | 559 Result stack_push = StackPush(object); |
526 if (stack_push != SUCCESS) return stack_push; | 560 if (stack_push != SUCCESS) return stack_push; |
527 DCHECK(!object->IsJSGlobalProxy() && !object->IsJSGlobalObject()); | 561 DCHECK(!object->IsJSGlobalProxy() && !object->IsJSGlobalObject()); |
528 | 562 |
529 builder_.AppendCharacter('{'); | 563 builder_.AppendCharacter('{'); |
| 564 Indent(); |
530 bool comma = false; | 565 bool comma = false; |
531 | 566 |
532 if (object->HasFastProperties() && | 567 if (object->HasFastProperties() && |
533 !object->HasIndexedInterceptor() && | 568 !object->HasIndexedInterceptor() && |
534 !object->HasNamedInterceptor() && | 569 !object->HasNamedInterceptor() && |
535 object->elements()->length() == 0) { | 570 object->elements()->length() == 0) { |
536 Handle<Map> map(object->map()); | 571 Handle<Map> map(object->map()); |
537 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | 572 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
538 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); | 573 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); |
539 // TODO(rossberg): Should this throw? | 574 // TODO(rossberg): Should this throw? |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 } | 621 } |
587 } | 622 } |
588 Handle<Object> property; | 623 Handle<Object> property; |
589 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 624 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
590 isolate_, property, maybe_property, EXCEPTION); | 625 isolate_, property, maybe_property, EXCEPTION); |
591 Result result = SerializeProperty(property, comma, key_handle); | 626 Result result = SerializeProperty(property, comma, key_handle); |
592 if (!comma && result == SUCCESS) comma = true; | 627 if (!comma && result == SUCCESS) comma = true; |
593 if (result == EXCEPTION) return result; | 628 if (result == EXCEPTION) return result; |
594 } | 629 } |
595 } | 630 } |
596 | 631 Unindent(); |
| 632 if (comma) NewLine(); |
597 builder_.AppendCharacter('}'); | 633 builder_.AppendCharacter('}'); |
598 StackPop(); | 634 StackPop(); |
599 return SUCCESS; | 635 return SUCCESS; |
600 } | 636 } |
601 | 637 |
602 | 638 |
603 template <typename SrcChar, typename DestChar> | 639 template <typename SrcChar, typename DestChar> |
604 void BasicJsonStringifier::SerializeStringUnchecked_( | 640 void BasicJsonStringifier::SerializeStringUnchecked_( |
605 Vector<const SrcChar> src, | 641 Vector<const SrcChar> src, |
606 IncrementalStringBuilder::NoExtend<DestChar>* dest) { | 642 IncrementalStringBuilder::NoExtend<DestChar>* dest) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { | 690 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { |
655 return c >= '#' && c <= '~' && c != '\\'; | 691 return c >= '#' && c <= '~' && c != '\\'; |
656 } | 692 } |
657 | 693 |
658 | 694 |
659 template <> | 695 template <> |
660 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { | 696 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { |
661 return c >= '#' && c != '\\' && c != 0x7f; | 697 return c >= '#' && c != '\\' && c != 0x7f; |
662 } | 698 } |
663 | 699 |
| 700 void BasicJsonStringifier::NewLine() { |
| 701 if (gap_ == nullptr) return; |
| 702 builder_.AppendCharacter('\n'); |
| 703 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); |
| 704 } |
664 | 705 |
665 void BasicJsonStringifier::SerializeString(Handle<String> object) { | 706 void BasicJsonStringifier::SerializeString(Handle<String> object) { |
666 object = String::Flatten(object); | 707 object = String::Flatten(object); |
667 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { | 708 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { |
668 if (object->IsOneByteRepresentationUnderneath()) { | 709 if (object->IsOneByteRepresentationUnderneath()) { |
669 SerializeString_<uint8_t, uint8_t>(object); | 710 SerializeString_<uint8_t, uint8_t>(object); |
670 } else { | 711 } else { |
671 builder_.ChangeEncoding(); | 712 builder_.ChangeEncoding(); |
672 SerializeString(object); | 713 SerializeString(object); |
673 } | 714 } |
674 } else { | 715 } else { |
675 if (object->IsOneByteRepresentationUnderneath()) { | 716 if (object->IsOneByteRepresentationUnderneath()) { |
676 SerializeString_<uint8_t, uc16>(object); | 717 SerializeString_<uint8_t, uc16>(object); |
677 } else { | 718 } else { |
678 SerializeString_<uc16, uc16>(object); | 719 SerializeString_<uc16, uc16>(object); |
679 } | 720 } |
680 } | 721 } |
681 } | 722 } |
682 | 723 |
683 } // namespace internal | 724 } // namespace internal |
684 } // namespace v8 | 725 } // namespace v8 |
685 | 726 |
686 #endif // V8_JSON_STRINGIFIER_H_ | 727 #endif // V8_JSON_STRINGIFIER_H_ |
OLD | NEW |