OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium 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 #include "base/json/json_parser.h" | 5 #include "base/json/json_parser.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 default: | 272 default: |
273 return; | 273 return; |
274 } | 274 } |
275 } | 275 } |
276 } | 276 } |
277 | 277 |
278 bool JSONParser::EatComment() { | 278 bool JSONParser::EatComment() { |
279 if (*pos_ != '/' || !CanConsume(1)) | 279 if (*pos_ != '/' || !CanConsume(1)) |
280 return false; | 280 return false; |
281 | 281 |
282 char next_char = *NextChar(); | 282 NextChar(); |
brettw
2017/05/09 19:53:14
Did you consider making NextChar() return void? It
Robert Sesek
2017/05/09 21:27:36
Yeah, I was thinking about this because result of
| |
283 if (next_char == '/') { | 283 |
284 if (!CanConsume(1)) | |
285 return false; | |
286 | |
287 if (*pos_ == '/') { | |
284 // Single line comment, read to newline. | 288 // Single line comment, read to newline. |
285 while (CanConsume(1)) { | 289 while (CanConsume(1)) { |
286 next_char = *NextChar(); | 290 if (*pos_ == '\n' || *pos_ == '\r') |
287 if (next_char == '\n' || next_char == '\r') | |
288 return true; | 291 return true; |
292 NextChar(); | |
289 } | 293 } |
290 } else if (next_char == '*') { | 294 } else if (*pos_ == '*') { |
291 char previous_char = '\0'; | 295 char previous_char = '\0'; |
292 // Block comment, read until end marker. | 296 // Block comment, read until end marker. |
293 while (CanConsume(1)) { | 297 while (CanConsume(1)) { |
294 next_char = *NextChar(); | 298 if (previous_char == '*' && *pos_ == '/') { |
295 if (previous_char == '*' && next_char == '/') { | |
296 // EatWhitespaceAndComments will inspect pos_, which will still be on | 299 // EatWhitespaceAndComments will inspect pos_, which will still be on |
297 // the last / of the comment, so advance once more (which may also be | 300 // the last / of the comment, so advance once more (which may also be |
298 // end of input). | 301 // end of input). |
299 NextChar(); | 302 NextChar(); |
300 return true; | 303 return true; |
301 } | 304 } |
302 previous_char = next_char; | 305 previous_char = *pos_; |
306 NextChar(); | |
303 } | 307 } |
304 | 308 |
305 // If the comment is unterminated, GetNextToken will report T_END_OF_INPUT. | 309 // If the comment is unterminated, GetNextToken will report T_END_OF_INPUT. |
306 } | 310 } |
307 | 311 |
308 return false; | 312 return false; |
309 } | 313 } |
310 | 314 |
311 std::unique_ptr<Value> JSONParser::ParseNextToken() { | 315 std::unique_ptr<Value> JSONParser::ParseNextToken() { |
312 return ParseToken(GetNextToken()); | 316 return ParseToken(GetNextToken()); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 | 451 |
448 return base::MakeUnique<Value>(string.DestructiveAsString()); | 452 return base::MakeUnique<Value>(string.DestructiveAsString()); |
449 } | 453 } |
450 | 454 |
451 bool JSONParser::ConsumeStringRaw(StringBuilder* out) { | 455 bool JSONParser::ConsumeStringRaw(StringBuilder* out) { |
452 if (*pos_ != '"') { | 456 if (*pos_ != '"') { |
453 ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1); | 457 ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1); |
454 return false; | 458 return false; |
455 } | 459 } |
456 | 460 |
461 // Strings are at minimum two characters: the surrounding double quotes. | |
462 if (!CanConsume(2)) { | |
463 ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); | |
464 return false; | |
465 } | |
466 | |
457 // StringBuilder will internally build a StringPiece unless a UTF-16 | 467 // StringBuilder will internally build a StringPiece unless a UTF-16 |
458 // conversion occurs, at which point it will perform a copy into a | 468 // conversion occurs, at which point it will perform a copy into a |
459 // std::string. | 469 // std::string. |
460 StringBuilder string(NextChar()); | 470 StringBuilder string(NextChar()); |
461 | 471 |
472 // Handle the empty string case early. | |
473 if (*pos_ == '"') { | |
474 *out = std::move(string); | |
475 return true; | |
476 } | |
477 | |
462 int length = end_pos_ - start_pos_; | 478 int length = end_pos_ - start_pos_; |
463 int32_t next_char = 0; | 479 int32_t next_char = 0; |
464 | 480 |
465 while (CanConsume(1)) { | 481 // There must always be at least two characters left in the stream: the next |
482 // string character and the terminating closing quote. | |
483 while (CanConsume(2)) { | |
466 int start_index = index_; | 484 int start_index = index_; |
467 pos_ = start_pos_ + index_; // CBU8_NEXT is postcrement. | 485 pos_ = start_pos_ + index_; // CBU8_NEXT is postcrement. |
468 CBU8_NEXT(start_pos_, index_, length, next_char); | 486 CBU8_NEXT(start_pos_, index_, length, next_char); |
469 if (next_char < 0 || !IsValidCharacter(next_char)) { | 487 if (next_char < 0 || !IsValidCharacter(next_char)) { |
470 if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) { | 488 if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) { |
471 ReportError(JSONReader::JSON_UNSUPPORTED_ENCODING, 1); | 489 ReportError(JSONReader::JSON_UNSUPPORTED_ENCODING, 1); |
472 return false; | 490 return false; |
473 } | 491 } |
474 CBU8_NEXT(start_pos_, start_index, length, next_char); | 492 CBU8_NEXT(start_pos_, start_index, length, next_char); |
475 string.Convert(); | 493 string.Convert(); |
(...skipping 19 matching lines...) Expand all Loading... | |
495 // (either by combining the two characters of an encoded escape sequence, | 513 // (either by combining the two characters of an encoded escape sequence, |
496 // or with a UTF conversion), so using StringPiece isn't possible -- force | 514 // or with a UTF conversion), so using StringPiece isn't possible -- force |
497 // a conversion. | 515 // a conversion. |
498 string.Convert(); | 516 string.Convert(); |
499 | 517 |
500 if (!CanConsume(1)) { | 518 if (!CanConsume(1)) { |
501 ReportError(JSONReader::JSON_INVALID_ESCAPE, 0); | 519 ReportError(JSONReader::JSON_INVALID_ESCAPE, 0); |
502 return false; | 520 return false; |
503 } | 521 } |
504 | 522 |
505 switch (*NextChar()) { | 523 NextChar(); |
524 if (!CanConsume(1)) { | |
525 ReportError(JSONReader::JSON_INVALID_ESCAPE, 0); | |
526 return false; | |
527 } | |
528 | |
529 switch (*pos_) { | |
506 // Allowed esape sequences: | 530 // Allowed esape sequences: |
507 case 'x': { // UTF-8 sequence. | 531 case 'x': { // UTF-8 sequence. |
508 // UTF-8 \x escape sequences are not allowed in the spec, but they | 532 // UTF-8 \x escape sequences are not allowed in the spec, but they |
509 // are supported here for backwards-compatiblity with the old parser. | 533 // are supported here for backwards-compatiblity with the old parser. |
510 if (!CanConsume(2)) { | 534 if (!CanConsume(3)) { |
511 ReportError(JSONReader::JSON_INVALID_ESCAPE, 1); | 535 ReportError(JSONReader::JSON_INVALID_ESCAPE, 1); |
512 return false; | 536 return false; |
513 } | 537 } |
514 | 538 |
515 int hex_digit = 0; | 539 int hex_digit = 0; |
516 if (!HexStringToInt(StringPiece(NextChar(), 2), &hex_digit) || | 540 if (!HexStringToInt(StringPiece(NextChar(), 2), &hex_digit) || |
517 !IsValidCharacter(hex_digit)) { | 541 !IsValidCharacter(hex_digit)) { |
518 ReportError(JSONReader::JSON_INVALID_ESCAPE, -1); | 542 ReportError(JSONReader::JSON_INVALID_ESCAPE, -1); |
519 return false; | 543 return false; |
520 } | 544 } |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
770 return false; | 794 return false; |
771 | 795 |
772 return true; | 796 return true; |
773 } | 797 } |
774 | 798 |
775 std::unique_ptr<Value> JSONParser::ConsumeLiteral() { | 799 std::unique_ptr<Value> JSONParser::ConsumeLiteral() { |
776 switch (*pos_) { | 800 switch (*pos_) { |
777 case 't': { | 801 case 't': { |
778 const char kTrueLiteral[] = "true"; | 802 const char kTrueLiteral[] = "true"; |
779 const int kTrueLen = static_cast<int>(strlen(kTrueLiteral)); | 803 const int kTrueLen = static_cast<int>(strlen(kTrueLiteral)); |
780 if (!CanConsume(kTrueLen - 1) || | 804 if (!CanConsume(kTrueLen) || |
781 !StringsAreEqual(pos_, kTrueLiteral, kTrueLen)) { | 805 !StringsAreEqual(pos_, kTrueLiteral, kTrueLen)) { |
782 ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); | 806 ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); |
783 return nullptr; | 807 return nullptr; |
784 } | 808 } |
785 NextNChars(kTrueLen - 1); | 809 NextNChars(kTrueLen - 1); |
786 return base::MakeUnique<Value>(true); | 810 return base::MakeUnique<Value>(true); |
787 } | 811 } |
788 case 'f': { | 812 case 'f': { |
789 const char kFalseLiteral[] = "false"; | 813 const char kFalseLiteral[] = "false"; |
790 const int kFalseLen = static_cast<int>(strlen(kFalseLiteral)); | 814 const int kFalseLen = static_cast<int>(strlen(kFalseLiteral)); |
791 if (!CanConsume(kFalseLen - 1) || | 815 if (!CanConsume(kFalseLen) || |
792 !StringsAreEqual(pos_, kFalseLiteral, kFalseLen)) { | 816 !StringsAreEqual(pos_, kFalseLiteral, kFalseLen)) { |
793 ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); | 817 ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); |
794 return nullptr; | 818 return nullptr; |
795 } | 819 } |
796 NextNChars(kFalseLen - 1); | 820 NextNChars(kFalseLen - 1); |
797 return base::MakeUnique<Value>(false); | 821 return base::MakeUnique<Value>(false); |
798 } | 822 } |
799 case 'n': { | 823 case 'n': { |
800 const char kNullLiteral[] = "null"; | 824 const char kNullLiteral[] = "null"; |
801 const int kNullLen = static_cast<int>(strlen(kNullLiteral)); | 825 const int kNullLen = static_cast<int>(strlen(kNullLiteral)); |
802 if (!CanConsume(kNullLen - 1) || | 826 if (!CanConsume(kNullLen) || |
803 !StringsAreEqual(pos_, kNullLiteral, kNullLen)) { | 827 !StringsAreEqual(pos_, kNullLiteral, kNullLen)) { |
804 ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); | 828 ReportError(JSONReader::JSON_SYNTAX_ERROR, 1); |
805 return nullptr; | 829 return nullptr; |
806 } | 830 } |
807 NextNChars(kNullLen - 1); | 831 NextNChars(kNullLen - 1); |
808 return MakeUnique<Value>(); | 832 return MakeUnique<Value>(); |
809 } | 833 } |
810 default: | 834 default: |
811 ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1); | 835 ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1); |
812 return nullptr; | 836 return nullptr; |
(...skipping 17 matching lines...) Expand all Loading... | |
830 const std::string& description) { | 854 const std::string& description) { |
831 if (line || column) { | 855 if (line || column) { |
832 return StringPrintf("Line: %i, column: %i, %s", | 856 return StringPrintf("Line: %i, column: %i, %s", |
833 line, column, description.c_str()); | 857 line, column, description.c_str()); |
834 } | 858 } |
835 return description; | 859 return description; |
836 } | 860 } |
837 | 861 |
838 } // namespace internal | 862 } // namespace internal |
839 } // namespace base | 863 } // namespace base |
OLD | NEW |