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 137cbcee2f7f1f53b04fa262b4e6b0de9da94488..1494ebd78d8ca00550af2afed357a9c2666ea2ee 100644 |
--- a/third_party/protobuf/src/google/protobuf/text_format.cc |
+++ b/third_party/protobuf/src/google/protobuf/text_format.cc |
@@ -37,6 +37,7 @@ |
#include <stdio.h> |
#include <stack> |
#include <limits> |
+#include <vector> |
#include <google/protobuf/text_format.h> |
@@ -118,8 +119,10 @@ class TextFormat::Parser::ParserImpl { |
ParserImpl(const Descriptor* root_message_type, |
io::ZeroCopyInputStream* input_stream, |
io::ErrorCollector* error_collector, |
+ TextFormat::Finder* finder, |
SingularOverwritePolicy singular_overwrite_policy) |
: error_collector_(error_collector), |
+ finder_(finder), |
tokenizer_error_collector_(this), |
tokenizer_(input_stream, &tokenizer_error_collector_), |
root_message_type_(root_message_type), |
@@ -249,7 +252,9 @@ class TextFormat::Parser::ParserImpl { |
} |
DO(Consume("]")); |
- field = reflection->FindKnownExtensionByName(field_name); |
+ field = (finder_ != NULL |
+ ? finder_->FindExtension(message, field_name) |
+ : reflection->FindKnownExtensionByName(field_name)); |
if (field == NULL) { |
ReportError("Extension \"" + field_name + "\" is not defined or " |
@@ -301,9 +306,24 @@ class TextFormat::Parser::ParserImpl { |
DO(ConsumeFieldMessage(message, reflection, field)); |
} else { |
DO(Consume(":")); |
- DO(ConsumeFieldValue(message, reflection, field)); |
+ if (field->is_repeated() && TryConsume("[")) { |
+ // Short repeated format, e.g. "foo: [1, 2, 3]" |
+ while (true) { |
+ DO(ConsumeFieldValue(message, reflection, field)); |
+ if (TryConsume("]")) { |
+ break; |
+ } |
+ DO(Consume(",")); |
+ } |
+ } else { |
+ DO(ConsumeFieldValue(message, reflection, field)); |
+ } |
} |
+ // For historical reasons, fields may optionally be separated by commas or |
+ // semicolons. |
+ TryConsume(";") || TryConsume(","); |
+ |
if (field->options().deprecated()) { |
ReportWarning("text format contains deprecated field \"" |
+ field_name + "\""); |
@@ -397,29 +417,46 @@ class TextFormat::Parser::ParserImpl { |
} |
case FieldDescriptor::CPPTYPE_BOOL: { |
- string value; |
- DO(ConsumeIdentifier(&value)); |
- |
- if (value == "true") { |
- SET_FIELD(Bool, true); |
- } else if (value == "false") { |
- SET_FIELD(Bool, false); |
+ if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { |
+ uint64 value; |
+ DO(ConsumeUnsignedInteger(&value, 1)); |
+ SET_FIELD(Bool, value); |
} else { |
- ReportError("Invalid value for boolean field \"" + field->name() |
- + "\". Value: \"" + value + "\"."); |
- return false; |
+ string value; |
+ DO(ConsumeIdentifier(&value)); |
+ if (value == "true" || value == "t") { |
+ SET_FIELD(Bool, true); |
+ } else if (value == "false" || value == "f") { |
+ SET_FIELD(Bool, false); |
+ } else { |
+ ReportError("Invalid value for boolean field \"" + field->name() |
+ + "\". Value: \"" + value + "\"."); |
+ return false; |
+ } |
} |
break; |
} |
case FieldDescriptor::CPPTYPE_ENUM: { |
string value; |
- DO(ConsumeIdentifier(&value)); |
- |
- // Find the enumeration value. |
const EnumDescriptor* enum_type = field->enum_type(); |
- const EnumValueDescriptor* enum_value |
- = enum_type->FindValueByName(value); |
+ const EnumValueDescriptor* enum_value = NULL; |
+ |
+ if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { |
+ DO(ConsumeIdentifier(&value)); |
+ // Find the enumeration value. |
+ enum_value = enum_type->FindValueByName(value); |
+ |
+ } else if (LookingAt("-") || |
+ LookingAtType(io::Tokenizer::TYPE_INTEGER)) { |
+ int64 int_value; |
+ DO(ConsumeSignedInteger(&int_value, kint32max)); |
+ value = SimpleItoa(int_value); // for error reporting |
+ enum_value = enum_type->FindValueByNumber(int_value); |
+ } else { |
+ ReportError("Expected integer or identifier."); |
+ return false; |
+ } |
if (enum_value == NULL) { |
ReportError("Unknown enumeration value of \"" + value + "\" for " |
@@ -632,6 +669,7 @@ class TextFormat::Parser::ParserImpl { |
}; |
io::ErrorCollector* error_collector_; |
+ TextFormat::Finder* finder_; |
ParserErrorCollector tokenizer_error_collector_; |
io::Tokenizer tokenizer_; |
const Descriptor* root_message_type_; |
@@ -765,9 +803,14 @@ class TextFormat::Printer::TextGenerator { |
// =========================================================================== |
+TextFormat::Finder::~Finder() { |
+} |
+ |
TextFormat::Parser::Parser() |
: error_collector_(NULL), |
- allow_partial_(false) {} |
+ finder_(NULL), |
+ allow_partial_(false) { |
+} |
TextFormat::Parser::~Parser() {} |
@@ -775,7 +818,7 @@ bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, |
Message* output) { |
output->Clear(); |
ParserImpl parser(output->GetDescriptor(), input, error_collector_, |
- ParserImpl::FORBID_SINGULAR_OVERWRITES); |
+ finder_, ParserImpl::FORBID_SINGULAR_OVERWRITES); |
return MergeUsingImpl(input, output, &parser); |
} |
@@ -788,7 +831,7 @@ bool TextFormat::Parser::ParseFromString(const string& input, |
bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, |
Message* output) { |
ParserImpl parser(output->GetDescriptor(), input, error_collector_, |
- ParserImpl::ALLOW_SINGULAR_OVERWRITES); |
+ finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES); |
return MergeUsingImpl(input, output, &parser); |
} |
@@ -818,7 +861,7 @@ bool TextFormat::Parser::ParseFieldValueFromString( |
Message* output) { |
io::ArrayInputStream input_stream(input.data(), input.size()); |
ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_, |
- ParserImpl::ALLOW_SINGULAR_OVERWRITES); |
+ finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES); |
return parser.ParseField(field, output); |
} |
@@ -853,7 +896,7 @@ TextFormat::Printer::Printer() |
TextFormat::Printer::~Printer() {} |
bool TextFormat::Printer::PrintToString(const Message& message, |
- string* output) { |
+ string* output) const { |
GOOGLE_DCHECK(output) << "output specified is NULL"; |
output->clear(); |
@@ -866,7 +909,7 @@ bool TextFormat::Printer::PrintToString(const Message& message, |
bool TextFormat::Printer::PrintUnknownFieldsToString( |
const UnknownFieldSet& unknown_fields, |
- string* output) { |
+ string* output) const { |
GOOGLE_DCHECK(output) << "output specified is NULL"; |
output->clear(); |
@@ -875,7 +918,7 @@ bool TextFormat::Printer::PrintUnknownFieldsToString( |
} |
bool TextFormat::Printer::Print(const Message& message, |
- io::ZeroCopyOutputStream* output) { |
+ io::ZeroCopyOutputStream* output) const { |
TextGenerator generator(output, initial_indent_level_); |
Print(message, generator); |
@@ -886,7 +929,7 @@ bool TextFormat::Printer::Print(const Message& message, |
bool TextFormat::Printer::PrintUnknownFields( |
const UnknownFieldSet& unknown_fields, |
- io::ZeroCopyOutputStream* output) { |
+ io::ZeroCopyOutputStream* output) const { |
TextGenerator generator(output, initial_indent_level_); |
PrintUnknownFields(unknown_fields, generator); |
@@ -896,7 +939,7 @@ bool TextFormat::Printer::PrintUnknownFields( |
} |
void TextFormat::Printer::Print(const Message& message, |
- TextGenerator& generator) { |
+ TextGenerator& generator) const { |
const Reflection* reflection = message.GetReflection(); |
vector<const FieldDescriptor*> fields; |
reflection->ListFields(message, &fields); |
@@ -910,7 +953,7 @@ void TextFormat::Printer::PrintFieldValueToString( |
const Message& message, |
const FieldDescriptor* field, |
int index, |
- string* output) { |
+ string* output) const { |
GOOGLE_DCHECK(output) << "output specified is NULL"; |
@@ -924,7 +967,7 @@ void TextFormat::Printer::PrintFieldValueToString( |
void TextFormat::Printer::PrintField(const Message& message, |
const Reflection* reflection, |
const FieldDescriptor* field, |
- TextGenerator& generator) { |
+ TextGenerator& generator) const { |
if (use_short_repeated_primitives_ && |
field->is_repeated() && |
field->cpp_type() != FieldDescriptor::CPPTYPE_STRING && |
@@ -980,10 +1023,11 @@ void TextFormat::Printer::PrintField(const Message& message, |
} |
} |
-void TextFormat::Printer::PrintShortRepeatedField(const Message& message, |
- const Reflection* reflection, |
- const FieldDescriptor* field, |
- TextGenerator& generator) { |
+void TextFormat::Printer::PrintShortRepeatedField( |
+ const Message& message, |
+ const Reflection* reflection, |
+ const FieldDescriptor* field, |
+ TextGenerator& generator) const { |
// Print primitive repeated field in short form. |
PrintFieldName(message, reflection, field, generator); |
@@ -1003,7 +1047,7 @@ void TextFormat::Printer::PrintShortRepeatedField(const Message& message, |
void TextFormat::Printer::PrintFieldName(const Message& message, |
const Reflection* reflection, |
const FieldDescriptor* field, |
- TextGenerator& generator) { |
+ TextGenerator& generator) const { |
if (field->is_extension()) { |
generator.Print("["); |
// We special-case MessageSet elements for compatibility with proto1. |
@@ -1031,7 +1075,7 @@ void TextFormat::Printer::PrintFieldValue( |
const Reflection* reflection, |
const FieldDescriptor* field, |
int index, |
- TextGenerator& generator) { |
+ TextGenerator& generator) const { |
GOOGLE_DCHECK(field->is_repeated() || (index == -1)) |
<< "Index must be -1 for non-repeated fields"; |
@@ -1143,7 +1187,7 @@ static string PaddedHex(IntType value) { |
} |
void TextFormat::Printer::PrintUnknownFields( |
- const UnknownFieldSet& unknown_fields, TextGenerator& generator) { |
+ const UnknownFieldSet& unknown_fields, TextGenerator& generator) const { |
for (int i = 0; i < unknown_fields.field_count(); i++) { |
const UnknownField& field = unknown_fields.field(i); |
string field_number = SimpleItoa(field.number()); |