diff options
Diffstat (limited to 'src/google/protobuf/text_format.cc')
-rw-r--r-- | src/google/protobuf/text_format.cc | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index c0dfd53f..d49d8588 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -234,7 +234,8 @@ class TextFormat::Parser::ParserImpl { bool allow_unknown_field, bool allow_unknown_enum, bool allow_field_number, - bool allow_relaxed_whitespace) + bool allow_relaxed_whitespace, + bool allow_partial) : error_collector_(error_collector), finder_(finder), parse_info_tree_(parse_info_tree), @@ -246,6 +247,7 @@ class TextFormat::Parser::ParserImpl { allow_unknown_field_(allow_unknown_field), allow_unknown_enum_(allow_unknown_enum), allow_field_number_(allow_field_number), + allow_partial_(allow_partial), had_errors_(false) { // For backwards-compatibility with proto1, we need to allow the 'f' suffix // for floats. @@ -718,7 +720,8 @@ class TextFormat::Parser::ParserImpl { value = SimpleItoa(int_value); // for error reporting enum_value = enum_type->FindValueByNumber(int_value); } else { - ReportError("Expected integer or identifier."); + ReportError("Expected integer or identifier, got: " + + tokenizer_.current().text); return false; } @@ -831,7 +834,7 @@ class TextFormat::Parser::ParserImpl { return true; } - ReportError("Expected identifier."); + ReportError("Expected identifier, got: " + tokenizer_.current().text); return false; } @@ -851,7 +854,7 @@ class TextFormat::Parser::ParserImpl { // Returns false if the token is not of type STRING. bool ConsumeString(string* text) { if (!LookingAtType(io::Tokenizer::TYPE_STRING)) { - ReportError("Expected string."); + ReportError("Expected string, got: " + tokenizer_.current().text); return false; } @@ -869,13 +872,13 @@ class TextFormat::Parser::ParserImpl { // Returns false if the token is not of type INTEGER. bool ConsumeUnsignedInteger(uint64* value, uint64 max_value) { if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) { - ReportError("Expected integer."); + ReportError("Expected integer, got: " + tokenizer_.current().text); return false; } if (!io::Tokenizer::ParseInteger(tokenizer_.current().text, max_value, value)) { - ReportError("Integer out of range."); + ReportError("Integer out of range (" + tokenizer_.current().text + ")"); return false; } @@ -902,10 +905,14 @@ class TextFormat::Parser::ParserImpl { DO(ConsumeUnsignedInteger(&unsigned_value, max_value)); - *value = static_cast<int64>(unsigned_value); - if (negative) { - *value = -*value; + if ((static_cast<uint64>(kint64max) + 1) == unsigned_value) { + *value = kint64min; + } else { + *value = -static_cast<int64>(unsigned_value); + } + } else { + *value = static_cast<int64>(unsigned_value); } return true; @@ -915,18 +922,18 @@ class TextFormat::Parser::ParserImpl { // Accepts decimal numbers only, rejects hex or oct numbers. bool ConsumeUnsignedDecimalInteger(uint64* value, uint64 max_value) { if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) { - ReportError("Expected integer."); + ReportError("Expected integer, got: " + tokenizer_.current().text); return false; } const string& text = tokenizer_.current().text; if (IsHexNumber(text) || IsOctNumber(text)) { - ReportError("Expect a decimal number."); + ReportError("Expect a decimal number, got: " + text); return false; } if (!io::Tokenizer::ParseInteger(text, max_value, value)) { - ReportError("Integer out of range."); + ReportError("Integer out of range (" + text + ")"); return false; } @@ -971,11 +978,11 @@ class TextFormat::Parser::ParserImpl { *value = std::numeric_limits<double>::quiet_NaN(); tokenizer_.Next(); } else { - ReportError("Expected double."); + ReportError("Expected double, got: " + text); return false; } } else { - ReportError("Expected double."); + ReportError("Expected double, got: " + tokenizer_.current().text); return false; } @@ -1033,7 +1040,17 @@ class TextFormat::Parser::ParserImpl { DO(ConsumeMessageDelimiter(&sub_delimiter)); DO(ConsumeMessage(value.get(), sub_delimiter)); - value->AppendToString(serialized_value); + if (allow_partial_) { + value->AppendPartialToString(serialized_value); + } else { + if (!value->IsInitialized()) { + ReportError( + "Value of type \"" + full_type_name + + "\" stored in google.protobuf.Any has missing required fields"); + return false; + } + value->AppendToString(serialized_value); + } return true; } @@ -1098,6 +1115,7 @@ class TextFormat::Parser::ParserImpl { const bool allow_unknown_field_; const bool allow_unknown_enum_; const bool allow_field_number_; + const bool allow_partial_; bool had_errors_; }; @@ -1259,7 +1277,7 @@ bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, overwrites_policy, allow_case_insensitive_field_, allow_unknown_field_, allow_unknown_enum_, allow_field_number_, - allow_relaxed_whitespace_); + allow_relaxed_whitespace_, allow_partial_); return MergeUsingImpl(input, output, &parser); } @@ -1276,7 +1294,7 @@ bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, ParserImpl::ALLOW_SINGULAR_OVERWRITES, allow_case_insensitive_field_, allow_unknown_field_, allow_unknown_enum_, allow_field_number_, - allow_relaxed_whitespace_); + allow_relaxed_whitespace_, allow_partial_); return MergeUsingImpl(input, output, &parser); } @@ -1310,7 +1328,7 @@ bool TextFormat::Parser::ParseFieldValueFromString( ParserImpl::ALLOW_SINGULAR_OVERWRITES, allow_case_insensitive_field_, allow_unknown_field_, allow_unknown_enum_, allow_field_number_, - allow_relaxed_whitespace_); + allow_relaxed_whitespace_, allow_partial_); return parser.ParseField(field, output); } |