From fccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9 Mon Sep 17 00:00:00 2001 From: "kenton@google.com" Date: Fri, 18 Dec 2009 02:11:36 +0000 Subject: Massive roll-up of changes. See CHANGES.txt. --- src/google/protobuf/text_format.cc | 156 +++++++++++++++++++++++++++++-------- 1 file changed, 123 insertions(+), 33 deletions(-) (limited to 'src/google/protobuf/text_format.cc') diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index cf754024..137cbcee 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -54,21 +54,19 @@ namespace protobuf { string Message::DebugString() const { string debug_string; - io::StringOutputStream output_stream(&debug_string); - TextFormat::Print(*this, &output_stream); + TextFormat::PrintToString(*this, &debug_string); return debug_string; } string Message::ShortDebugString() const { string debug_string; - io::StringOutputStream output_stream(&debug_string); TextFormat::Printer printer; printer.SetSingleLineMode(true); - printer.Print(*this, &output_stream); + printer.PrintToString(*this, &debug_string); // Single line mode currently might have an extra space at the end. if (debug_string.size() > 0 && debug_string[debug_string.size() - 1] == ' ') { @@ -78,10 +76,22 @@ string Message::ShortDebugString() const { return debug_string; } +string Message::Utf8DebugString() const { + string debug_string; + + TextFormat::Printer printer; + printer.SetUseUtf8StringEscaping(true); + + printer.PrintToString(*this, &debug_string); + + return debug_string; +} + void Message::PrintDebugString() const { printf("%s", DebugString().c_str()); } + // =========================================================================== // Internal class for parsing an ASCII representation of a Protocol Message. // This class makes use of the Protocol Message compiler's tokenizer found @@ -170,6 +180,23 @@ class TextFormat::Parser::ParserImpl { } } + void ReportWarning(int line, int col, const string& message) { + if (error_collector_ == NULL) { + if (line >= 0) { + GOOGLE_LOG(WARNING) << "Warning parsing text-format " + << root_message_type_->full_name() + << ": " << (line + 1) << ":" + << (col + 1) << ": " << message; + } else { + GOOGLE_LOG(WARNING) << "Warning parsing text-format " + << root_message_type_->full_name() + << ": " << message; + } + } else { + error_collector_->AddWarning(line, col, message); + } + } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserImpl); @@ -180,6 +207,13 @@ class TextFormat::Parser::ParserImpl { message); } + // Reports a warning with the given message with information indicating + // the position (as derived from the current token). + void ReportWarning(const string& message) { + ReportWarning(tokenizer_.current().line, tokenizer_.current().column, + message); + } + // Consumes the specified message with the given starting delimeter. // This method checks to see that the end delimeter at the conclusion of // the consumption matches the starting delimeter passed in here. @@ -270,6 +304,11 @@ class TextFormat::Parser::ParserImpl { DO(ConsumeFieldValue(message, reflection, field)); } + if (field->options().deprecated()) { + ReportWarning("text format contains deprecated field \"" + + field_name + "\""); + } + return true; } @@ -583,6 +622,10 @@ class TextFormat::Parser::ParserImpl { parser_->ReportError(line, column, message); } + virtual void AddWarning(int line, int column, const string& message) { + parser_->ReportWarning(line, column, message); + } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector); TextFormat::Parser::ParserImpl* parser_; @@ -644,12 +687,16 @@ class TextFormat::Printer::TextGenerator { // Print text to the output stream. void Print(const string& str) { - Print(str.c_str()); + Print(str.data(), str.size()); } // Print text to the output stream. void Print(const char* text) { - int size = strlen(text); + Print(text, strlen(text)); + } + + // Print text to the output stream. + void Print(const char* text, int size) { int pos = 0; // The number of bytes we've written so far. for (int i = 0; i < size; i++) { @@ -799,7 +846,9 @@ bool TextFormat::Parser::ParseFieldValueFromString( TextFormat::Printer::Printer() : initial_indent_level_(0), - single_line_mode_(false) {} + single_line_mode_(false), + use_short_repeated_primitives_(false), + utf8_string_escaping_(false) {} TextFormat::Printer::~Printer() {} @@ -876,6 +925,14 @@ void TextFormat::Printer::PrintField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, TextGenerator& generator) { + if (use_short_repeated_primitives_ && + field->is_repeated() && + field->cpp_type() != FieldDescriptor::CPPTYPE_STRING && + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + PrintShortRepeatedField(message, reflection, field, generator); + return; + } + int count = 0; if (field->is_repeated()) { @@ -885,26 +942,7 @@ void TextFormat::Printer::PrintField(const Message& message, } for (int j = 0; j < count; ++j) { - if (field->is_extension()) { - generator.Print("["); - // We special-case MessageSet elements for compatibility with proto1. - if (field->containing_type()->options().message_set_wire_format() - && field->type() == FieldDescriptor::TYPE_MESSAGE - && field->is_optional() - && field->extension_scope() == field->message_type()) { - generator.Print(field->message_type()->full_name()); - } else { - generator.Print(field->full_name()); - } - generator.Print("]"); - } else { - if (field->type() == FieldDescriptor::TYPE_GROUP) { - // Groups must be serialized with their original capitalization. - generator.Print(field->message_type()->name()); - } else { - generator.Print(field->name()); - } - } + PrintFieldName(message, reflection, field, generator); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (single_line_mode_) { @@ -926,16 +964,64 @@ void TextFormat::Printer::PrintField(const Message& message, PrintFieldValue(message, reflection, field, field_index, generator); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (!single_line_mode_) { + if (single_line_mode_) { + generator.Print("} "); + } else { generator.Outdent(); + generator.Print("}\n"); + } + } else { + if (single_line_mode_) { + generator.Print(" "); + } else { + generator.Print("\n"); } - generator.Print("}"); } + } +} - if (single_line_mode_) { - generator.Print(" "); +void TextFormat::Printer::PrintShortRepeatedField(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator& generator) { + // Print primitive repeated field in short form. + PrintFieldName(message, reflection, field, generator); + + int size = reflection->FieldSize(message, field); + generator.Print(": ["); + for (int i = 0; i < size; i++) { + if (i > 0) generator.Print(", "); + PrintFieldValue(message, reflection, field, i, generator); + } + if (single_line_mode_) { + generator.Print("] "); + } else { + generator.Print("]\n"); + } +} + +void TextFormat::Printer::PrintFieldName(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator& generator) { + if (field->is_extension()) { + generator.Print("["); + // We special-case MessageSet elements for compatibility with proto1. + if (field->containing_type()->options().message_set_wire_format() + && field->type() == FieldDescriptor::TYPE_MESSAGE + && field->is_optional() + && field->extension_scope() == field->message_type()) { + generator.Print(field->message_type()->full_name()); + } else { + generator.Print(field->full_name()); + } + generator.Print("]"); + } else { + if (field->type() == FieldDescriptor::TYPE_GROUP) { + // Groups must be serialized with their original capitalization. + generator.Print(field->message_type()->name()); } else { - generator.Print("\n"); + generator.Print(field->name()); } } } @@ -973,7 +1059,11 @@ void TextFormat::Printer::PrintFieldValue( reflection->GetStringReference(message, field, &scratch); generator.Print("\""); - generator.Print(CEscape(value)); + if (utf8_string_escaping_) { + generator.Print(strings::Utf8SafeCEscape(value)); + } else { + generator.Print(CEscape(value)); + } generator.Print("\""); break; -- cgit v1.2.3