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(); |
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(2)) { |
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; |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after 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 |