Chromium Code Reviews| 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 |