OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 27 matching lines...) Expand all Loading... |
38 #include <memory> | 38 #include <memory> |
39 #ifndef _SHARED_PTR_H | 39 #ifndef _SHARED_PTR_H |
40 #include <google/protobuf/stubs/shared_ptr.h> | 40 #include <google/protobuf/stubs/shared_ptr.h> |
41 #endif | 41 #endif |
42 | 42 |
43 #include <google/protobuf/stubs/logging.h> | 43 #include <google/protobuf/stubs/logging.h> |
44 #include <google/protobuf/stubs/common.h> | 44 #include <google/protobuf/stubs/common.h> |
45 #include <google/protobuf/util/internal/object_writer.h> | 45 #include <google/protobuf/util/internal/object_writer.h> |
46 #include <google/protobuf/util/internal/json_escaping.h> | 46 #include <google/protobuf/util/internal/json_escaping.h> |
47 #include <google/protobuf/stubs/strutil.h> | 47 #include <google/protobuf/stubs/strutil.h> |
| 48 #include <google/protobuf/stubs/mathlimits.h> |
| 49 |
48 | 50 |
49 namespace google { | 51 namespace google { |
50 namespace protobuf { | 52 namespace protobuf { |
51 namespace util { | 53 namespace util { |
52 | 54 |
53 // Allow these symbols to be referenced as util::Status, util::error::* in | 55 // Allow these symbols to be referenced as util::Status, util::error::* in |
54 // this file. | 56 // this file. |
55 using util::Status; | 57 using util::Status; |
56 namespace error { | 58 namespace error { |
57 using util::error::INTERNAL; | 59 using util::error::INTERNAL; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 leftover_(), | 102 leftover_(), |
101 json_(), | 103 json_(), |
102 p_(), | 104 p_(), |
103 key_(), | 105 key_(), |
104 key_storage_(), | 106 key_storage_(), |
105 finishing_(false), | 107 finishing_(false), |
106 parsed_(), | 108 parsed_(), |
107 parsed_storage_(), | 109 parsed_storage_(), |
108 string_open_(0), | 110 string_open_(0), |
109 chunk_storage_(), | 111 chunk_storage_(), |
110 coerce_to_utf8_(false) { | 112 coerce_to_utf8_(false), |
| 113 allow_empty_null_(false), |
| 114 loose_float_number_conversion_(false) { |
111 // Initialize the stack with a single value to be parsed. | 115 // Initialize the stack with a single value to be parsed. |
112 stack_.push(VALUE); | 116 stack_.push(VALUE); |
113 } | 117 } |
114 | 118 |
115 JsonStreamParser::~JsonStreamParser() {} | 119 JsonStreamParser::~JsonStreamParser() {} |
116 | 120 |
117 | 121 |
118 util::Status JsonStreamParser::Parse(StringPiece json) { | 122 util::Status JsonStreamParser::Parse(StringPiece json) { |
119 StringPiece chunk = json; | 123 StringPiece chunk = json; |
120 // If we have leftovers from a previous chunk, append the new chunk to it | 124 // If we have leftovers from a previous chunk, append the new chunk to it |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 return ParseNumber(); | 274 return ParseNumber(); |
271 case BEGIN_TRUE: | 275 case BEGIN_TRUE: |
272 return ParseTrue(); | 276 return ParseTrue(); |
273 case BEGIN_FALSE: | 277 case BEGIN_FALSE: |
274 return ParseFalse(); | 278 return ParseFalse(); |
275 case BEGIN_NULL: | 279 case BEGIN_NULL: |
276 return ParseNull(); | 280 return ParseNull(); |
277 case UNKNOWN: | 281 case UNKNOWN: |
278 return ReportUnknown("Expected a value."); | 282 return ReportUnknown("Expected a value."); |
279 default: { | 283 default: { |
| 284 if (allow_empty_null_ && IsEmptyNullAllowed(type)) { |
| 285 return ParseEmptyNull(); |
| 286 } |
| 287 |
280 // Special case for having been cut off while parsing, wait for more data. | 288 // Special case for having been cut off while parsing, wait for more data. |
281 // This handles things like 'fals' being at the end of the string, we | 289 // This handles things like 'fals' being at the end of the string, we |
282 // don't know if the next char would be e, completing it, or something | 290 // don't know if the next char would be e, completing it, or something |
283 // else, making it invalid. | 291 // else, making it invalid. |
284 if (!finishing_ && p_.length() < false_len) { | 292 if (!finishing_ && p_.length() < false_len) { |
285 return util::Status::CANCELLED; | 293 return util::Status::CANCELLED; |
286 } | 294 } |
287 return ReportFailure("Unexpected token."); | 295 return ReportFailure("Unexpected token."); |
288 } | 296 } |
289 } | 297 } |
290 } | 298 } |
291 | 299 |
292 util::Status JsonStreamParser::ParseString() { | 300 util::Status JsonStreamParser::ParseString() { |
293 util::Status result = ParseStringHelper(); | 301 util::Status result = ParseStringHelper(); |
294 if (result.ok()) { | 302 if (result.ok()) { |
295 ow_->RenderString(key_, parsed_); | 303 ow_->RenderString(key_, parsed_); |
296 key_.clear(); | 304 key_ = StringPiece(); |
297 parsed_.clear(); | 305 parsed_ = StringPiece(); |
298 parsed_storage_.clear(); | 306 parsed_storage_.clear(); |
299 } | 307 } |
300 return result; | 308 return result; |
301 } | 309 } |
302 | 310 |
303 util::Status JsonStreamParser::ParseStringHelper() { | 311 util::Status JsonStreamParser::ParseStringHelper() { |
304 // If we haven't seen the start quote, grab it and remember it for later. | 312 // If we haven't seen the start quote, grab it and remember it for later. |
305 if (string_open_ == 0) { | 313 if (string_open_ == 0) { |
306 string_open_ = *p_.data(); | 314 string_open_ = *p_.data(); |
307 GOOGLE_DCHECK(string_open_ == '\"' || string_open_ == '\''); | 315 GOOGLE_DCHECK(string_open_ == '\"' || string_open_ == '\''); |
308 Advance(); | 316 Advance(); |
309 } | 317 } |
310 // Track where we last copied data from so we can minimize copying. | 318 // Track where we last copied data from so we can minimize copying. |
311 const char* last = p_.data(); | 319 const char* last = p_.data(); |
312 while (!p_.empty()) { | 320 while (!p_.empty()) { |
313 const char* data = p_.data(); | 321 const char* data = p_.data(); |
314 if (*data == '\\') { | 322 if (*data == '\\') { |
315 // We're about to handle an escape, copy all bytes from last to data. | 323 // We're about to handle an escape, copy all bytes from last to data. |
316 if (last < data) { | 324 if (last < data) { |
317 parsed_storage_.append(last, data - last); | 325 parsed_storage_.append(last, data - last); |
318 last = data; | |
319 } | 326 } |
320 // If we ran out of string after the \, cancel or report an error | 327 // If we ran out of string after the \, cancel or report an error |
321 // depending on if we expect more data later. | 328 // depending on if we expect more data later. |
322 if (p_.length() == 1) { | 329 if (p_.length() == 1) { |
323 if (!finishing_) { | 330 if (!finishing_) { |
324 return util::Status::CANCELLED; | 331 return util::Status::CANCELLED; |
325 } | 332 } |
326 return ReportFailure("Closing quote expected in string."); | 333 return ReportFailure("Closing quote expected in string."); |
327 } | 334 } |
328 // Parse a unicode escape if we found \u in the string. | 335 // Parse a unicode escape if we found \u in the string. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 continue; | 371 continue; |
365 } | 372 } |
366 // If we found the closing quote note it, advance past it, and return. | 373 // If we found the closing quote note it, advance past it, and return. |
367 if (*data == string_open_) { | 374 if (*data == string_open_) { |
368 // If we didn't copy anything, reuse the input buffer. | 375 // If we didn't copy anything, reuse the input buffer. |
369 if (parsed_storage_.empty()) { | 376 if (parsed_storage_.empty()) { |
370 parsed_ = StringPiece(last, data - last); | 377 parsed_ = StringPiece(last, data - last); |
371 } else { | 378 } else { |
372 if (last < data) { | 379 if (last < data) { |
373 parsed_storage_.append(last, data - last); | 380 parsed_storage_.append(last, data - last); |
374 last = data; | |
375 } | 381 } |
376 parsed_ = StringPiece(parsed_storage_); | 382 parsed_ = StringPiece(parsed_storage_); |
377 } | 383 } |
378 // Clear the quote char so next time we try to parse a string we'll | 384 // Clear the quote char so next time we try to parse a string we'll |
379 // start fresh. | 385 // start fresh. |
380 string_open_ = 0; | 386 string_open_ = 0; |
381 Advance(); | 387 Advance(); |
382 return util::Status::OK; | 388 return util::Status::OK; |
383 } | 389 } |
384 // Normal character, just advance past it. | 390 // Normal character, just advance past it. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 return util::Status::OK; | 470 return util::Status::OK; |
465 } | 471 } |
466 | 472 |
467 util::Status JsonStreamParser::ParseNumber() { | 473 util::Status JsonStreamParser::ParseNumber() { |
468 NumberResult number; | 474 NumberResult number; |
469 util::Status result = ParseNumberHelper(&number); | 475 util::Status result = ParseNumberHelper(&number); |
470 if (result.ok()) { | 476 if (result.ok()) { |
471 switch (number.type) { | 477 switch (number.type) { |
472 case NumberResult::DOUBLE: | 478 case NumberResult::DOUBLE: |
473 ow_->RenderDouble(key_, number.double_val); | 479 ow_->RenderDouble(key_, number.double_val); |
474 key_.clear(); | 480 key_ = StringPiece(); |
475 break; | 481 break; |
476 | 482 |
477 case NumberResult::INT: | 483 case NumberResult::INT: |
478 ow_->RenderInt64(key_, number.int_val); | 484 ow_->RenderInt64(key_, number.int_val); |
479 key_.clear(); | 485 key_ = StringPiece(); |
480 break; | 486 break; |
481 | 487 |
482 case NumberResult::UINT: | 488 case NumberResult::UINT: |
483 ow_->RenderUint64(key_, number.uint_val); | 489 ow_->RenderUint64(key_, number.uint_val); |
484 key_.clear(); | 490 key_ = StringPiece(); |
485 break; | 491 break; |
486 | 492 |
487 default: | 493 default: |
488 return ReportFailure("Unable to parse number."); | 494 return ReportFailure("Unable to parse number."); |
489 } | 495 } |
490 } | 496 } |
491 return result; | 497 return result; |
492 } | 498 } |
493 | 499 |
494 util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) { | 500 util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) { |
(...skipping 27 matching lines...) Expand all Loading... |
522 } | 528 } |
523 | 529 |
524 // Create a string containing just the number, so we can use safe_strtoX | 530 // Create a string containing just the number, so we can use safe_strtoX |
525 string number = p_.substr(0, index).ToString(); | 531 string number = p_.substr(0, index).ToString(); |
526 | 532 |
527 // Floating point number, parse as a double. | 533 // Floating point number, parse as a double. |
528 if (floating) { | 534 if (floating) { |
529 if (!safe_strtod(number, &result->double_val)) { | 535 if (!safe_strtod(number, &result->double_val)) { |
530 return ReportFailure("Unable to parse number."); | 536 return ReportFailure("Unable to parse number."); |
531 } | 537 } |
| 538 if (!loose_float_number_conversion_ && |
| 539 !MathLimits<double>::IsFinite(result->double_val)) { |
| 540 return ReportFailure("Number exceeds the range of double."); |
| 541 } |
532 result->type = NumberResult::DOUBLE; | 542 result->type = NumberResult::DOUBLE; |
533 p_.remove_prefix(index); | 543 p_.remove_prefix(index); |
534 return util::Status::OK; | 544 return util::Status::OK; |
535 } | 545 } |
536 | 546 |
537 // Positive non-floating point number, parse as a uint64. | 547 // Positive non-floating point number, parse as a uint64. |
538 if (!negative) { | 548 if (!negative) { |
539 // Octal/Hex numbers are not valid JSON values. | 549 // Octal/Hex numbers are not valid JSON values. |
540 if (number.length() >= 2 && number[0] == '0') { | 550 if (number.length() >= 2 && number[0] == '0') { |
541 return ReportFailure("Octal/hex numbers are not valid JSON values."); | 551 return ReportFailure("Octal/hex numbers are not valid JSON values."); |
(...skipping 16 matching lines...) Expand all Loading... |
558 } | 568 } |
559 result->type = NumberResult::INT; | 569 result->type = NumberResult::INT; |
560 p_.remove_prefix(index); | 570 p_.remove_prefix(index); |
561 return util::Status::OK; | 571 return util::Status::OK; |
562 } | 572 } |
563 | 573 |
564 util::Status JsonStreamParser::HandleBeginObject() { | 574 util::Status JsonStreamParser::HandleBeginObject() { |
565 GOOGLE_DCHECK_EQ('{', *p_.data()); | 575 GOOGLE_DCHECK_EQ('{', *p_.data()); |
566 Advance(); | 576 Advance(); |
567 ow_->StartObject(key_); | 577 ow_->StartObject(key_); |
568 key_.clear(); | 578 key_ = StringPiece(); |
569 stack_.push(ENTRY); | 579 stack_.push(ENTRY); |
570 return util::Status::OK; | 580 return util::Status::OK; |
571 } | 581 } |
572 | 582 |
573 util::Status JsonStreamParser::ParseObjectMid(TokenType type) { | 583 util::Status JsonStreamParser::ParseObjectMid(TokenType type) { |
574 if (type == UNKNOWN) { | 584 if (type == UNKNOWN) { |
575 return ReportUnknown("Expected , or } after key:value pair."); | 585 return ReportUnknown("Expected , or } after key:value pair."); |
576 } | 586 } |
577 | 587 |
578 // Object is complete, advance past the comma and render the EndObject. | 588 // Object is complete, advance past the comma and render the EndObject. |
(...skipping 29 matching lines...) Expand all Loading... |
608 // Key is a string (standard JSON), parse it and store the string. | 618 // Key is a string (standard JSON), parse it and store the string. |
609 result = ParseStringHelper(); | 619 result = ParseStringHelper(); |
610 if (result.ok()) { | 620 if (result.ok()) { |
611 key_storage_.clear(); | 621 key_storage_.clear(); |
612 if (!parsed_storage_.empty()) { | 622 if (!parsed_storage_.empty()) { |
613 parsed_storage_.swap(key_storage_); | 623 parsed_storage_.swap(key_storage_); |
614 key_ = StringPiece(key_storage_); | 624 key_ = StringPiece(key_storage_); |
615 } else { | 625 } else { |
616 key_ = parsed_; | 626 key_ = parsed_; |
617 } | 627 } |
618 parsed_.clear(); | 628 parsed_ = StringPiece(); |
619 } | 629 } |
620 } else if (type == BEGIN_KEY) { | 630 } else if (type == BEGIN_KEY) { |
621 // Key is a bare key (back compat), create a StringPiece pointing to it. | 631 // Key is a bare key (back compat), create a StringPiece pointing to it. |
622 result = ParseKey(); | 632 result = ParseKey(); |
623 } else { | 633 } else { |
624 // Unknown key type, report an error. | 634 // Unknown key type, report an error. |
625 result = ReportFailure("Expected an object key or }."); | 635 result = ReportFailure("Expected an object key or }."); |
626 } | 636 } |
627 // On success we next expect an entry mid ':' then an object mid ',' or '}' | 637 // On success we next expect an entry mid ':' then an object mid ',' or '}' |
628 if (result.ok()) { | 638 if (result.ok()) { |
(...skipping 12 matching lines...) Expand all Loading... |
641 stack_.push(VALUE); | 651 stack_.push(VALUE); |
642 return util::Status::OK; | 652 return util::Status::OK; |
643 } | 653 } |
644 return ReportFailure("Expected : between key:value pair."); | 654 return ReportFailure("Expected : between key:value pair."); |
645 } | 655 } |
646 | 656 |
647 util::Status JsonStreamParser::HandleBeginArray() { | 657 util::Status JsonStreamParser::HandleBeginArray() { |
648 GOOGLE_DCHECK_EQ('[', *p_.data()); | 658 GOOGLE_DCHECK_EQ('[', *p_.data()); |
649 Advance(); | 659 Advance(); |
650 ow_->StartList(key_); | 660 ow_->StartList(key_); |
651 key_.clear(); | 661 key_ = StringPiece(); |
652 stack_.push(ARRAY_VALUE); | 662 stack_.push(ARRAY_VALUE); |
653 return util::Status::OK; | 663 return util::Status::OK; |
654 } | 664 } |
655 | 665 |
656 util::Status JsonStreamParser::ParseArrayValue(TokenType type) { | 666 util::Status JsonStreamParser::ParseArrayValue(TokenType type) { |
657 if (type == UNKNOWN) { | 667 if (type == UNKNOWN) { |
658 return ReportUnknown("Expected a value or ] within an array."); | 668 return ReportUnknown("Expected a value or ] within an array."); |
659 } | 669 } |
660 | 670 |
661 if (type == END_ARRAY) { | 671 if (type == END_ARRAY) { |
662 ow_->EndList(); | 672 ow_->EndList(); |
663 Advance(); | 673 Advance(); |
664 return util::Status::OK; | 674 return util::Status::OK; |
665 } | 675 } |
666 | 676 |
667 // The ParseValue call may push something onto the stack so we need to make | 677 // The ParseValue call may push something onto the stack so we need to make |
668 // sure an ARRAY_MID is after it, so we push it on now. | 678 // sure an ARRAY_MID is after it, so we push it on now. Also, the parsing of |
| 679 // empty-null array value is relying on this ARRAY_MID token. |
669 stack_.push(ARRAY_MID); | 680 stack_.push(ARRAY_MID); |
670 util::Status result = ParseValue(type); | 681 util::Status result = ParseValue(type); |
671 if (result == util::Status::CANCELLED) { | 682 if (result == util::Status::CANCELLED) { |
672 // If we were cancelled, pop back off the ARRAY_MID so we don't try to | 683 // If we were cancelled, pop back off the ARRAY_MID so we don't try to |
673 // push it on again when we try over. | 684 // push it on again when we try over. |
674 stack_.pop(); | 685 stack_.pop(); |
675 } | 686 } |
676 return result; | 687 return result; |
677 } | 688 } |
678 | 689 |
(...skipping 13 matching lines...) Expand all Loading... |
692 Advance(); | 703 Advance(); |
693 stack_.push(ARRAY_VALUE); | 704 stack_.push(ARRAY_VALUE); |
694 return util::Status::OK; | 705 return util::Status::OK; |
695 } | 706 } |
696 // Illegal token after array value. | 707 // Illegal token after array value. |
697 return ReportFailure("Expected , or ] after array value."); | 708 return ReportFailure("Expected , or ] after array value."); |
698 } | 709 } |
699 | 710 |
700 util::Status JsonStreamParser::ParseTrue() { | 711 util::Status JsonStreamParser::ParseTrue() { |
701 ow_->RenderBool(key_, true); | 712 ow_->RenderBool(key_, true); |
702 key_.clear(); | 713 key_ = StringPiece(); |
703 p_.remove_prefix(true_len); | 714 p_.remove_prefix(true_len); |
704 return util::Status::OK; | 715 return util::Status::OK; |
705 } | 716 } |
706 | 717 |
707 util::Status JsonStreamParser::ParseFalse() { | 718 util::Status JsonStreamParser::ParseFalse() { |
708 ow_->RenderBool(key_, false); | 719 ow_->RenderBool(key_, false); |
709 key_.clear(); | 720 key_ = StringPiece(); |
710 p_.remove_prefix(false_len); | 721 p_.remove_prefix(false_len); |
711 return util::Status::OK; | 722 return util::Status::OK; |
712 } | 723 } |
713 | 724 |
714 util::Status JsonStreamParser::ParseNull() { | 725 util::Status JsonStreamParser::ParseNull() { |
715 ow_->RenderNull(key_); | 726 ow_->RenderNull(key_); |
716 key_.clear(); | 727 key_ = StringPiece(); |
717 p_.remove_prefix(null_len); | 728 p_.remove_prefix(null_len); |
718 return util::Status::OK; | 729 return util::Status::OK; |
719 } | 730 } |
720 | 731 |
| 732 util::Status JsonStreamParser::ParseEmptyNull() { |
| 733 ow_->RenderNull(key_); |
| 734 key_ = StringPiece(); |
| 735 return util::Status::OK; |
| 736 } |
| 737 |
| 738 bool JsonStreamParser::IsEmptyNullAllowed(TokenType type) { |
| 739 if (stack_.empty()) return false; |
| 740 return (stack_.top() == ARRAY_MID && type == VALUE_SEPARATOR) || |
| 741 stack_.top() == OBJ_MID; |
| 742 } |
| 743 |
721 util::Status JsonStreamParser::ReportFailure(StringPiece message) { | 744 util::Status JsonStreamParser::ReportFailure(StringPiece message) { |
722 static const int kContextLength = 20; | 745 static const int kContextLength = 20; |
723 const char* p_start = p_.data(); | 746 const char* p_start = p_.data(); |
724 const char* json_start = json_.data(); | 747 const char* json_start = json_.data(); |
725 const char* begin = std::max(p_start - kContextLength, json_start); | 748 const char* begin = std::max(p_start - kContextLength, json_start); |
726 const char* end = | 749 const char* end = |
727 std::min(p_start + kContextLength, json_start + json_.size()); | 750 std::min(p_start + kContextLength, json_start + json_.size()); |
728 StringPiece segment(begin, end - begin); | 751 StringPiece segment(begin, end - begin); |
729 string location(p_start - begin, ' '); | 752 string location(p_start - begin, ' '); |
730 location.push_back('^'); | 753 location.push_back('^'); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 // can't parse what we have so far. So we don't report an error and just | 834 // can't parse what we have so far. So we don't report an error and just |
812 // return UNKNOWN so we can try again later when we have more data, or if we | 835 // return UNKNOWN so we can try again later when we have more data, or if we |
813 // finish and we have leftovers. | 836 // finish and we have leftovers. |
814 return UNKNOWN; | 837 return UNKNOWN; |
815 } | 838 } |
816 | 839 |
817 } // namespace converter | 840 } // namespace converter |
818 } // namespace util | 841 } // namespace util |
819 } // namespace protobuf | 842 } // namespace protobuf |
820 } // namespace google | 843 } // namespace google |
OLD | NEW |