Index: third_party/protobuf/src/google/protobuf/text_format.cc |
diff --git a/third_party/protobuf/src/google/protobuf/text_format.cc b/third_party/protobuf/src/google/protobuf/text_format.cc |
index c0dfd53fd7b0c7360f3fada07cc23207f36723e9..e3d908ecddea85e5d51636a41e0147de81825c18 100644 |
--- a/third_party/protobuf/src/google/protobuf/text_format.cc |
+++ b/third_party/protobuf/src/google/protobuf/text_format.cc |
@@ -154,7 +154,7 @@ TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested( |
const FieldDescriptor* field) { |
// Owned by us in the map. |
TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree(); |
- vector<TextFormat::ParseInfoTree*>* trees = &nested_[field]; |
+ std::vector<TextFormat::ParseInfoTree*>* trees = &nested_[field]; |
GOOGLE_CHECK(trees); |
trees->push_back(instance); |
return instance; |
@@ -177,7 +177,7 @@ TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation( |
CheckFieldIndex(field, index); |
if (index == -1) { index = 0; } |
- const vector<TextFormat::ParseLocation>* locations = |
+ const std::vector<TextFormat::ParseLocation>* locations = |
FindOrNull(locations_, field); |
if (locations == NULL || index >= locations->size()) { |
return TextFormat::ParseLocation(); |
@@ -191,7 +191,8 @@ TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( |
CheckFieldIndex(field, index); |
if (index == -1) { index = 0; } |
- const vector<TextFormat::ParseInfoTree*>* trees = FindOrNull(nested_, field); |
+ const std::vector<TextFormat::ParseInfoTree*>* trees = |
+ FindOrNull(nested_, field); |
if (trees == NULL || index >= trees->size()) { |
return NULL; |
} |
@@ -234,7 +235,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 +248,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. |
@@ -391,6 +394,16 @@ class TextFormat::Parser::ParserImpl { |
DO(ConsumeAnyValue(full_type_name, |
message->GetDescriptor()->file()->pool(), |
&serialized_value)); |
+ if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) { |
+ // Fail if any_type_url_field has already been specified. |
+ if ((!any_type_url_field->is_repeated() && |
+ reflection->HasField(*message, any_type_url_field)) || |
+ (!any_value_field->is_repeated() && |
+ reflection->HasField(*message, any_value_field))) { |
+ ReportError("Non-repeated Any specified multiple times."); |
+ return false; |
+ } |
+ } |
reflection->SetString( |
message, any_type_url_field, |
string(prefix + full_type_name)); |
@@ -506,32 +519,42 @@ class TextFormat::Parser::ParserImpl { |
// Perform special handling for embedded message types. |
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
// ':' is optional here. |
- TryConsume(":"); |
+ bool consumed_semicolon = TryConsume(":"); |
+ if (consumed_semicolon && field->options().weak() && LookingAtType(io::Tokenizer::TYPE_STRING)) { |
+ // we are getting a bytes string for a weak field. |
+ string tmp; |
+ DO(ConsumeString(&tmp)); |
+ reflection->MutableMessage(message, field)->ParseFromString(tmp); |
+ goto label_skip_parsing; |
+ } |
} else { |
// ':' is required here. |
DO(Consume(":")); |
} |
if (field->is_repeated() && TryConsume("[")) { |
- // Short repeated format, e.g. "foo: [1, 2, 3]" |
- while (true) { |
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- // Perform special handling for embedded message types. |
- DO(ConsumeFieldMessage(message, reflection, field)); |
- } else { |
- DO(ConsumeFieldValue(message, reflection, field)); |
- } |
- if (TryConsume("]")) { |
- break; |
+ // Short repeated format, e.g. "foo: [1, 2, 3]". |
+ if (!TryConsume("]")) { |
+ // "foo: []" is treated as empty. |
+ while (true) { |
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
+ // Perform special handling for embedded message types. |
+ DO(ConsumeFieldMessage(message, reflection, field)); |
+ } else { |
+ DO(ConsumeFieldValue(message, reflection, field)); |
+ } |
+ if (TryConsume("]")) { |
+ break; |
+ } |
+ DO(Consume(",")); |
} |
- DO(Consume(",")); |
} |
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
DO(ConsumeFieldMessage(message, reflection, field)); |
} else { |
DO(ConsumeFieldValue(message, reflection, field)); |
} |
- |
+label_skip_parsing: |
// For historical reasons, fields may optionally be separated by commas or |
// semicolons. |
TryConsume(";") || TryConsume(","); |
@@ -718,7 +741,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; |
} |
@@ -756,6 +780,20 @@ class TextFormat::Parser::ParserImpl { |
} |
return true; |
} |
+ if (TryConsume("[")) { |
+ while (true) { |
+ if (!LookingAt("{") && !LookingAt("<")) { |
+ DO(SkipFieldValue()); |
+ } else { |
+ DO(SkipFieldMessage()); |
+ } |
+ if (TryConsume("]")) { |
+ break; |
+ } |
+ DO(Consume(",")); |
+ } |
+ return true; |
+ } |
// Possible field values other than string: |
// 12345 => TYPE_INTEGER |
// -12345 => TYPE_SYMBOL + TYPE_INTEGER |
@@ -831,7 +869,7 @@ class TextFormat::Parser::ParserImpl { |
return true; |
} |
- ReportError("Expected identifier."); |
+ ReportError("Expected identifier, got: " + tokenizer_.current().text); |
return false; |
} |
@@ -851,7 +889,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 +907,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 +940,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 +957,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 +1013,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 +1075,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 +1150,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 +1312,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 +1329,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); |
} |
@@ -1291,7 +1344,7 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* /* input */, |
ParserImpl* parser_impl) { |
if (!parser_impl->Parse(output)) return false; |
if (!allow_partial_ && !output->IsInitialized()) { |
- vector<string> missing_fields; |
+ std::vector<string> missing_fields; |
output->FindInitializationErrors(&missing_fields); |
parser_impl->ReportError(-1, 0, "Message missing required fields: " + |
Join(missing_fields, ", ")); |
@@ -1310,7 +1363,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); |
} |
@@ -1565,7 +1618,7 @@ void TextFormat::Printer::Print(const Message& message, |
PrintAny(message, generator)) { |
return; |
} |
- vector<const FieldDescriptor*> fields; |
+ std::vector<const FieldDescriptor*> fields; |
reflection->ListFields(message, &fields); |
if (print_message_fields_in_index_order_) { |
std::sort(fields.begin(), fields.end(), FieldIndexSorter()); |