OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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_PARSER_H_ | 5 #ifndef V8_JSON_PARSER_H_ |
6 #define V8_JSON_PARSER_H_ | 6 #define V8_JSON_PARSER_H_ |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/char-predicates-inl.h" | 10 #include "src/char-predicates-inl.h" |
11 #include "src/conversions.h" | 11 #include "src/conversions.h" |
12 #include "src/heap/spaces-inl.h" | 12 #include "src/heap/spaces-inl.h" |
13 #include "src/messages.h" | 13 #include "src/messages.h" |
14 #include "src/token.h" | 14 #include "src/token.h" |
15 | 15 |
16 namespace v8 { | 16 namespace v8 { |
17 namespace internal { | 17 namespace internal { |
18 | 18 |
19 // A simple json parser. | 19 // A simple json parser. |
20 template <bool seq_ascii> | 20 template <bool seq_one_byte> |
21 class JsonParser BASE_EMBEDDED { | 21 class JsonParser BASE_EMBEDDED { |
22 public: | 22 public: |
23 MUST_USE_RESULT static MaybeHandle<Object> Parse(Handle<String> source) { | 23 MUST_USE_RESULT static MaybeHandle<Object> Parse(Handle<String> source) { |
24 return JsonParser(source).ParseJson(); | 24 return JsonParser(source).ParseJson(); |
25 } | 25 } |
26 | 26 |
27 static const int kEndOfString = -1; | 27 static const int kEndOfString = -1; |
28 | 28 |
29 private: | 29 private: |
30 explicit JsonParser(Handle<String> source) | 30 explicit JsonParser(Handle<String> source) |
31 : source_(source), | 31 : source_(source), |
32 source_length_(source->length()), | 32 source_length_(source->length()), |
33 isolate_(source->map()->GetHeap()->isolate()), | 33 isolate_(source->map()->GetHeap()->isolate()), |
34 factory_(isolate_->factory()), | 34 factory_(isolate_->factory()), |
35 zone_(isolate_), | 35 zone_(isolate_), |
36 object_constructor_(isolate_->native_context()->object_function(), | 36 object_constructor_(isolate_->native_context()->object_function(), |
37 isolate_), | 37 isolate_), |
38 position_(-1) { | 38 position_(-1) { |
39 source_ = String::Flatten(source_); | 39 source_ = String::Flatten(source_); |
40 pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED; | 40 pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED; |
41 | 41 |
42 // Optimized fast case where we only have ASCII characters. | 42 // Optimized fast case where we only have Latin1 characters. |
43 if (seq_ascii) { | 43 if (seq_one_byte) { |
44 seq_source_ = Handle<SeqOneByteString>::cast(source_); | 44 seq_source_ = Handle<SeqOneByteString>::cast(source_); |
45 } | 45 } |
46 } | 46 } |
47 | 47 |
48 // Parse a string containing a single JSON value. | 48 // Parse a string containing a single JSON value. |
49 MaybeHandle<Object> ParseJson(); | 49 MaybeHandle<Object> ParseJson(); |
50 | 50 |
51 inline void Advance() { | 51 inline void Advance() { |
52 position_++; | 52 position_++; |
53 if (position_ >= source_length_) { | 53 if (position_ >= source_length_) { |
54 c0_ = kEndOfString; | 54 c0_ = kEndOfString; |
55 } else if (seq_ascii) { | 55 } else if (seq_one_byte) { |
56 c0_ = seq_source_->SeqOneByteStringGet(position_); | 56 c0_ = seq_source_->SeqOneByteStringGet(position_); |
57 } else { | 57 } else { |
58 c0_ = source_->Get(position_); | 58 c0_ = source_->Get(position_); |
59 } | 59 } |
60 } | 60 } |
61 | 61 |
62 // The JSON lexical grammar is specified in the ECMAScript 5 standard, | 62 // The JSON lexical grammar is specified in the ECMAScript 5 standard, |
63 // section 15.12.1.1. The only allowed whitespace characters between tokens | 63 // section 15.12.1.1. The only allowed whitespace characters between tokens |
64 // are tab, carriage-return, newline and space. | 64 // are tab, carriage-return, newline and space. |
65 | 65 |
(...skipping 30 matching lines...) Expand all Loading... |
96 // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid. | 96 // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid. |
97 Handle<String> ParseJsonString() { | 97 Handle<String> ParseJsonString() { |
98 return ScanJsonString<false>(); | 98 return ScanJsonString<false>(); |
99 } | 99 } |
100 | 100 |
101 bool ParseJsonString(Handle<String> expected) { | 101 bool ParseJsonString(Handle<String> expected) { |
102 int length = expected->length(); | 102 int length = expected->length(); |
103 if (source_->length() - position_ - 1 > length) { | 103 if (source_->length() - position_ - 1 > length) { |
104 DisallowHeapAllocation no_gc; | 104 DisallowHeapAllocation no_gc; |
105 String::FlatContent content = expected->GetFlatContent(); | 105 String::FlatContent content = expected->GetFlatContent(); |
106 if (content.IsAscii()) { | 106 if (content.IsOneByte()) { |
107 DCHECK_EQ('"', c0_); | 107 DCHECK_EQ('"', c0_); |
108 const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1; | 108 const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1; |
109 const uint8_t* expected_chars = content.ToOneByteVector().start(); | 109 const uint8_t* expected_chars = content.ToOneByteVector().start(); |
110 for (int i = 0; i < length; i++) { | 110 for (int i = 0; i < length; i++) { |
111 uint8_t c0 = input_chars[i]; | 111 uint8_t c0 = input_chars[i]; |
112 if (c0 != expected_chars[i] || | 112 if (c0 != expected_chars[i] || |
113 c0 == '"' || c0 < 0x20 || c0 == '\\') { | 113 c0 == '"' || c0 < 0x20 || c0 == '\\') { |
114 return false; | 114 return false; |
115 } | 115 } |
116 } | 116 } |
117 if (input_chars[length] == '"') { | 117 if (input_chars[length] == '"') { |
118 position_ = position_ + length + 1; | 118 position_ = position_ + length + 1; |
119 AdvanceSkipWhitespace(); | 119 AdvanceSkipWhitespace(); |
120 return true; | 120 return true; |
121 } | 121 } |
122 } | 122 } |
123 } | 123 } |
124 return false; | 124 return false; |
125 } | 125 } |
126 | 126 |
127 Handle<String> ParseJsonInternalizedString() { | 127 Handle<String> ParseJsonInternalizedString() { |
128 return ScanJsonString<true>(); | 128 return ScanJsonString<true>(); |
129 } | 129 } |
130 | 130 |
131 template <bool is_internalized> | 131 template <bool is_internalized> |
132 Handle<String> ScanJsonString(); | 132 Handle<String> ScanJsonString(); |
133 // Creates a new string and copies prefix[start..end] into the beginning | 133 // Creates a new string and copies prefix[start..end] into the beginning |
134 // of it. Then scans the rest of the string, adding characters after the | 134 // of it. Then scans the rest of the string, adding characters after the |
135 // prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char. | 135 // prefix. Called by ScanJsonString when reaching a '\' or non-Latin1 char. |
136 template <typename StringType, typename SinkChar> | 136 template <typename StringType, typename SinkChar> |
137 Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end); | 137 Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end); |
138 | 138 |
139 // A JSON number (production JSONNumber) is a subset of the valid JavaScript | 139 // A JSON number (production JSONNumber) is a subset of the valid JavaScript |
140 // decimal number literals. | 140 // decimal number literals. |
141 // It includes an optional minus sign, must have at least one | 141 // It includes an optional minus sign, must have at least one |
142 // digit before and after a decimal point, may not have prefixed zeros (unless | 142 // digit before and after a decimal point, may not have prefixed zeros (unless |
143 // the integer part is zero), and may include an exponent part (e.g., "e-10"). | 143 // the integer part is zero), and may include an exponent part (e.g., "e-10"). |
144 // Hexadecimal and octal numbers are not allowed. | 144 // Hexadecimal and octal numbers are not allowed. |
145 Handle<Object> ParseJsonNumber(); | 145 Handle<Object> ParseJsonNumber(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 | 188 |
189 PretenureFlag pretenure_; | 189 PretenureFlag pretenure_; |
190 Isolate* isolate_; | 190 Isolate* isolate_; |
191 Factory* factory_; | 191 Factory* factory_; |
192 Zone zone_; | 192 Zone zone_; |
193 Handle<JSFunction> object_constructor_; | 193 Handle<JSFunction> object_constructor_; |
194 uc32 c0_; | 194 uc32 c0_; |
195 int position_; | 195 int position_; |
196 }; | 196 }; |
197 | 197 |
198 template <bool seq_ascii> | 198 template <bool seq_one_byte> |
199 MaybeHandle<Object> JsonParser<seq_ascii>::ParseJson() { | 199 MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() { |
200 // Advance to the first character (possibly EOS) | 200 // Advance to the first character (possibly EOS) |
201 AdvanceSkipWhitespace(); | 201 AdvanceSkipWhitespace(); |
202 Handle<Object> result = ParseJsonValue(); | 202 Handle<Object> result = ParseJsonValue(); |
203 if (result.is_null() || c0_ != kEndOfString) { | 203 if (result.is_null() || c0_ != kEndOfString) { |
204 // Some exception (for example stack overflow) is already pending. | 204 // Some exception (for example stack overflow) is already pending. |
205 if (isolate_->has_pending_exception()) return Handle<Object>::null(); | 205 if (isolate_->has_pending_exception()) return Handle<Object>::null(); |
206 | 206 |
207 // Parse failed. Current character is the unexpected token. | 207 // Parse failed. Current character is the unexpected token. |
208 const char* message; | 208 const char* message; |
209 Factory* factory = this->factory(); | 209 Factory* factory = this->factory(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 Handle<Object> error; | 247 Handle<Object> error; |
248 ASSIGN_RETURN_ON_EXCEPTION(isolate(), error, | 248 ASSIGN_RETURN_ON_EXCEPTION(isolate(), error, |
249 factory->NewSyntaxError(message, array), Object); | 249 factory->NewSyntaxError(message, array), Object); |
250 return isolate()->template Throw<Object>(error, &location); | 250 return isolate()->template Throw<Object>(error, &location); |
251 } | 251 } |
252 return result; | 252 return result; |
253 } | 253 } |
254 | 254 |
255 | 255 |
256 // Parse any JSON value. | 256 // Parse any JSON value. |
257 template <bool seq_ascii> | 257 template <bool seq_one_byte> |
258 Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() { | 258 Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() { |
259 StackLimitCheck stack_check(isolate_); | 259 StackLimitCheck stack_check(isolate_); |
260 if (stack_check.HasOverflowed()) { | 260 if (stack_check.HasOverflowed()) { |
261 isolate_->StackOverflow(); | 261 isolate_->StackOverflow(); |
262 return Handle<Object>::null(); | 262 return Handle<Object>::null(); |
263 } | 263 } |
264 | 264 |
265 if (c0_ == '"') return ParseJsonString(); | 265 if (c0_ == '"') return ParseJsonString(); |
266 if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber(); | 266 if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber(); |
267 if (c0_ == '{') return ParseJsonObject(); | 267 if (c0_ == '{') return ParseJsonObject(); |
268 if (c0_ == '[') return ParseJsonArray(); | 268 if (c0_ == '[') return ParseJsonArray(); |
(...skipping 19 matching lines...) Expand all Loading... |
288 AdvanceSkipWhitespace(); | 288 AdvanceSkipWhitespace(); |
289 return factory()->null_value(); | 289 return factory()->null_value(); |
290 } | 290 } |
291 return ReportUnexpectedCharacter(); | 291 return ReportUnexpectedCharacter(); |
292 } | 292 } |
293 return ReportUnexpectedCharacter(); | 293 return ReportUnexpectedCharacter(); |
294 } | 294 } |
295 | 295 |
296 | 296 |
297 // Parse a JSON object. Position must be right at '{'. | 297 // Parse a JSON object. Position must be right at '{'. |
298 template <bool seq_ascii> | 298 template <bool seq_one_byte> |
299 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() { | 299 Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() { |
300 HandleScope scope(isolate()); | 300 HandleScope scope(isolate()); |
301 Handle<JSObject> json_object = | 301 Handle<JSObject> json_object = |
302 factory()->NewJSObject(object_constructor(), pretenure_); | 302 factory()->NewJSObject(object_constructor(), pretenure_); |
303 Handle<Map> map(json_object->map()); | 303 Handle<Map> map(json_object->map()); |
304 ZoneList<Handle<Object> > properties(8, zone()); | 304 ZoneList<Handle<Object> > properties(8, zone()); |
305 DCHECK_EQ(c0_, '{'); | 305 DCHECK_EQ(c0_, '{'); |
306 | 306 |
307 bool transitioning = true; | 307 bool transitioning = true; |
308 | 308 |
309 AdvanceSkipWhitespace(); | 309 AdvanceSkipWhitespace(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 Handle<String> key; | 352 Handle<String> key; |
353 Handle<Object> value; | 353 Handle<Object> value; |
354 | 354 |
355 // Try to follow existing transitions as long as possible. Once we stop | 355 // Try to follow existing transitions as long as possible. Once we stop |
356 // transitioning, no transition can be found anymore. | 356 // transitioning, no transition can be found anymore. |
357 if (transitioning) { | 357 if (transitioning) { |
358 // First check whether there is a single expected transition. If so, try | 358 // First check whether there is a single expected transition. If so, try |
359 // to parse it first. | 359 // to parse it first. |
360 bool follow_expected = false; | 360 bool follow_expected = false; |
361 Handle<Map> target; | 361 Handle<Map> target; |
362 if (seq_ascii) { | 362 if (seq_one_byte) { |
363 key = Map::ExpectedTransitionKey(map); | 363 key = Map::ExpectedTransitionKey(map); |
364 follow_expected = !key.is_null() && ParseJsonString(key); | 364 follow_expected = !key.is_null() && ParseJsonString(key); |
365 } | 365 } |
366 // If the expected transition hits, follow it. | 366 // If the expected transition hits, follow it. |
367 if (follow_expected) { | 367 if (follow_expected) { |
368 target = Map::ExpectedTransitionTarget(map); | 368 target = Map::ExpectedTransitionTarget(map); |
369 } else { | 369 } else { |
370 // If the expected transition failed, parse an internalized string and | 370 // If the expected transition failed, parse an internalized string and |
371 // try to find a matching transition. | 371 // try to find a matching transition. |
372 key = ParseJsonInternalizedString(); | 372 key = ParseJsonInternalizedString(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); | 442 FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); |
443 json_object->FastPropertyAtPut(index, *value); | 443 json_object->FastPropertyAtPut(index, *value); |
444 } | 444 } |
445 } | 445 } |
446 } | 446 } |
447 AdvanceSkipWhitespace(); | 447 AdvanceSkipWhitespace(); |
448 return scope.CloseAndEscape(json_object); | 448 return scope.CloseAndEscape(json_object); |
449 } | 449 } |
450 | 450 |
451 // Parse a JSON array. Position must be right at '['. | 451 // Parse a JSON array. Position must be right at '['. |
452 template <bool seq_ascii> | 452 template <bool seq_one_byte> |
453 Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() { | 453 Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() { |
454 HandleScope scope(isolate()); | 454 HandleScope scope(isolate()); |
455 ZoneList<Handle<Object> > elements(4, zone()); | 455 ZoneList<Handle<Object> > elements(4, zone()); |
456 DCHECK_EQ(c0_, '['); | 456 DCHECK_EQ(c0_, '['); |
457 | 457 |
458 AdvanceSkipWhitespace(); | 458 AdvanceSkipWhitespace(); |
459 if (c0_ != ']') { | 459 if (c0_ != ']') { |
460 do { | 460 do { |
461 Handle<Object> element = ParseJsonValue(); | 461 Handle<Object> element = ParseJsonValue(); |
462 if (element.is_null()) return ReportUnexpectedCharacter(); | 462 if (element.is_null()) return ReportUnexpectedCharacter(); |
463 elements.Add(element, zone()); | 463 elements.Add(element, zone()); |
464 } while (MatchSkipWhiteSpace(',')); | 464 } while (MatchSkipWhiteSpace(',')); |
465 if (c0_ != ']') { | 465 if (c0_ != ']') { |
466 return ReportUnexpectedCharacter(); | 466 return ReportUnexpectedCharacter(); |
467 } | 467 } |
468 } | 468 } |
469 AdvanceSkipWhitespace(); | 469 AdvanceSkipWhitespace(); |
470 // Allocate a fixed array with all the elements. | 470 // Allocate a fixed array with all the elements. |
471 Handle<FixedArray> fast_elements = | 471 Handle<FixedArray> fast_elements = |
472 factory()->NewFixedArray(elements.length(), pretenure_); | 472 factory()->NewFixedArray(elements.length(), pretenure_); |
473 for (int i = 0, n = elements.length(); i < n; i++) { | 473 for (int i = 0, n = elements.length(); i < n; i++) { |
474 fast_elements->set(i, *elements[i]); | 474 fast_elements->set(i, *elements[i]); |
475 } | 475 } |
476 Handle<Object> json_array = factory()->NewJSArrayWithElements( | 476 Handle<Object> json_array = factory()->NewJSArrayWithElements( |
477 fast_elements, FAST_ELEMENTS, pretenure_); | 477 fast_elements, FAST_ELEMENTS, pretenure_); |
478 return scope.CloseAndEscape(json_array); | 478 return scope.CloseAndEscape(json_array); |
479 } | 479 } |
480 | 480 |
481 | 481 |
482 template <bool seq_ascii> | 482 template <bool seq_one_byte> |
483 Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() { | 483 Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() { |
484 bool negative = false; | 484 bool negative = false; |
485 int beg_pos = position_; | 485 int beg_pos = position_; |
486 if (c0_ == '-') { | 486 if (c0_ == '-') { |
487 Advance(); | 487 Advance(); |
488 negative = true; | 488 negative = true; |
489 } | 489 } |
490 if (c0_ == '0') { | 490 if (c0_ == '0') { |
491 Advance(); | 491 Advance(); |
492 // Prefix zero is only allowed if it's the only digit before | 492 // Prefix zero is only allowed if it's the only digit before |
493 // a decimal point or exponent. | 493 // a decimal point or exponent. |
(...skipping 22 matching lines...) Expand all Loading... |
516 if (AsciiAlphaToLower(c0_) == 'e') { | 516 if (AsciiAlphaToLower(c0_) == 'e') { |
517 Advance(); | 517 Advance(); |
518 if (c0_ == '-' || c0_ == '+') Advance(); | 518 if (c0_ == '-' || c0_ == '+') Advance(); |
519 if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter(); | 519 if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter(); |
520 do { | 520 do { |
521 Advance(); | 521 Advance(); |
522 } while (c0_ >= '0' && c0_ <= '9'); | 522 } while (c0_ >= '0' && c0_ <= '9'); |
523 } | 523 } |
524 int length = position_ - beg_pos; | 524 int length = position_ - beg_pos; |
525 double number; | 525 double number; |
526 if (seq_ascii) { | 526 if (seq_one_byte) { |
527 Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length); | 527 Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length); |
528 number = StringToDouble(isolate()->unicode_cache(), | 528 number = StringToDouble(isolate()->unicode_cache(), |
529 chars, | 529 chars, |
530 NO_FLAGS, // Hex, octal or trailing junk. | 530 NO_FLAGS, // Hex, octal or trailing junk. |
531 base::OS::nan_value()); | 531 base::OS::nan_value()); |
532 } else { | 532 } else { |
533 Vector<uint8_t> buffer = Vector<uint8_t>::New(length); | 533 Vector<uint8_t> buffer = Vector<uint8_t>::New(length); |
534 String::WriteToFlat(*source_, buffer.start(), beg_pos, position_); | 534 String::WriteToFlat(*source_, buffer.start(), beg_pos, position_); |
535 Vector<const uint8_t> result = | 535 Vector<const uint8_t> result = |
536 Vector<const uint8_t>(buffer.start(), length); | 536 Vector<const uint8_t>(buffer.start(), length); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 inline Handle<SeqOneByteString> NewRawString(Factory* factory, | 574 inline Handle<SeqOneByteString> NewRawString(Factory* factory, |
575 int length, | 575 int length, |
576 PretenureFlag pretenure) { | 576 PretenureFlag pretenure) { |
577 return factory->NewRawOneByteString(length, pretenure).ToHandleChecked(); | 577 return factory->NewRawOneByteString(length, pretenure).ToHandleChecked(); |
578 } | 578 } |
579 | 579 |
580 | 580 |
581 // Scans the rest of a JSON string starting from position_ and writes | 581 // Scans the rest of a JSON string starting from position_ and writes |
582 // prefix[start..end] along with the scanned characters into a | 582 // prefix[start..end] along with the scanned characters into a |
583 // sequential string of type StringType. | 583 // sequential string of type StringType. |
584 template <bool seq_ascii> | 584 template <bool seq_one_byte> |
585 template <typename StringType, typename SinkChar> | 585 template <typename StringType, typename SinkChar> |
586 Handle<String> JsonParser<seq_ascii>::SlowScanJsonString( | 586 Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString( |
587 Handle<String> prefix, int start, int end) { | 587 Handle<String> prefix, int start, int end) { |
588 int count = end - start; | 588 int count = end - start; |
589 int max_length = count + source_length_ - position_; | 589 int max_length = count + source_length_ - position_; |
590 int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count)); | 590 int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count)); |
591 Handle<StringType> seq_string = | 591 Handle<StringType> seq_string = |
592 NewRawString<StringType>(factory(), length, pretenure_); | 592 NewRawString<StringType>(factory(), length, pretenure_); |
593 // Copy prefix into seq_str. | 593 // Copy prefix into seq_str. |
594 SinkChar* dest = seq_string->GetChars(); | 594 SinkChar* dest = seq_string->GetChars(); |
595 String::WriteToFlat(*prefix, dest, start, end); | 595 String::WriteToFlat(*prefix, dest, start, end); |
596 | 596 |
597 while (c0_ != '"') { | 597 while (c0_ != '"') { |
598 // Check for control character (0x00-0x1f) or unterminated string (<0). | 598 // Check for control character (0x00-0x1f) or unterminated string (<0). |
599 if (c0_ < 0x20) return Handle<String>::null(); | 599 if (c0_ < 0x20) return Handle<String>::null(); |
600 if (count >= length) { | 600 if (count >= length) { |
601 // We need to create a longer sequential string for the result. | 601 // We need to create a longer sequential string for the result. |
602 return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count); | 602 return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count); |
603 } | 603 } |
604 if (c0_ != '\\') { | 604 if (c0_ != '\\') { |
605 // If the sink can contain UC16 characters, or source_ contains only | 605 // If the sink can contain UC16 characters, or source_ contains only |
606 // ASCII characters, there's no need to test whether we can store the | 606 // Latin1 characters, there's no need to test whether we can store the |
607 // character. Otherwise check whether the UC16 source character can fit | 607 // character. Otherwise check whether the UC16 source character can fit |
608 // in the ASCII sink. | 608 // in the Latin1 sink. |
609 if (sizeof(SinkChar) == kUC16Size || | 609 if (sizeof(SinkChar) == kUC16Size || seq_one_byte || |
610 seq_ascii || | |
611 c0_ <= String::kMaxOneByteCharCode) { | 610 c0_ <= String::kMaxOneByteCharCode) { |
612 SeqStringSet(seq_string, count++, c0_); | 611 SeqStringSet(seq_string, count++, c0_); |
613 Advance(); | 612 Advance(); |
614 } else { | 613 } else { |
615 // StringType is SeqOneByteString and we just read a non-ASCII char. | 614 // StringType is SeqOneByteString and we just read a non-Latin1 char. |
616 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count); | 615 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count); |
617 } | 616 } |
618 } else { | 617 } else { |
619 Advance(); // Advance past the \. | 618 Advance(); // Advance past the \. |
620 switch (c0_) { | 619 switch (c0_) { |
621 case '"': | 620 case '"': |
622 case '\\': | 621 case '\\': |
623 case '/': | 622 case '/': |
624 SeqStringSet(seq_string, count++, c0_); | 623 SeqStringSet(seq_string, count++, c0_); |
625 break; | 624 break; |
(...skipping 20 matching lines...) Expand all Loading... |
646 if (digit < 0) { | 645 if (digit < 0) { |
647 return Handle<String>::null(); | 646 return Handle<String>::null(); |
648 } | 647 } |
649 value = value * 16 + digit; | 648 value = value * 16 + digit; |
650 } | 649 } |
651 if (sizeof(SinkChar) == kUC16Size || | 650 if (sizeof(SinkChar) == kUC16Size || |
652 value <= String::kMaxOneByteCharCode) { | 651 value <= String::kMaxOneByteCharCode) { |
653 SeqStringSet(seq_string, count++, value); | 652 SeqStringSet(seq_string, count++, value); |
654 break; | 653 break; |
655 } else { | 654 } else { |
656 // StringType is SeqOneByteString and we just read a non-ASCII char. | 655 // StringType is SeqOneByteString and we just read a non-Latin1 |
| 656 // char. |
657 position_ -= 6; // Rewind position_ to \ in \uxxxx. | 657 position_ -= 6; // Rewind position_ to \ in \uxxxx. |
658 Advance(); | 658 Advance(); |
659 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, | 659 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, |
660 0, | 660 0, |
661 count); | 661 count); |
662 } | 662 } |
663 } | 663 } |
664 default: | 664 default: |
665 return Handle<String>::null(); | 665 return Handle<String>::null(); |
666 } | 666 } |
667 Advance(); | 667 Advance(); |
668 } | 668 } |
669 } | 669 } |
670 | 670 |
671 DCHECK_EQ('"', c0_); | 671 DCHECK_EQ('"', c0_); |
672 // Advance past the last '"'. | 672 // Advance past the last '"'. |
673 AdvanceSkipWhitespace(); | 673 AdvanceSkipWhitespace(); |
674 | 674 |
675 // Shrink seq_string length to count and return. | 675 // Shrink seq_string length to count and return. |
676 return SeqString::Truncate(seq_string, count); | 676 return SeqString::Truncate(seq_string, count); |
677 } | 677 } |
678 | 678 |
679 | 679 |
680 template <bool seq_ascii> | 680 template <bool seq_one_byte> |
681 template <bool is_internalized> | 681 template <bool is_internalized> |
682 Handle<String> JsonParser<seq_ascii>::ScanJsonString() { | 682 Handle<String> JsonParser<seq_one_byte>::ScanJsonString() { |
683 DCHECK_EQ('"', c0_); | 683 DCHECK_EQ('"', c0_); |
684 Advance(); | 684 Advance(); |
685 if (c0_ == '"') { | 685 if (c0_ == '"') { |
686 AdvanceSkipWhitespace(); | 686 AdvanceSkipWhitespace(); |
687 return factory()->empty_string(); | 687 return factory()->empty_string(); |
688 } | 688 } |
689 | 689 |
690 if (seq_ascii && is_internalized) { | 690 if (seq_one_byte && is_internalized) { |
691 // Fast path for existing internalized strings. If the the string being | 691 // Fast path for existing internalized strings. If the the string being |
692 // parsed is not a known internalized string, contains backslashes or | 692 // parsed is not a known internalized string, contains backslashes or |
693 // unexpectedly reaches the end of string, return with an empty handle. | 693 // unexpectedly reaches the end of string, return with an empty handle. |
694 uint32_t running_hash = isolate()->heap()->HashSeed(); | 694 uint32_t running_hash = isolate()->heap()->HashSeed(); |
695 int position = position_; | 695 int position = position_; |
696 uc32 c0 = c0_; | 696 uc32 c0 = c0_; |
697 do { | 697 do { |
698 if (c0 == '\\') { | 698 if (c0 == '\\') { |
699 c0_ = c0; | 699 c0_ = c0; |
700 int beg_pos = position_; | 700 int beg_pos = position_; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 } | 751 } |
752 entry = StringTable::NextProbe(entry, count++, capacity); | 752 entry = StringTable::NextProbe(entry, count++, capacity); |
753 } | 753 } |
754 position_ = position; | 754 position_ = position; |
755 // Advance past the last '"'. | 755 // Advance past the last '"'. |
756 AdvanceSkipWhitespace(); | 756 AdvanceSkipWhitespace(); |
757 return result; | 757 return result; |
758 } | 758 } |
759 | 759 |
760 int beg_pos = position_; | 760 int beg_pos = position_; |
761 // Fast case for ASCII only without escape characters. | 761 // Fast case for Latin1 only without escape characters. |
762 do { | 762 do { |
763 // Check for control character (0x00-0x1f) or unterminated string (<0). | 763 // Check for control character (0x00-0x1f) or unterminated string (<0). |
764 if (c0_ < 0x20) return Handle<String>::null(); | 764 if (c0_ < 0x20) return Handle<String>::null(); |
765 if (c0_ != '\\') { | 765 if (c0_ != '\\') { |
766 if (seq_ascii || c0_ <= String::kMaxOneByteCharCode) { | 766 if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) { |
767 Advance(); | 767 Advance(); |
768 } else { | 768 } else { |
769 return SlowScanJsonString<SeqTwoByteString, uc16>(source_, | 769 return SlowScanJsonString<SeqTwoByteString, uc16>(source_, |
770 beg_pos, | 770 beg_pos, |
771 position_); | 771 position_); |
772 } | 772 } |
773 } else { | 773 } else { |
774 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, | 774 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, |
775 beg_pos, | 775 beg_pos, |
776 position_); | 776 position_); |
777 } | 777 } |
778 } while (c0_ != '"'); | 778 } while (c0_ != '"'); |
779 int length = position_ - beg_pos; | 779 int length = position_ - beg_pos; |
780 Handle<String> result = | 780 Handle<String> result = |
781 factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked(); | 781 factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked(); |
782 uint8_t* dest = SeqOneByteString::cast(*result)->GetChars(); | 782 uint8_t* dest = SeqOneByteString::cast(*result)->GetChars(); |
783 String::WriteToFlat(*source_, dest, beg_pos, position_); | 783 String::WriteToFlat(*source_, dest, beg_pos, position_); |
784 | 784 |
785 DCHECK_EQ('"', c0_); | 785 DCHECK_EQ('"', c0_); |
786 // Advance past the last '"'. | 786 // Advance past the last '"'. |
787 AdvanceSkipWhitespace(); | 787 AdvanceSkipWhitespace(); |
788 return result; | 788 return result; |
789 } | 789 } |
790 | 790 |
791 } } // namespace v8::internal | 791 } } // namespace v8::internal |
792 | 792 |
793 #endif // V8_JSON_PARSER_H_ | 793 #endif // V8_JSON_PARSER_H_ |
OLD | NEW |