aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/text_format.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/text_format.cc')
-rw-r--r--src/google/protobuf/text_format.cc581
1 files changed, 404 insertions, 177 deletions
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 04c887e0..1ebbdf86 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -42,20 +42,21 @@
#include <google/protobuf/text_format.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/any.h>
#include <google/protobuf/io/strtod.h>
#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/any.h>
-#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/stubs/strutil.h>
+
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>
@@ -364,7 +365,7 @@ class TextFormat::Parser::ParserImpl {
const Descriptor* descriptor = message->GetDescriptor();
string field_name;
-
+ bool reserved_field = false;
const FieldDescriptor* field = NULL;
int start_line = tokenizer_.current().line;
int start_column = tokenizer_.current().column;
@@ -426,6 +427,8 @@ class TextFormat::Parser::ParserImpl {
if (allow_field_number_ && safe_strto32(field_name, &field_number)) {
if (descriptor->IsExtensionNumber(field_number)) {
field = reflection->FindKnownExtensionByNumber(field_number);
+ } else if (descriptor->IsReservedNumber(field_number)) {
+ reserved_field = true;
} else {
field = descriptor->FindFieldByNumber(field_number);
}
@@ -454,9 +457,13 @@ class TextFormat::Parser::ParserImpl {
LowerString(&lower_field_name);
field = descriptor->FindFieldByLowercaseName(lower_field_name);
}
+
+ if (field == NULL) {
+ reserved_field = descriptor->IsReservedName(field_name);
+ }
}
- if (field == NULL) {
+ if (field == NULL && !reserved_field) {
if (!allow_unknown_field_) {
ReportError("Message type \"" + descriptor->full_name() +
"\" has no field named \"" + field_name + "\".");
@@ -468,9 +475,10 @@ class TextFormat::Parser::ParserImpl {
}
}
- // Skips unknown field.
+ // Skips unknown or reserved fields.
if (field == NULL) {
- GOOGLE_CHECK(allow_unknown_field_);
+ GOOGLE_CHECK(allow_unknown_field_ || reserved_field);
+
// Try to guess the type of this field.
// If this field is not a message, there should be a ":" between the
// field name and the field value and also the field value should not
@@ -1147,7 +1155,8 @@ label_skip_parsing:
// ===========================================================================
// Internal class for writing text to the io::ZeroCopyOutputStream. Adapted
// from the Printer found in //google/protobuf/io/printer.h
-class TextFormat::Printer::TextGenerator {
+class TextFormat::Printer::TextGenerator
+ : public TextFormat::BaseTextGenerator {
public:
explicit TextGenerator(io::ZeroCopyOutputStream* output,
int initial_indent_level)
@@ -1156,9 +1165,8 @@ class TextFormat::Printer::TextGenerator {
buffer_size_(0),
at_start_of_line_(true),
failed_(false),
- indent_(""),
+ indent_level_(initial_indent_level),
initial_indent_level_(initial_indent_level) {
- indent_.resize(initial_indent_level_ * 2, ' ');
}
~TextGenerator() {
@@ -1173,50 +1181,45 @@ class TextFormat::Printer::TextGenerator {
// inserted at the beginning of each line of text. Indent() may be called
// multiple times to produce deeper indents.
void Indent() {
- indent_ += " ";
+ ++indent_level_;
}
// Reduces the current indent level by two spaces, or crashes if the indent
// level is zero.
void Outdent() {
- if (indent_.empty() ||
- indent_.size() < initial_indent_level_ * 2) {
+ if (indent_level_ == 0 ||
+ indent_level_ < initial_indent_level_) {
GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
return;
}
- indent_.resize(indent_.size() - 2);
- }
-
- // Print text to the output stream.
- void Print(const string& str) {
- Print(str.data(), str.size());
- }
-
- // Print text to the output stream.
- void Print(const char* text) {
- Print(text, strlen(text));
+ --indent_level_;
}
// Print text to the output stream.
void Print(const char* text, size_t size) {
- size_t pos = 0; // The number of bytes we've written so far.
-
- for (size_t i = 0; i < size; i++) {
- if (text[i] == '\n') {
- // Saw newline. If there is more text, we may need to insert an indent
- // here. So, write what we have so far, including the '\n'.
- Write(text + pos, i - pos + 1);
- pos = i + 1;
-
- // Setting this true will cause the next Write() to insert an indent
- // first.
+ if (indent_level_ > 0) {
+ size_t pos = 0; // The number of bytes we've written so far.
+ for (size_t i = 0; i < size; i++) {
+ if (text[i] == '\n') {
+ // Saw newline. If there is more text, we may need to insert an
+ // indent here. So, write what we have so far, including the '\n'.
+ Write(text + pos, i - pos + 1);
+ pos = i + 1;
+
+ // Setting this true will cause the next Write() to insert an indent
+ // first.
+ at_start_of_line_ = true;
+ }
+ }
+ // Write the rest.
+ Write(text + pos, size - pos);
+ } else {
+ Write(text, size);
+ if (text[size - 1] == '\n') {
at_start_of_line_ = true;
}
}
-
- // Write the rest.
- Write(text + pos, size - pos);
}
// True if any write to the underlying stream failed. (We don't just
@@ -1234,7 +1237,7 @@ class TextFormat::Printer::TextGenerator {
if (at_start_of_line_) {
// Insert an indent.
at_start_of_line_ = false;
- Write(indent_.data(), indent_.size());
+ WriteIndent();
if (failed_) return;
}
@@ -1256,13 +1259,35 @@ class TextFormat::Printer::TextGenerator {
buffer_size_ -= size;
}
+ void WriteIndent() {
+ if (indent_level_ == 0) { return; }
+ GOOGLE_DCHECK(!failed_);
+ int size = 2 * indent_level_;
+
+ while (size > buffer_size_) {
+ // Data exceeds space in the buffer. Write what we can and request a new
+ // buffer.
+ memset(buffer_, ' ', buffer_size_);
+ size -= buffer_size_;
+ void* void_buffer;
+ failed_ = !output_->Next(&void_buffer, &buffer_size_);
+ if (failed_) return;
+ buffer_ = reinterpret_cast<char*>(void_buffer);
+ }
+
+ // Buffer is big enough to receive the data; copy it.
+ memset(buffer_, ' ', size);
+ buffer_ += size;
+ buffer_size_ -= size;
+ }
+
io::ZeroCopyOutputStream* const output_;
char* buffer_;
int buffer_size_;
bool at_start_of_line_;
bool failed_;
- string indent_;
+ int indent_level_;
int initial_indent_level_;
};
@@ -1380,90 +1405,272 @@ bool TextFormat::Parser::ParseFieldValueFromString(
// ===========================================================================
-// The default implementation for FieldValuePrinter. The base class just
-// does simple formatting. That way, deriving classes could decide to fallback
-// to that behavior.
+TextFormat::BaseTextGenerator::~BaseTextGenerator() {}
+
+namespace {
+
+// A BaseTextGenerator that writes to a string.
+class StringBaseTextGenerator : public TextFormat::BaseTextGenerator {
+ public:
+ void Print(const char* text, size_t size) { output_.append(text, size); }
+
+#if LANG_CXX11
+ string Consume() && { return std::move(output_); }
+#else // !LANG_CXX11
+ const string& Get() { return output_; }
+#endif // LANG_CXX11
+
+ private:
+ string output_;
+};
+
+} // namespace
+
+// The default implementation for FieldValuePrinter. We just delegate the
+// implementation to the default FastFieldValuePrinter to avoid duplicating the
+// logic.
TextFormat::FieldValuePrinter::FieldValuePrinter() {}
TextFormat::FieldValuePrinter::~FieldValuePrinter() {}
+
+#if LANG_CXX11
+#define FORWARD_IMPL(fn, ...) \
+ StringBaseTextGenerator generator; \
+ delegate_.fn(__VA_ARGS__, &generator); \
+ return std::move(generator).Consume()
+#else // !LANG_CXX11
+#define FORWARD_IMPL(fn, ...) \
+ StringBaseTextGenerator generator; \
+ delegate_.fn(__VA_ARGS__, &generator); \
+ return generator.Get()
+#endif // LANG_CXX11
+
string TextFormat::FieldValuePrinter::PrintBool(bool val) const {
- return val ? "true" : "false";
+ FORWARD_IMPL(PrintBool, val);
}
string TextFormat::FieldValuePrinter::PrintInt32(int32 val) const {
- return SimpleItoa(val);
+ FORWARD_IMPL(PrintInt32, val);
}
string TextFormat::FieldValuePrinter::PrintUInt32(uint32 val) const {
- return SimpleItoa(val);
+ FORWARD_IMPL(PrintUInt32, val);
}
string TextFormat::FieldValuePrinter::PrintInt64(int64 val) const {
- return SimpleItoa(val);
+ FORWARD_IMPL(PrintInt64, val);
}
string TextFormat::FieldValuePrinter::PrintUInt64(uint64 val) const {
- return SimpleItoa(val);
+ FORWARD_IMPL(PrintUInt64, val);
}
string TextFormat::FieldValuePrinter::PrintFloat(float val) const {
- return SimpleFtoa(val);
+ FORWARD_IMPL(PrintFloat, val);
}
string TextFormat::FieldValuePrinter::PrintDouble(double val) const {
- return SimpleDtoa(val);
+ FORWARD_IMPL(PrintDouble, val);
}
string TextFormat::FieldValuePrinter::PrintString(const string& val) const {
- string printed("\"");
- CEscapeAndAppend(val, &printed);
- printed.push_back('\"');
- return printed;
+ FORWARD_IMPL(PrintString, val);
}
string TextFormat::FieldValuePrinter::PrintBytes(const string& val) const {
return PrintString(val);
}
string TextFormat::FieldValuePrinter::PrintEnum(int32 val,
const string& name) const {
- return name;
+ FORWARD_IMPL(PrintEnum, val, name);
}
string TextFormat::FieldValuePrinter::PrintFieldName(
const Message& message,
const Reflection* reflection,
const FieldDescriptor* field) const {
- if (field->is_extension()) {
- // 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()) {
- return StrCat("[", field->message_type()->full_name(), "]");
- } else {
- return StrCat("[", field->full_name(), "]");
- }
- } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
- // Groups must be serialized with their original capitalization.
- return field->message_type()->name();
- } else {
- return field->name();
- }
+ FORWARD_IMPL(PrintFieldName, message, reflection, field);
}
string TextFormat::FieldValuePrinter::PrintMessageStart(
const Message& message,
int field_index,
int field_count,
bool single_line_mode) const {
- return single_line_mode ? " { " : " {\n";
+ FORWARD_IMPL(PrintMessageStart, message, field_index, field_count,
+ single_line_mode);
}
string TextFormat::FieldValuePrinter::PrintMessageEnd(
const Message& message,
int field_index,
int field_count,
bool single_line_mode) const {
- return single_line_mode ? "} " : "}\n";
+ FORWARD_IMPL(PrintMessageEnd, message, field_index, field_count,
+ single_line_mode);
+}
+#undef FORWARD_IMPL
+
+TextFormat::FastFieldValuePrinter::FastFieldValuePrinter() {}
+TextFormat::FastFieldValuePrinter::~FastFieldValuePrinter() {}
+void TextFormat::FastFieldValuePrinter::PrintBool(
+ bool val, BaseTextGenerator* generator) const {
+ if (val) {
+ generator->PrintLiteral("true");
+ } else {
+ generator->PrintLiteral("false");
+ }
+}
+void TextFormat::FastFieldValuePrinter::PrintInt32(
+ int32 val, BaseTextGenerator* generator) const {
+ generator->PrintString(SimpleItoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintUInt32(
+ uint32 val, BaseTextGenerator* generator) const {
+ generator->PrintString(SimpleItoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintInt64(
+ int64 val, BaseTextGenerator* generator) const {
+ generator->PrintString(SimpleItoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintUInt64(
+ uint64 val, BaseTextGenerator* generator) const {
+ generator->PrintString(SimpleItoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintFloat(
+ float val, BaseTextGenerator* generator) const {
+ generator->PrintString(SimpleFtoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintDouble(
+ double val, BaseTextGenerator* generator) const {
+ generator->PrintString(SimpleDtoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintEnum(
+ int32 val, const string& name, BaseTextGenerator* generator) const {
+ generator->PrintString(name);
+}
+
+void TextFormat::FastFieldValuePrinter::PrintString(
+ const string& val, BaseTextGenerator* generator) const {
+ generator->PrintLiteral("\"");
+ generator->PrintString(CEscape(val));
+ generator->PrintLiteral("\"");
+}
+void TextFormat::FastFieldValuePrinter::PrintBytes(
+ const string& val, BaseTextGenerator* generator) const {
+ PrintString(val, generator);
+}
+void TextFormat::FastFieldValuePrinter::PrintFieldName(
+ const Message& message, const Reflection* reflection,
+ const FieldDescriptor* field, BaseTextGenerator* generator) const {
+ if (field->is_extension()) {
+ generator->PrintLiteral("[");
+ // 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->PrintString(field->message_type()->full_name());
+ } else {
+ generator->PrintString(field->full_name());
+ }
+ generator->PrintLiteral("]");
+ } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ // Groups must be serialized with their original capitalization.
+ generator->PrintString(field->message_type()->name());
+ } else {
+ generator->PrintString(field->name());
+ }
+}
+void TextFormat::FastFieldValuePrinter::PrintMessageStart(
+ const Message& message, int field_index, int field_count,
+ bool single_line_mode, BaseTextGenerator* generator) const {
+ if (single_line_mode) {
+ generator->PrintLiteral(" { ");
+ } else {
+ generator->PrintLiteral(" {\n");
+ }
+}
+void TextFormat::FastFieldValuePrinter::PrintMessageEnd(
+ const Message& message, int field_index, int field_count,
+ bool single_line_mode, BaseTextGenerator* generator) const {
+ if (single_line_mode) {
+ generator->PrintLiteral("} ");
+ } else {
+ generator->PrintLiteral("}\n");
+ }
}
namespace {
+
+// A legacy compatibility wrapper. Takes ownership of the delegate.
+class FieldValuePrinterWrapper : public TextFormat::FastFieldValuePrinter {
+ public:
+ explicit FieldValuePrinterWrapper(
+ const TextFormat::FieldValuePrinter* delegate)
+ : delegate_(delegate) {}
+
+ void SetDelegate(const TextFormat::FieldValuePrinter* delegate) {
+ delegate_.reset(delegate);
+ }
+
+ void PrintBool(bool val, TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintBool(val));
+ }
+ void PrintInt32(int32 val, TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintInt32(val));
+ }
+ void PrintUInt32(uint32 val, TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintUInt32(val));
+ }
+ void PrintInt64(int64 val, TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintInt64(val));
+ }
+ void PrintUInt64(uint64 val, TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintUInt64(val));
+ }
+ void PrintFloat(float val, TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintFloat(val));
+ }
+ void PrintDouble(double val, TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintDouble(val));
+ }
+ void PrintString(const string& val,
+ TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintString(val));
+ }
+ void PrintBytes(const string& val,
+ TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintBytes(val));
+ }
+ void PrintEnum(int32 val, const string& name,
+ TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintEnum(val, name));
+ }
+ void PrintFieldName(const Message& message, const Reflection* reflection,
+ const FieldDescriptor* field,
+ TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(
+ delegate_->PrintFieldName(message, reflection, field));
+ }
+ void PrintMessageStart(const Message& message, int field_index,
+ int field_count, bool single_line_mode,
+ TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintMessageStart(
+ message, field_index, field_count, single_line_mode));
+ }
+ void PrintMessageEnd(const Message& message, int field_index, int field_count,
+ bool single_line_mode,
+ TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintString(delegate_->PrintMessageEnd(
+ message, field_index, field_count, single_line_mode));
+ }
+
+ private:
+ google::protobuf::scoped_ptr<const TextFormat::FieldValuePrinter> delegate_;
+};
+
// Our own specialization: for UTF8 escaped strings.
-class FieldValuePrinterUtf8Escaping : public TextFormat::FieldValuePrinter {
+class FastFieldValuePrinterUtf8Escaping
+ : public TextFormat::FastFieldValuePrinter {
public:
- virtual string PrintString(const string& val) const {
- return StrCat("\"", strings::Utf8SafeCEscape(val), "\"");
+ void PrintString(const string& val,
+ TextFormat::BaseTextGenerator* generator) const {
+ generator->PrintLiteral("\"");
+ generator->PrintString(strings::Utf8SafeCEscape(val));
+ generator->PrintLiteral("\"");
}
- virtual string PrintBytes(const string& val) const {
- return TextFormat::FieldValuePrinter::PrintString(val);
+ void PrintBytes(const string& val,
+ TextFormat::BaseTextGenerator* generator) const {
+ return FastFieldValuePrinter::PrintString(val, generator);
}
};
@@ -1486,19 +1693,39 @@ TextFormat::Printer::~Printer() {
}
void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) {
- SetDefaultFieldValuePrinter(as_utf8
- ? new FieldValuePrinterUtf8Escaping()
- : new FieldValuePrinter());
+ SetDefaultFieldValuePrinter(as_utf8 ? new FastFieldValuePrinterUtf8Escaping()
+ : new FastFieldValuePrinter());
}
void TextFormat::Printer::SetDefaultFieldValuePrinter(
const FieldValuePrinter* printer) {
+ default_field_value_printer_.reset(new FieldValuePrinterWrapper(printer));
+}
+
+void TextFormat::Printer::SetDefaultFieldValuePrinter(
+ const FastFieldValuePrinter* printer) {
default_field_value_printer_.reset(printer);
}
bool TextFormat::Printer::RegisterFieldValuePrinter(
const FieldDescriptor* field,
const FieldValuePrinter* printer) {
+ if (field == NULL || printer == NULL) {
+ return false;
+ }
+ FieldValuePrinterWrapper* const wrapper =
+ new FieldValuePrinterWrapper(NULL);
+ if (custom_printers_.insert(std::make_pair(field, wrapper)).second) {
+ wrapper->SetDelegate(printer);
+ return true;
+ } else {
+ delete wrapper;
+ return false;
+ }
+}
+
+bool TextFormat::Printer::RegisterFieldValuePrinter(
+ const FieldDescriptor* field, const FastFieldValuePrinter* printer) {
return field != NULL && printer != NULL &&
custom_printers_.insert(std::make_pair(field, printer)).second;
}
@@ -1527,7 +1754,7 @@ bool TextFormat::Printer::Print(const Message& message,
io::ZeroCopyOutputStream* output) const {
TextGenerator generator(output, initial_indent_level_);
- Print(message, generator);
+ Print(message, &generator);
// Output false if the generator failed internally.
return !generator.failed();
@@ -1538,7 +1765,7 @@ bool TextFormat::Printer::PrintUnknownFields(
io::ZeroCopyOutputStream* output) const {
TextGenerator generator(output, initial_indent_level_);
- PrintUnknownFields(unknown_fields, generator);
+ PrintUnknownFields(unknown_fields, &generator);
// Output false if the generator failed internally.
return !generator.failed();
@@ -1556,7 +1783,7 @@ struct FieldIndexSorter {
} // namespace
bool TextFormat::Printer::PrintAny(const Message& message,
- TextGenerator& generator) const {
+ TextGenerator* generator) const {
const FieldDescriptor* type_url_field;
const FieldDescriptor* value_field;
if (!internal::GetAnyFieldDescriptors(message, &type_url_field,
@@ -1589,20 +1816,21 @@ bool TextFormat::Printer::PrintAny(const Message& message,
GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents";
return false;
}
- generator.Print(StrCat("[", type_url, "]"));
- const FieldValuePrinter* printer = FindWithDefault(
+ generator->PrintLiteral("[");
+ generator->PrintString(type_url);
+ generator->PrintLiteral("]");
+ const FastFieldValuePrinter* printer = FindWithDefault(
custom_printers_, value_field, default_field_value_printer_.get());
- generator.Print(
- printer->PrintMessageStart(message, -1, 0, single_line_mode_));
- generator.Indent();
+ printer->PrintMessageStart(message, -1, 0, single_line_mode_, generator);
+ generator->Indent();
Print(*value_message, generator);
- generator.Outdent();
- generator.Print(printer->PrintMessageEnd(message, -1, 0, single_line_mode_));
+ generator->Outdent();
+ printer->PrintMessageEnd(message, -1, 0, single_line_mode_, generator);
return true;
}
void TextFormat::Printer::Print(const Message& message,
- TextGenerator& generator) const {
+ TextGenerator* generator) const {
const Descriptor* descriptor = message.GetDescriptor();
const Reflection* reflection = message.GetReflection();
if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ &&
@@ -1634,13 +1862,13 @@ void TextFormat::Printer::PrintFieldValueToString(
io::StringOutputStream output_stream(output);
TextGenerator generator(&output_stream, initial_indent_level_);
- PrintFieldValue(message, message.GetReflection(), field, index, generator);
+ PrintFieldValue(message, message.GetReflection(), field, index, &generator);
}
void TextFormat::Printer::PrintField(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
- TextGenerator& generator) const {
+ TextGenerator* generator) const {
if (use_short_repeated_primitives_ &&
field->is_repeated() &&
field->cpp_type() != FieldDescriptor::CPPTYPE_STRING &&
@@ -1669,92 +1897,88 @@ void TextFormat::Printer::PrintField(const Message& message,
PrintFieldName(message, reflection, field, generator);
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- const FieldValuePrinter* printer = FindWithDefault(
+ const FastFieldValuePrinter* printer = FindWithDefault(
custom_printers_, field, default_field_value_printer_.get());
const Message& sub_message =
field->is_repeated()
? (is_map ? *map_entries[j]
: reflection->GetRepeatedMessage(message, field, j))
: reflection->GetMessage(message, field);
- generator.Print(
- printer->PrintMessageStart(
- sub_message, field_index, count, single_line_mode_));
- generator.Indent();
+ printer->PrintMessageStart(sub_message, field_index, count,
+ single_line_mode_, generator);
+ generator->Indent();
Print(sub_message, generator);
- generator.Outdent();
- generator.Print(
- printer->PrintMessageEnd(
- sub_message, field_index, count, single_line_mode_));
+ generator->Outdent();
+ printer->PrintMessageEnd(sub_message, field_index, count,
+ single_line_mode_, generator);
} else {
- generator.Print(": ");
+ generator->PrintLiteral(": ");
// Write the field value.
PrintFieldValue(message, reflection, field, field_index, generator);
if (single_line_mode_) {
- generator.Print(" ");
+ generator->PrintLiteral(" ");
} else {
- generator.Print("\n");
+ generator->PrintLiteral("\n");
}
}
}
}
void TextFormat::Printer::PrintShortRepeatedField(
- const Message& message,
- const Reflection* reflection,
- const FieldDescriptor* field,
- TextGenerator& generator) const {
+ const Message& message, const Reflection* reflection,
+ const FieldDescriptor* field, TextGenerator* generator) const {
// Print primitive repeated field in short form.
PrintFieldName(message, reflection, field, generator);
int size = reflection->FieldSize(message, field);
- generator.Print(": [");
+ generator->PrintLiteral(": [");
for (int i = 0; i < size; i++) {
- if (i > 0) generator.Print(", ");
+ if (i > 0) generator->PrintLiteral(", ");
PrintFieldValue(message, reflection, field, i, generator);
}
if (single_line_mode_) {
- generator.Print("] ");
+ generator->PrintLiteral("] ");
} else {
- generator.Print("]\n");
+ generator->PrintLiteral("]\n");
}
}
void TextFormat::Printer::PrintFieldName(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
- TextGenerator& generator) const {
+ TextGenerator* generator) const {
// if use_field_number_ is true, prints field number instead
// of field name.
if (use_field_number_) {
- generator.Print(SimpleItoa(field->number()));
+ generator->PrintString(SimpleItoa(field->number()));
return;
}
- const FieldValuePrinter* printer = FindWithDefault(
+ const FastFieldValuePrinter* printer = FindWithDefault(
custom_printers_, field, default_field_value_printer_.get());
- generator.Print(printer->PrintFieldName(message, reflection, field));
+ printer->PrintFieldName(message, reflection, field, generator);
}
-void TextFormat::Printer::PrintFieldValue(
- const Message& message,
- const Reflection* reflection,
- const FieldDescriptor* field,
- int index,
- TextGenerator& generator) const {
+void TextFormat::Printer::PrintFieldValue(const Message& message,
+ const Reflection* reflection,
+ const FieldDescriptor* field,
+ int index,
+ TextGenerator* generator) const {
GOOGLE_DCHECK(field->is_repeated() || (index == -1))
<< "Index must be -1 for non-repeated fields";
- const FieldValuePrinter* printer
- = FindWithDefault(custom_printers_, field,
- default_field_value_printer_.get());
+ const FastFieldValuePrinter* printer = FindWithDefault(
+ custom_printers_, field, default_field_value_printer_.get());
switch (field->cpp_type()) {
-#define OUTPUT_FIELD(CPPTYPE, METHOD) \
- case FieldDescriptor::CPPTYPE_##CPPTYPE: \
- generator.Print(printer->Print##METHOD(field->is_repeated() \
- ? reflection->GetRepeated##METHOD(message, field, index) \
- : reflection->Get##METHOD(message, field))); \
- break
+#define OUTPUT_FIELD(CPPTYPE, METHOD) \
+ case FieldDescriptor::CPPTYPE_##CPPTYPE: \
+ printer->Print##METHOD( \
+ field->is_repeated() \
+ ? reflection->GetRepeated##METHOD(message, field, index) \
+ : reflection->Get##METHOD(message, field), \
+ generator); \
+ break
OUTPUT_FIELD( INT32, Int32);
OUTPUT_FIELD( INT64, Int64);
@@ -1780,10 +2004,10 @@ void TextFormat::Printer::PrintFieldValue(
value_to_print = &truncated_value;
}
if (field->type() == FieldDescriptor::TYPE_STRING) {
- generator.Print(printer->PrintString(*value_to_print));
+ printer->PrintString(*value_to_print, generator);
} else {
GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_BYTES);
- generator.Print(printer->PrintBytes(*value_to_print));
+ printer->PrintBytes(*value_to_print, generator);
}
break;
}
@@ -1795,7 +2019,7 @@ void TextFormat::Printer::PrintFieldValue(
const EnumValueDescriptor* enum_desc =
field->enum_type()->FindValueByNumber(enum_value);
if (enum_desc != NULL) {
- generator.Print(printer->PrintEnum(enum_value, enum_desc->name()));
+ printer->PrintEnum(enum_value, enum_desc->name(), generator);
} else {
// Ordinarily, enum_desc should not be null, because proto2 has the
// invariant that set enum field values must be in-range, but with the
@@ -1803,8 +2027,8 @@ void TextFormat::Printer::PrintFieldValue(
// it is possible for the user to force an unknown integer value. So we
// simply use the integer value itself as the enum value name in this
// case.
- generator.Print(printer->PrintEnum(enum_value,
- StringPrintf("%d", enum_value)));
+ printer->PrintEnum(enum_value, StringPrintf("%d", enum_value),
+ generator);
}
break;
}
@@ -1867,90 +2091,93 @@ static string PaddedHex(IntType value) {
}
void TextFormat::Printer::PrintUnknownFields(
- const UnknownFieldSet& unknown_fields, TextGenerator& generator) const {
+ 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());
switch (field.type()) {
case UnknownField::TYPE_VARINT:
- generator.Print(field_number);
- generator.Print(": ");
- generator.Print(SimpleItoa(field.varint()));
+ generator->PrintString(field_number);
+ generator->PrintLiteral(": ");
+ generator->PrintString(SimpleItoa(field.varint()));
if (single_line_mode_) {
- generator.Print(" ");
+ generator->PrintLiteral(" ");
} else {
- generator.Print("\n");
+ generator->PrintLiteral("\n");
}
break;
case UnknownField::TYPE_FIXED32: {
- generator.Print(field_number);
- generator.Print(": 0x");
- generator.Print(
+ generator->PrintString(field_number);
+ generator->PrintLiteral(": 0x");
+ generator->PrintString(
StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8)));
if (single_line_mode_) {
- generator.Print(" ");
+ generator->PrintLiteral(" ");
} else {
- generator.Print("\n");
+ generator->PrintLiteral("\n");
}
break;
}
case UnknownField::TYPE_FIXED64: {
- generator.Print(field_number);
- generator.Print(": 0x");
- generator.Print(
+ generator->PrintString(field_number);
+ generator->PrintLiteral(": 0x");
+ generator->PrintString(
StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16)));
if (single_line_mode_) {
- generator.Print(" ");
+ generator->PrintLiteral(" ");
} else {
- generator.Print("\n");
+ generator->PrintLiteral("\n");
}
break;
}
case UnknownField::TYPE_LENGTH_DELIMITED: {
- generator.Print(field_number);
+ generator->PrintString(field_number);
const string& value = field.length_delimited();
UnknownFieldSet embedded_unknown_fields;
if (!value.empty() && embedded_unknown_fields.ParseFromString(value)) {
// This field is parseable as a Message.
// So it is probably an embedded message.
if (single_line_mode_) {
- generator.Print(" { ");
+ generator->PrintLiteral(" { ");
} else {
- generator.Print(" {\n");
- generator.Indent();
+ generator->PrintLiteral(" {\n");
+ generator->Indent();
}
PrintUnknownFields(embedded_unknown_fields, generator);
if (single_line_mode_) {
- generator.Print("} ");
+ generator->PrintLiteral("} ");
} else {
- generator.Outdent();
- generator.Print("}\n");
+ generator->Outdent();
+ generator->PrintLiteral("}\n");
}
} else {
// This field is not parseable as a Message.
// So it is probably just a plain string.
- string printed(": \"");
- CEscapeAndAppend(value, &printed);
- printed.append(single_line_mode_ ? "\" " : "\"\n");
- generator.Print(printed);
+ generator->PrintLiteral(": \"");
+ generator->PrintString(CEscape(value));
+ if (single_line_mode_) {
+ generator->PrintLiteral("\" ");
+ } else {
+ generator->PrintLiteral("\"\n");
+ }
}
break;
}
case UnknownField::TYPE_GROUP:
- generator.Print(field_number);
+ generator->PrintString(field_number);
if (single_line_mode_) {
- generator.Print(" { ");
+ generator->PrintLiteral(" { ");
} else {
- generator.Print(" {\n");
- generator.Indent();
+ generator->PrintLiteral(" {\n");
+ generator->Indent();
}
PrintUnknownFields(field.group(), generator);
if (single_line_mode_) {
- generator.Print("} ");
+ generator->PrintLiteral("} ");
} else {
- generator.Outdent();
- generator.Print("}\n");
+ generator->Outdent();
+ generator->PrintLiteral("}\n");
}
break;
}