aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/text_format.cc
diff options
context:
space:
mode:
authorGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-12-18 02:11:36 +0000
committerGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-12-18 02:11:36 +0000
commitfccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9 (patch)
tree9f2d9fe0267d96a54e541377ffeada3d0bff0d1d /src/google/protobuf/text_format.cc
parentd5cf7b55a6a1f959d1646785f63ca2b62da78079 (diff)
Massive roll-up of changes. See CHANGES.txt.
Diffstat (limited to 'src/google/protobuf/text_format.cc')
-rw-r--r--src/google/protobuf/text_format.cc156
1 files changed, 123 insertions, 33 deletions
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;