aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf
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
parentd5cf7b55a6a1f959d1646785f63ca2b62da78079 (diff)
Massive roll-up of changes. See CHANGES.txt.
Diffstat (limited to 'src/google/protobuf')
-rw-r--r--src/google/protobuf/compiler/code_generator.cc9
-rw-r--r--src/google/protobuf/compiler/code_generator.h9
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc468
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h65
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc576
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc11
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc14
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc71
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.cc21
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc29
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc59
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc53
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h24
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc99
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc36
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc78
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc35
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc73
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc5
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc46
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.h3
-rw-r--r--src/google/protobuf/compiler/java/java_extension.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc10
-rw-r--r--src/google/protobuf/compiler/java/java_field.h2
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc40
-rw-r--r--src/google/protobuf/compiler/java/java_file.h5
-rw-r--r--src/google/protobuf/compiler/java/java_generator.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.cc43
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h18
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc83
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc18
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.h2
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc46
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.h3
-rw-r--r--src/google/protobuf/compiler/main.cc1
-rw-r--r--src/google/protobuf/compiler/parser.cc11
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc6
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc227
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h16
-rw-r--r--src/google/protobuf/descriptor.cc20
-rw-r--r--src/google/protobuf/descriptor.h23
-rw-r--r--src/google/protobuf/descriptor.pb.cc1327
-rw-r--r--src/google/protobuf/descriptor.pb.h637
-rw-r--r--src/google/protobuf/descriptor.proto22
-rw-r--r--src/google/protobuf/descriptor_database.cc30
-rw-r--r--src/google/protobuf/descriptor_database.h4
-rw-r--r--src/google/protobuf/descriptor_database_unittest.cc34
-rw-r--r--src/google/protobuf/descriptor_unittest.cc3
-rw-r--r--src/google/protobuf/dynamic_message.cc80
-rw-r--r--src/google/protobuf/dynamic_message.h27
-rw-r--r--src/google/protobuf/extension_set.cc304
-rw-r--r--src/google/protobuf/extension_set.h202
-rw-r--r--src/google/protobuf/extension_set_heavy.cc257
-rw-r--r--src/google/protobuf/extension_set_unittest.cc159
-rw-r--r--src/google/protobuf/generated_message_reflection.cc194
-rw-r--r--src/google/protobuf/generated_message_reflection.h17
-rw-r--r--src/google/protobuf/generated_message_util.cc9
-rw-r--r--src/google/protobuf/generated_message_util.h18
-rw-r--r--src/google/protobuf/io/coded_stream.cc379
-rw-r--r--src/google/protobuf/io/coded_stream.h347
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc88
-rw-r--r--src/google/protobuf/io/gzip_stream.cc2
-rw-r--r--src/google/protobuf/io/printer.cc25
-rw-r--r--src/google/protobuf/io/printer.h19
-rw-r--r--src/google/protobuf/io/printer_unittest.cc69
-rw-r--r--src/google/protobuf/io/tokenizer.cc2
-rw-r--r--src/google/protobuf/io/tokenizer.h5
-rw-r--r--src/google/protobuf/io/tokenizer_unittest.cc6
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl.h9
-rw-r--r--src/google/protobuf/io/zero_copy_stream_unittest.cc3
-rw-r--r--src/google/protobuf/message.cc4
-rw-r--r--src/google/protobuf/message.h28
-rw-r--r--src/google/protobuf/message_lite.cc59
-rw-r--r--src/google/protobuf/repeated_field.cc12
-rw-r--r--src/google/protobuf/repeated_field.h273
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc214
-rw-r--r--src/google/protobuf/stubs/common.h31
-rw-r--r--src/google/protobuf/stubs/strutil.cc34
-rw-r--r--src/google/protobuf/stubs/strutil.h8
-rw-r--r--src/google/protobuf/test_util.cc88
-rw-r--r--src/google/protobuf/test_util.h3
-rw-r--r--src/google/protobuf/testing/file.cc13
-rw-r--r--src/google/protobuf/text_format.cc156
-rw-r--r--src/google/protobuf/text_format.h35
-rw-r--r--src/google/protobuf/text_format_unittest.cc83
-rw-r--r--src/google/protobuf/unittest.proto93
-rw-r--r--src/google/protobuf/unittest_enormous_descriptor.proto1
-rw-r--r--src/google/protobuf/unknown_field_set.cc12
-rw-r--r--src/google/protobuf/unknown_field_set.h10
-rw-r--r--src/google/protobuf/wire_format.cc185
-rw-r--r--src/google/protobuf/wire_format_lite.cc175
-rw-r--r--src/google/protobuf/wire_format_lite.h156
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h366
-rw-r--r--src/google/protobuf/wire_format_unittest.cc71
98 files changed, 6364 insertions, 2395 deletions
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 0def84d8..3413a36a 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@@ -43,9 +44,15 @@ namespace compiler {
CodeGenerator::~CodeGenerator() {}
OutputDirectory::~OutputDirectory() {}
+io::ZeroCopyOutputStream* OutputDirectory::OpenForInsert(
+ const string& filename, const string& insertion_point) {
+ GOOGLE_LOG(FATAL) << "This OutputDirectory does not support insertion.";
+ return NULL; // make compiler happy
+}
+
// Parses a set of comma-delimited name/value pairs.
void ParseGeneratorParameter(const string& text,
- vector<pair<string, string> >* output) {
+ vector<pair<string, string> >* output) {
vector<string> parts;
SplitStringUsing(text, ",", &parts);
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index 8a7081f7..47ebb4d2 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -103,6 +103,13 @@ class LIBPROTOC_EXPORT OutputDirectory {
// contain "." or ".." components.
virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0;
+ // Creates a ZeroCopyOutputStream which will insert code into the given file
+ // at the given insertion point. See plugin.proto for more information on
+ // insertion points. The default implementation assert-fails -- it exists
+ // only for backwards-compatibility.
+ virtual io::ZeroCopyOutputStream* OpenForInsert(
+ const string& filename, const string& insertion_point);
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory);
};
@@ -114,7 +121,7 @@ class LIBPROTOC_EXPORT OutputDirectory {
// parses to the pairs:
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
extern void ParseGeneratorParameter(const string&,
- vector<pair<string, string> >*);
+ vector<pair<string, string> >*);
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 3eba3486..39bd370e 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -32,6 +32,8 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/compiler/command_line_interface.h>
+
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -46,15 +48,19 @@
#include <iostream>
#include <ctype.h>
-#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/compiler/subprocess.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/map-util.h>
namespace google {
@@ -182,6 +188,8 @@ class CommandLineInterface::DiskOutputDirectory : public OutputDirectory {
// implements OutputDirectory --------------------------------------
io::ZeroCopyOutputStream* Open(const string& filename);
+ io::ZeroCopyOutputStream* OpenForInsert(
+ const string& filename, const string& insertion_point);
private:
string root_;
@@ -209,11 +217,45 @@ class CommandLineInterface::ErrorReportingFileOutput
private:
scoped_ptr<io::FileOutputStream> file_stream_;
- int file_descriptor_;
string filename_;
DiskOutputDirectory* directory_;
};
+// Kind of like ErrorReportingFileOutput, but used when inserting
+// (OutputDirectory::OpenForInsert()). In this case, we are writing to a
+// temporary file, since we must copy data from the original. We copy the
+// data up to the insertion point in the constructor, and the remainder in the
+// destructor. We then replace the original file with the temporary, also in
+// the destructor.
+class CommandLineInterface::InsertionOutputStream
+ : public io::ZeroCopyOutputStream {
+ public:
+ InsertionOutputStream(
+ const string& filename,
+ const string& temp_filename,
+ const string& insertion_point,
+ int original_file_descriptor, // Takes ownership.
+ int temp_file_descriptor, // Takes ownership.
+ DiskOutputDirectory* directory); // Does not take ownership.
+ ~InsertionOutputStream();
+
+ // implements ZeroCopyOutputStream ---------------------------------
+ bool Next(void** data, int* size) { return temp_file_->Next(data, size); }
+ void BackUp(int count) { temp_file_->BackUp(count); }
+ int64 ByteCount() const { return temp_file_->ByteCount(); }
+
+ private:
+ scoped_ptr<io::FileInputStream> original_file_;
+ scoped_ptr<io::FileOutputStream> temp_file_;
+
+ string filename_;
+ string temp_filename_;
+ DiskOutputDirectory* directory_;
+
+ // The contents of the line containing the insertion point.
+ string magic_line_;
+};
+
// -------------------------------------------------------------------
CommandLineInterface::DiskOutputDirectory::DiskOutputDirectory(
@@ -242,6 +284,8 @@ bool CommandLineInterface::DiskOutputDirectory::VerifyExistence() {
return true;
}
+// -------------------------------------------------------------------
+
io::ZeroCopyOutputStream* CommandLineInterface::DiskOutputDirectory::Open(
const string& filename) {
// Recursively create parent directories to the output file.
@@ -286,7 +330,6 @@ CommandLineInterface::ErrorReportingFileOutput::ErrorReportingFileOutput(
const string& filename,
DiskOutputDirectory* directory)
: file_stream_(new io::FileOutputStream(file_descriptor)),
- file_descriptor_(file_descriptor),
filename_(filename),
directory_(directory) {}
@@ -304,6 +347,201 @@ CommandLineInterface::ErrorReportingFileOutput::~ErrorReportingFileOutput() {
}
}
+// -------------------------------------------------------------------
+
+io::ZeroCopyOutputStream*
+CommandLineInterface::DiskOutputDirectory::OpenForInsert(
+ const string& filename, const string& insertion_point) {
+ string path = root_ + filename;
+
+ // Put the temp file in the same directory so that we can simply rename() it
+ // into place later.
+ string temp_path = path + ".protoc_temp";
+
+ // Open the original file.
+ int original_file;
+ do {
+ original_file = open(path.c_str(), O_RDONLY | O_BINARY);
+ } while (original_file < 0 && errno == EINTR);
+
+ if (original_file < 0) {
+ // Failed to open.
+ cerr << path << ": " << strerror(errno) << endl;
+ had_error_ = true;
+ // Return a dummy stream.
+ return new io::ArrayOutputStream(NULL, 0);
+ }
+
+ // Create the temp file.
+ int temp_file;
+ do {
+ temp_file =
+ open(temp_path.c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ } while (temp_file < 0 && errno == EINTR);
+
+ if (temp_file < 0) {
+ // Failed to open.
+ cerr << temp_path << ": " << strerror(errno) << endl;
+ had_error_ = true;
+ close(original_file);
+ // Return a dummy stream.
+ return new io::ArrayOutputStream(NULL, 0);
+ }
+
+ return new InsertionOutputStream(
+ path, temp_path, insertion_point, original_file, temp_file, this);
+}
+
+namespace {
+
+// Helper for reading lines from a ZeroCopyInputStream.
+// TODO(kenton): Put somewhere reusable?
+class LineReader {
+ public:
+ LineReader(io::ZeroCopyInputStream* input)
+ : input_(input), buffer_(NULL), size_(0) {}
+
+ ~LineReader() {
+ if (size_ > 0) {
+ input_->BackUp(size_);
+ }
+ }
+
+ bool ReadLine(string* line) {
+ line->clear();
+
+ while (true) {
+ for (int i = 0; i < size_; i++) {
+ if (buffer_[i] == '\n') {
+ line->append(buffer_, i + 1);
+ buffer_ += i + 1;
+ size_ -= i + 1;
+ return true;
+ }
+ }
+
+ line->append(buffer_, size_);
+
+ const void* void_buffer;
+ if (!input_->Next(&void_buffer, &size_)) {
+ buffer_ = NULL;
+ size_ = 0;
+ return false;
+ }
+
+ buffer_ = reinterpret_cast<const char*>(void_buffer);
+ }
+ }
+
+ private:
+ io::ZeroCopyInputStream* input_;
+ const char* buffer_;
+ int size_;
+};
+
+} // namespace
+
+CommandLineInterface::InsertionOutputStream::InsertionOutputStream(
+ const string& filename,
+ const string& temp_filename,
+ const string& insertion_point,
+ int original_file_descriptor,
+ int temp_file_descriptor,
+ DiskOutputDirectory* directory)
+ : original_file_(new io::FileInputStream(original_file_descriptor)),
+ temp_file_(new io::FileOutputStream(temp_file_descriptor)),
+ filename_(filename),
+ temp_filename_(temp_filename),
+ directory_(directory) {
+ string magic_string = strings::Substitute(
+ "@@protoc_insertion_point($0)", insertion_point);
+
+ LineReader reader(original_file_.get());
+ io::Printer writer(temp_file_.get(), '$');
+ string line;
+
+ while (true) {
+ if (!reader.ReadLine(&line)) {
+ int error = temp_file_->GetErrno();
+ if (error == 0) {
+ cerr << filename << ": Insertion point not found: "
+ << insertion_point << endl;
+ } else {
+ cerr << filename << ": " << strerror(error) << endl;
+ }
+ original_file_->Close();
+ original_file_.reset();
+ // Will finish handling error in the destructor.
+ break;
+ }
+
+ if (line.find(magic_string) != string::npos) {
+ // Found the magic line. Since we want to insert before it, save it for
+ // later.
+ magic_line_ = line;
+ break;
+ }
+
+ writer.PrintRaw(line);
+ }
+}
+
+CommandLineInterface::InsertionOutputStream::~InsertionOutputStream() {
+ // C-style error handling is teh best.
+ bool had_error = false;
+
+ if (original_file_ == NULL) {
+ // We had an error in the constructor.
+ had_error = true;
+ } else {
+ // Use CodedOutputStream for convenience, so we don't have to deal with
+ // copying buffers ourselves.
+ io::CodedOutputStream out(temp_file_.get());
+ out.WriteRaw(magic_line_.data(), magic_line_.size());
+
+ // Write the rest of the original file.
+ const void* buffer;
+ int size;
+ while (original_file_->Next(&buffer, &size)) {
+ out.WriteRaw(buffer, size);
+ }
+
+ // Close the original file.
+ if (!original_file_->Close()) {
+ cerr << filename_ << ": " << strerror(original_file_->GetErrno()) << endl;
+ had_error = true;
+ }
+ }
+
+ // Check if we had any errors while writing.
+ if (temp_file_->GetErrno() != 0) {
+ cerr << filename_ << ": " << strerror(temp_file_->GetErrno()) << endl;
+ had_error = true;
+ }
+
+ // Close the temp file.
+ if (!temp_file_->Close()) {
+ cerr << filename_ << ": " << strerror(temp_file_->GetErrno()) << endl;
+ had_error = true;
+ }
+
+ // If everything was successful, overwrite the original file with the temp
+ // file.
+ if (!had_error) {
+ if (rename(temp_filename_.c_str(), filename_.c_str()) < 0) {
+ cerr << filename_ << ": rename: " << strerror(errno) << endl;
+ had_error = true;
+ }
+ }
+
+ if (had_error) {
+ // We had some sort of error so let's try to delete the temp file.
+ remove(temp_filename_.c_str());
+ directory_->set_had_error(true);
+ }
+}
+
// ===================================================================
CommandLineInterface::CommandLineInterface()
@@ -323,6 +561,10 @@ void CommandLineInterface::RegisterGenerator(const string& flag_name,
generators_[flag_name] = info;
}
+void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) {
+ plugin_prefix_ = exe_name_prefix;
+}
+
int CommandLineInterface::Run(int argc, const char* const argv[]) {
Clear();
if (!ParseArguments(argc, argv)) return 1;
@@ -346,7 +588,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
vector<const FileDescriptor*> parsed_files;
- // Parse each file and generate output.
+ // Parse each file.
for (int i = 0; i < input_files_.size(); i++) {
// Import the file.
const FileDescriptor* parsed_file = importer.Import(input_files_[i]);
@@ -359,13 +601,13 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
"--disallow_services was used." << endl;
return 1;
}
+ }
- if (mode_ == MODE_COMPILE) {
- // Generate output files.
- for (int i = 0; i < output_directives_.size(); i++) {
- if (!GenerateOutput(parsed_file, output_directives_[i])) {
- return 1;
- }
+ // Generate output.
+ if (mode_ == MODE_COMPILE) {
+ for (int i = 0; i < output_directives_.size(); i++) {
+ if (!GenerateOutput(parsed_files, output_directives_[i])) {
+ return 1;
}
}
}
@@ -686,10 +928,37 @@ bool CommandLineInterface::InterpretArgument(const string& name,
return false;
}
+ } else if (name == "--plugin") {
+ if (plugin_prefix_.empty()) {
+ cerr << "This compiler does not support plugins." << endl;
+ return false;
+ }
+
+ string name;
+ string path;
+
+ string::size_type equals_pos = value.find_first_of('=');
+ if (equals_pos == string::npos) {
+ // Use the basename of the file.
+ string::size_type slash_pos = value.find_last_of('/');
+ if (slash_pos == string::npos) {
+ name = value;
+ } else {
+ name = value.substr(slash_pos + 1);
+ }
+ path = value;
+ } else {
+ name = value.substr(0, equals_pos);
+ path = value.substr(equals_pos + 1);
+ }
+
+ plugins_[name] = path;
+
} else {
// Some other flag. Look it up in the generators list.
- GeneratorMap::const_iterator iter = generators_.find(name);
- if (iter == generators_.end()) {
+ const GeneratorInfo* generator_info = FindOrNull(generators_, name);
+ if (generator_info == NULL &&
+ (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
cerr << "Unknown flag: " << name << endl;
return false;
}
@@ -703,7 +972,11 @@ bool CommandLineInterface::InterpretArgument(const string& name,
OutputDirective directive;
directive.name = name;
- directive.generator = iter->second.generator;
+ if (generator_info == NULL) {
+ directive.generator = NULL;
+ } else {
+ directive.generator = generator_info->generator;
+ }
// Split value at ':' to separate the generator parameter from the
// filename. However, avoid doing this if the colon is part of a valid
@@ -755,6 +1028,17 @@ void CommandLineInterface::PrintHelpText() {
" --error_format=FORMAT Set the format in which to print errors.\n"
" FORMAT may be 'gcc' (the default) or 'msvs'\n"
" (Microsoft Visual Studio format)." << endl;
+ if (!plugin_prefix_.empty()) {
+ cerr <<
+" --plugin=EXECUTABLE Specifies a plugin executable to use.\n"
+" Normally, protoc searches the PATH for\n"
+" plugins, but you may specify additional\n"
+" executables not in the path using this flag.\n"
+" Additionally, EXECUTABLE may be of the form\n"
+" NAME=PATH, in which case the given plugin name\n"
+" is mapped to the given executable even if\n"
+" the executable's own name differs." << endl;
+ }
for (GeneratorMap::iterator iter = generators_.begin();
iter != generators_.end(); ++iter) {
@@ -768,7 +1052,7 @@ void CommandLineInterface::PrintHelpText() {
}
bool CommandLineInterface::GenerateOutput(
- const FileDescriptor* parsed_file,
+ const vector<const FileDescriptor*>& parsed_files,
const OutputDirective& output_directive) {
// Create the output directory.
DiskOutputDirectory output_directory(output_directive.output_location);
@@ -780,12 +1064,34 @@ bool CommandLineInterface::GenerateOutput(
// Call the generator.
string error;
- if (!output_directive.generator->Generate(
- parsed_file, output_directive.parameter, &output_directory, &error)) {
- // Generator returned an error.
- cerr << parsed_file->name() << ": " << output_directive.name << ": "
- << error << endl;
- return false;
+ if (output_directive.generator == NULL) {
+ // This is a plugin.
+ GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") &&
+ HasSuffixString(output_directive.name, "_out"))
+ << "Bad name for plugin generator: " << output_directive.name;
+
+ // Strip the "--" and "_out" and add the plugin prefix.
+ string plugin_name = plugin_prefix_ + "gen-" +
+ output_directive.name.substr(2, output_directive.name.size() - 6);
+
+ if (!GeneratePluginOutput(parsed_files, plugin_name,
+ output_directive.parameter,
+ &output_directory, &error)) {
+ cerr << output_directive.name << ": " << error << endl;
+ return false;
+ }
+ } else {
+ // Regular generator.
+ for (int i = 0; i < parsed_files.size(); i++) {
+ if (!output_directive.generator->Generate(
+ parsed_files[i], output_directive.parameter,
+ &output_directory, &error)) {
+ // Generator returned an error.
+ cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
+ << error << endl;
+ return false;
+ }
+ }
}
// Check for write errors.
@@ -796,6 +1102,84 @@ bool CommandLineInterface::GenerateOutput(
return true;
}
+bool CommandLineInterface::GeneratePluginOutput(
+ const vector<const FileDescriptor*>& parsed_files,
+ const string& plugin_name,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) {
+ CodeGeneratorRequest request;
+ CodeGeneratorResponse response;
+
+ // Build the request.
+ if (!parameter.empty()) {
+ request.set_parameter(parameter);
+ }
+
+ set<const FileDescriptor*> already_seen;
+ for (int i = 0; i < parsed_files.size(); i++) {
+ request.add_file_to_generate(parsed_files[i]->name());
+ GetTransitiveDependencies(parsed_files[i], &already_seen,
+ request.mutable_proto_file());
+ }
+
+ // Invoke the plugin.
+ Subprocess subprocess;
+
+ if (plugins_.count(plugin_name) > 0) {
+ subprocess.Start(plugins_[plugin_name], Subprocess::EXACT_NAME);
+ } else {
+ subprocess.Start(plugin_name, Subprocess::SEARCH_PATH);
+ }
+
+ string communicate_error;
+ if (!subprocess.Communicate(request, &response, &communicate_error)) {
+ *error = strings::Substitute("$0: $1", plugin_name, communicate_error);
+ return false;
+ }
+
+ // Write the files. We do this even if there was a generator error in order
+ // to match the behavior of a compiled-in generator.
+ scoped_ptr<io::ZeroCopyOutputStream> current_output;
+ for (int i = 0; i < response.file_size(); i++) {
+ const CodeGeneratorResponse::File& output_file = response.file(i);
+
+ if (!output_file.insertion_point().empty()) {
+ // Open a file for insert.
+ // We reset current_output to NULL first so that the old file is closed
+ // before the new one is opened.
+ current_output.reset();
+ current_output.reset(output_directory->OpenForInsert(
+ output_file.name(), output_file.insertion_point()));
+ } else if (!output_file.name().empty()) {
+ // Starting a new file. Open it.
+ // We reset current_output to NULL first so that the old file is closed
+ // before the new one is opened.
+ current_output.reset();
+ current_output.reset(output_directory->Open(output_file.name()));
+ } else if (current_output == NULL) {
+ *error = strings::Substitute(
+ "$0: First file chunk returned by plugin did not specify a file name.",
+ plugin_name);
+ return false;
+ }
+
+ // Use CodedOutputStream for convenience; otherwise we'd need to provide
+ // our own buffer-copying loop.
+ io::CodedOutputStream writer(current_output.get());
+ writer.WriteString(output_file.content());
+ }
+
+ // Check for errors.
+ if (!response.error().empty()) {
+ // Generator returned an error.
+ *error = response.error();
+ return false;
+ }
+
+ return true;
+}
+
bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
// Look up the type.
const Descriptor* type = pool->FindMessageTypeByName(codec_type_);
@@ -862,22 +1246,16 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
bool CommandLineInterface::WriteDescriptorSet(
const vector<const FileDescriptor*> parsed_files) {
FileDescriptorSet file_set;
- set<const FileDescriptor*> already_added;
- vector<const FileDescriptor*> to_add(parsed_files);
-
- while (!to_add.empty()) {
- const FileDescriptor* file = to_add.back();
- to_add.pop_back();
- if (already_added.insert(file).second) {
- // This file was not already in the set.
- file->CopyTo(file_set.add_file());
-
- if (imports_in_descriptor_set_) {
- // Add all of this file's dependencies.
- for (int i = 0; i < file->dependency_count(); i++) {
- to_add.push_back(file->dependency(i));
- }
- }
+
+ if (imports_in_descriptor_set_) {
+ set<const FileDescriptor*> already_seen;
+ for (int i = 0; i < parsed_files.size(); i++) {
+ GetTransitiveDependencies(
+ parsed_files[i], &already_seen, file_set.mutable_file());
+ }
+ } else {
+ for (int i = 0; i < parsed_files.size(); i++) {
+ parsed_files[i]->CopyTo(file_set.add_file());
}
}
@@ -906,6 +1284,24 @@ bool CommandLineInterface::WriteDescriptorSet(
return true;
}
+void CommandLineInterface::GetTransitiveDependencies(
+ const FileDescriptor* file,
+ set<const FileDescriptor*>* already_seen,
+ RepeatedPtrField<FileDescriptorProto>* output) {
+ if (!already_seen->insert(file).second) {
+ // Already saw this file. Skip.
+ return;
+ }
+
+ // Add all dependencies.
+ for (int i = 0; i < file->dependency_count(); i++) {
+ GetTransitiveDependencies(file->dependency(i), already_seen, output);
+ }
+
+ // Add this file.
+ file->CopyTo(output->Add());
+}
+
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index ec658636..1070a83b 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -50,10 +50,13 @@ namespace protobuf {
class FileDescriptor; // descriptor.h
class DescriptorPool; // descriptor.h
+class FileDescriptorProto; // descriptor.pb.h
+template<typename T> class RepeatedPtrField; // repeated_field.h
namespace compiler {
class CodeGenerator; // code_generator.h
+class OutputDirectory; // code_generator.h
class DiskSourceTree; // importer.h
// This class implements the command-line interface to the protocol compiler.
@@ -109,6 +112,37 @@ class LIBPROTOC_EXPORT CommandLineInterface {
CodeGenerator* generator,
const string& help_text);
+ // Enables "plugins". In this mode, if a command-line flag ends with "_out"
+ // but does not match any registered generator, the compiler will attempt to
+ // find a "plugin" to implement the generator. Plugins are just executables.
+ // They should live somewhere in the PATH.
+ //
+ // The compiler determines the executable name to search for by concatenating
+ // exe_name_prefix with the unrecognized flag name, removing "_out". So, for
+ // example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out,
+ // the compiler will try to run the program "protoc-foo".
+ //
+ // The plugin program should implement the following usage:
+ // plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
+ // --out indicates the output directory (as passed to the --foo_out
+ // parameter); if omitted, the current directory should be used. --parameter
+ // gives the generator parameter, if any was provided. The PROTO_FILES list
+ // the .proto files which were given on the compiler command-line; these are
+ // the files for which the plugin is expected to generate output code.
+ // Finally, DESCRIPTORS is an encoded FileDescriptorSet (as defined in
+ // descriptor.proto). This is piped to the plugin's stdin. The set will
+ // include descriptors for all the files listed in PROTO_FILES as well as
+ // all files that they import. The plugin MUST NOT attempt to read the
+ // PROTO_FILES directly -- it must use the FileDescriptorSet.
+ //
+ // The plugin should generate whatever files are necessary, as code generators
+ // normally do. It should write the names of all files it generates to
+ // stdout. The names should be relative to the output directory, NOT absolute
+ // names or relative to the current directory. If any errors occur, error
+ // messages should be written to stderr. If an error is fatal, the plugin
+ // should exit with a non-zero exit code.
+ void AllowPlugins(const string& exe_name_prefix);
+
// Run the Protocol Compiler with the given command-line parameters.
// Returns the error code which should be returned by main().
//
@@ -142,6 +176,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
class ErrorPrinter;
class DiskOutputDirectory;
class ErrorReportingFileOutput;
+ class InsertionOutputStream;
// Clear state from previous Run().
void Clear();
@@ -176,8 +211,13 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Generate the given output file from the given input.
struct OutputDirective; // see below
- bool GenerateOutput(const FileDescriptor* proto_file,
+ bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
const OutputDirective& output_directive);
+ bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
+ const string& plugin_name,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error);
// Implements --encode and --decode.
bool EncodeOrDecode(const DescriptorPool* pool);
@@ -185,6 +225,17 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Implements the --descriptor_set_out option.
bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
+ // Get all transitive dependencies of the given file (including the file
+ // itself), adding them to the given list of FileDescriptorProtos. The
+ // protos will be ordered such that every file is listed before any file that
+ // depends on it, so that you can call DescriptorPool::BuildFile() on them
+ // in order. Any files in *already_seen will not be added, and each file
+ // added will be inserted into *already_seen.
+ static void GetTransitiveDependencies(
+ const FileDescriptor* file,
+ set<const FileDescriptor*>* already_seen,
+ RepeatedPtrField<FileDescriptorProto>* output);
+
// -----------------------------------------------------------------
// The name of the executable as invoked (i.e. argv[0]).
@@ -201,6 +252,14 @@ class LIBPROTOC_EXPORT CommandLineInterface {
typedef map<string, GeneratorInfo> GeneratorMap;
GeneratorMap generators_;
+ // See AllowPlugins(). If this is empty, plugins aren't allowed.
+ string plugin_prefix_;
+
+ // Maps specific plugin names to files. When executing a plugin, this map
+ // is searched first to find the plugin executable. If not found here, the
+ // PATH (or other OS-specific search strategy) is searched.
+ map<string, string> plugins_;
+
// Stuff parsed from command line.
enum Mode {
MODE_COMPILE, // Normal mode: parse .proto files and compile them.
@@ -223,8 +282,8 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// output_directives_ lists all the files we are supposed to output and what
// generator to use for each.
struct OutputDirective {
- string name;
- CodeGenerator* generator;
+ string name; // E.g. "--foo_out"
+ CodeGenerator* generator; // NULL for plugins
string parameter;
string output_location;
};
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 9da41c02..83850cf9 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -47,10 +47,12 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/mock_code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -83,28 +85,19 @@ class CommandLineInterfaceTest : public testing::Test {
// -----------------------------------------------------------------
// Methods to set up the test (called before Run()).
- class MockCodeGenerator;
class NullCodeGenerator;
- // Registers a MockCodeGenerator with the given name.
- MockCodeGenerator* RegisterGenerator(const string& generator_name,
- const string& flag_name,
- const string& filename,
- const string& help_text);
- MockCodeGenerator* RegisterErrorGenerator(const string& generator_name,
- const string& error_text,
- const string& flag_name,
- const string& filename,
- const string& help_text);
-
- // Registers a CodeGenerator which will not actually generate anything,
- // but records the parameter passed to the generator.
- NullCodeGenerator* RegisterNullGenerator(const string& flag_name);
+ // Normally plugins are allowed for all tests. Call this to explicitly
+ // disable them.
+ void DisallowPlugins() { disallow_plugins_ = true; }
// Create a temp file within temp_directory_ with the given name.
// The containing directory is also created if necessary.
void CreateTempFile(const string& name, const string& contents);
+ // Create a subdirectory within temp_directory_.
+ void CreateTempDir(const string& name);
+
void SetInputsAreProtoPathRelative(bool enable) {
cli_.SetInputsAreProtoPathRelative(enable);
}
@@ -130,7 +123,8 @@ class CommandLineInterfaceTest : public testing::Test {
bool HasAlternateErrorSubstring(const string& expected_substring);
// Checks that MockCodeGenerator::Generate() was called in the given
- // context. That is, this tests if the generator with the given name
+ // context (or the generator in test_plugin.cc, which produces the same
+ // output). That is, this tests if the generator with the given name
// was called with the given parameter and proto file and produced the
// given output file. This is checked by reading the output file and
// checking that it contains the content that MockCodeGenerator would
@@ -140,8 +134,17 @@ class CommandLineInterfaceTest : public testing::Test {
void ExpectGenerated(const string& generator_name,
const string& parameter,
const string& proto_name,
+ const string& message_name);
+ void ExpectGenerated(const string& generator_name,
+ const string& parameter,
+ const string& proto_name,
const string& message_name,
- const string& output_file);
+ const string& output_directory);
+ void ExpectGeneratedWithInsertions(const string& generator_name,
+ const string& parameter,
+ const string& insertions,
+ const string& proto_name,
+ const string& message_name);
void ReadDescriptorSet(const string& filename,
FileDescriptorSet* descriptor_set);
@@ -150,6 +153,9 @@ class CommandLineInterfaceTest : public testing::Test {
// The object we are testing.
CommandLineInterface cli_;
+ // Was DisallowPlugins() called?
+ bool disallow_plugins_;
+
// We create a directory within TestTempDir() in order to add extra
// protection against accidentally deleting user files (since we recursively
// delete this directory during the test). This is the full path of that
@@ -166,40 +172,6 @@ class CommandLineInterfaceTest : public testing::Test {
vector<CodeGenerator*> mock_generators_to_delete_;
};
-// A mock CodeGenerator which outputs information about the context in which
-// it was called, which can then be checked. Output is written to a filename
-// constructed by concatenating the filename_prefix (given to the constructor)
-// with the proto file name, separated by a '.'.
-class CommandLineInterfaceTest::MockCodeGenerator : public CodeGenerator {
- public:
- // Create a MockCodeGenerator whose Generate() method returns true.
- MockCodeGenerator(const string& name, const string& filename_prefix);
-
- // Create a MockCodeGenerator whose Generate() method returns false
- // and sets the error string to the given string.
- MockCodeGenerator(const string& name, const string& filename_prefix,
- const string& error);
-
- ~MockCodeGenerator();
-
- void set_expect_write_error(bool value) {
- expect_write_error_ = value;
- }
-
- // implements CodeGenerator ----------------------------------------
- bool Generate(const FileDescriptor* file,
- const string& parameter,
- OutputDirectory* output_directory,
- string* error) const;
-
- private:
- string name_;
- string filename_prefix_;
- bool return_error_;
- string error_;
- bool expect_write_error_;
-};
-
class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator {
public:
NullCodeGenerator() : called_(false) {}
@@ -237,6 +209,22 @@ void CommandLineInterfaceTest::SetUp() {
// Create the temp directory.
GOOGLE_CHECK(File::CreateDir(temp_directory_.c_str(), DEFAULT_FILE_MODE));
+
+ // Register generators.
+ CodeGenerator* generator = new MockCodeGenerator("test_generator");
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator("--test_out", generator, "Test output.");
+ cli_.RegisterGenerator("-t", generator, "Test output.");
+
+ generator = new MockCodeGenerator("alt_generator");
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator("--alt_out", generator, "Alt output.");
+
+ generator = new NullCodeGenerator();
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator("--null_out", generator, "Null output.");
+
+ disallow_plugins_ = false;
}
void CommandLineInterfaceTest::TearDown() {
@@ -254,6 +242,11 @@ void CommandLineInterfaceTest::Run(const string& command) {
vector<string> args;
SplitStringUsing(command, " ", &args);
+ if (!disallow_plugins_) {
+ cli_.AllowPlugins("prefix-");
+ args.push_back("--plugin=prefix-gen-plug=test_plugin");
+ }
+
scoped_array<const char*> argv(new const char*[args.size()]);
for (int i = 0; i < args.size(); i++) {
@@ -270,44 +263,6 @@ void CommandLineInterfaceTest::Run(const string& command) {
// -------------------------------------------------------------------
-CommandLineInterfaceTest::MockCodeGenerator*
-CommandLineInterfaceTest::RegisterGenerator(
- const string& generator_name,
- const string& flag_name,
- const string& filename,
- const string& help_text) {
- MockCodeGenerator* generator =
- new MockCodeGenerator(generator_name, filename);
- mock_generators_to_delete_.push_back(generator);
-
- cli_.RegisterGenerator(flag_name, generator, help_text);
- return generator;
-}
-
-CommandLineInterfaceTest::MockCodeGenerator*
-CommandLineInterfaceTest::RegisterErrorGenerator(
- const string& generator_name,
- const string& error_text,
- const string& flag_name,
- const string& filename_prefix,
- const string& help_text) {
- MockCodeGenerator* generator =
- new MockCodeGenerator(generator_name, filename_prefix, error_text);
- mock_generators_to_delete_.push_back(generator);
-
- cli_.RegisterGenerator(flag_name, generator, help_text);
- return generator;
-}
-
-CommandLineInterfaceTest::NullCodeGenerator*
-CommandLineInterfaceTest::RegisterNullGenerator(
- const string& flag_name) {
- NullCodeGenerator* generator = new NullCodeGenerator;
- mock_generators_to_delete_.push_back(generator);
- cli_.RegisterGenerator(flag_name, generator, "");
- return generator;
-}
-
void CommandLineInterfaceTest::CreateTempFile(
const string& name,
const string& contents) {
@@ -323,6 +278,10 @@ void CommandLineInterfaceTest::CreateTempFile(
File::WriteStringToFileOrDie(contents, full_name);
}
+void CommandLineInterfaceTest::CreateTempDir(const string& name) {
+ File::RecursivelyCreateDir(temp_directory_ + "/" + name, 0777);
+}
+
// -------------------------------------------------------------------
void CommandLineInterfaceTest::ExpectNoErrors() {
@@ -352,21 +311,31 @@ void CommandLineInterfaceTest::ExpectGenerated(
const string& generator_name,
const string& parameter,
const string& proto_name,
+ const string& message_name) {
+ MockCodeGenerator::ExpectGenerated(
+ generator_name, parameter, "", proto_name, message_name, temp_directory_);
+}
+
+void CommandLineInterfaceTest::ExpectGenerated(
+ const string& generator_name,
+ const string& parameter,
+ const string& proto_name,
const string& message_name,
- const string& output_file_prefix) {
- // Open and read the file.
- string output_file = output_file_prefix + "." + proto_name;
- string file_contents;
- ASSERT_TRUE(File::ReadFileToString(temp_directory_ + "/" + output_file,
- &file_contents))
- << "Failed to open file: " + output_file;
+ const string& output_directory) {
+ MockCodeGenerator::ExpectGenerated(
+ generator_name, parameter, "", proto_name, message_name,
+ temp_directory_ + "/" + output_directory);
+}
- // Check that the contents are as we expect.
- string expected_contents =
- generator_name + ": " + parameter + ", " + proto_name + ", " +
- message_name + "\n";
- EXPECT_EQ(expected_contents, file_contents)
- << "Output file did not have expected contents: " + output_file;
+void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
+ const string& generator_name,
+ const string& parameter,
+ const string& insertions,
+ const string& proto_name,
+ const string& message_name) {
+ MockCodeGenerator::ExpectGenerated(
+ generator_name, parameter, insertions, proto_name, message_name,
+ temp_directory_);
}
void CommandLineInterfaceTest::ReadDescriptorSet(
@@ -383,77 +352,52 @@ void CommandLineInterfaceTest::ReadDescriptorSet(
// ===================================================================
-CommandLineInterfaceTest::MockCodeGenerator::MockCodeGenerator(
- const string& name, const string& filename_prefix)
- : name_(name),
- filename_prefix_(filename_prefix),
- return_error_(false),
- expect_write_error_(false) {
-}
-
-CommandLineInterfaceTest::MockCodeGenerator::MockCodeGenerator(
- const string& name, const string& filename_prefix, const string& error)
- : name_(name),
- filename_prefix_(filename_prefix),
- return_error_(true),
- error_(error),
- expect_write_error_(false) {
-}
+TEST_F(CommandLineInterfaceTest, BasicOutput) {
+ // Test that the common case works.
-CommandLineInterfaceTest::MockCodeGenerator::~MockCodeGenerator() {}
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
-bool CommandLineInterfaceTest::MockCodeGenerator::Generate(
- const FileDescriptor* file,
- const string& parameter,
- OutputDirectory* output_directory,
- string* error) const {
- scoped_ptr<io::ZeroCopyOutputStream> output(
- output_directory->Open(filename_prefix_ + "." + file->name()));
- io::Printer printer(output.get(), '$');
- map<string, string> vars;
- vars["name"] = name_;
- vars["parameter"] = parameter;
- vars["proto_name"] = file->name();
- vars["message_name"] = file->message_type_count() > 0 ?
- file->message_type(0)->full_name().c_str() : "(none)";
-
- printer.Print(vars, "$name$: $parameter$, $proto_name$, $message_name$\n");
-
- if (expect_write_error_) {
- EXPECT_TRUE(printer.failed());
- } else {
- EXPECT_FALSE(printer.failed());
- }
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
- *error = error_;
- return !return_error_;
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
-// ===================================================================
+TEST_F(CommandLineInterfaceTest, BasicPlugin) {
+ // Test that basic plugins work.
-TEST_F(CommandLineInterfaceTest, BasicOutput) {
- // Test that the common case works.
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
+ Run("protocol_compiler --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) {
+ // Invoke a generator and a plugin at the same time.
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
- Run("protocol_compiler --test_out=$tmpdir "
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+ ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, MultipleInputs) {
// Test parsing multiple input files.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -461,48 +405,68 @@ TEST_F(CommandLineInterfaceTest, MultipleInputs) {
"syntax = \"proto2\";\n"
"message Bar {}\n");
- Run("protocol_compiler --test_out=$tmpdir "
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
"--proto_path=$tmpdir foo.proto bar.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
- ExpectGenerated("test_generator", "", "bar.proto", "Bar", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+ ExpectGenerated("test_generator", "", "bar.proto", "Bar");
}
TEST_F(CommandLineInterfaceTest, CreateDirectory) {
// Test that when we output to a sub-directory, it is created.
- RegisterGenerator("test_generator", "--test_out",
- "bar/baz/output.test", "Test output.");
-
- CreateTempFile("foo.proto",
+ CreateTempFile("bar/baz/foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
+ CreateTempDir("out");
+ CreateTempDir("plugout");
- Run("protocol_compiler --test_out=$tmpdir "
- "--proto_path=$tmpdir foo.proto");
+ Run("protocol_compiler --test_out=$tmpdir/out --plug_out=$tmpdir/plugout "
+ "--proto_path=$tmpdir bar/baz/foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "",
- "foo.proto", "Foo", "bar/baz/output.test");
+ ExpectGenerated("test_generator", "", "bar/baz/foo.proto", "Foo", "out");
+ ExpectGenerated("test_plugin", "", "bar/baz/foo.proto", "Foo", "plugout");
}
TEST_F(CommandLineInterfaceTest, GeneratorParameters) {
// Test that generator parameters are correctly parsed from the command line.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
Run("protocol_compiler --test_out=TestParameter:$tmpdir "
+ "--plug_out=TestPluginParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "TestParameter", "foo.proto", "Foo");
+ ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, Insert) {
+ // Test running a generator that inserts code into another's output.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler "
+ "--test_out=TestParameter:$tmpdir "
+ "--plug_out=TestPluginParameter:$tmpdir "
+ "--test_out=insert=test_generator,test_plugin:$tmpdir "
+ "--plug_out=insert=test_generator,test_plugin:$tmpdir "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "TestParameter",
- "foo.proto", "Foo", "output.test");
+ ExpectGeneratedWithInsertions(
+ "test_generator", "TestParameter", "test_generator,test_plugin",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithInsertions(
+ "test_plugin", "TestPluginParameter", "test_generator,test_plugin",
+ "foo.proto", "Foo");
}
#if defined(_WIN32) || defined(__CYGWIN__)
@@ -510,12 +474,10 @@ TEST_F(CommandLineInterfaceTest, GeneratorParameters) {
TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
// Test that the output path can be a Windows-style path.
- NullCodeGenerator* generator = RegisterNullGenerator("--test_out");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n");
- Run("protocol_compiler --test_out=C:\\ "
+ Run("protocol_compiler --null_out=C:\\ "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
@@ -526,12 +488,10 @@ TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
TEST_F(CommandLineInterfaceTest, WindowsOutputPathAndParameter) {
// Test that we can have a windows-style output path and a parameter.
- NullCodeGenerator* generator = RegisterNullGenerator("--test_out");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n");
- Run("protocol_compiler --test_out=bar:C:\\ "
+ Run("protocol_compiler --null_out=bar:C:\\ "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
@@ -543,9 +503,6 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
// Test that the directories can end in backslashes. Some users claim this
// doesn't work on their system.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -554,7 +511,7 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
"--proto_path=$tmpdir\\ foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
#endif // defined(_WIN32) || defined(__CYGWIN__)
@@ -562,9 +519,6 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
TEST_F(CommandLineInterfaceTest, PathLookup) {
// Test that specifying multiple directories in the proto search path works.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("b/bar.proto",
"syntax = \"proto2\";\n"
"message Bar {}\n");
@@ -580,15 +534,12 @@ TEST_F(CommandLineInterfaceTest, PathLookup) {
"--proto_path=$tmpdir/a --proto_path=$tmpdir/b foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) {
// Same as PathLookup, but we provide the proto_path in a single flag.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("b/bar.proto",
"syntax = \"proto2\";\n"
"message Bar {}\n");
@@ -613,15 +564,12 @@ TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) {
#undef PATH_SEPARATOR
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, NonRootMapping) {
// Test setting up a search path mapping a directory to a non-root location.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -630,42 +578,34 @@ TEST_F(CommandLineInterfaceTest, NonRootMapping) {
"--proto_path=bar=$tmpdir bar/foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, MultipleGenerators) {
// Test that we can have multiple generators and use both in one invocation,
// each with a different output directory.
- RegisterGenerator("test_generator_1", "--test1_out",
- "output1.test", "Test output 1.");
- RegisterGenerator("test_generator_2", "--test2_out",
- "output2.test", "Test output 2.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
// Create the "a" and "b" sub-directories.
- CreateTempFile("a/dummy", "");
- CreateTempFile("b/dummy", "");
+ CreateTempDir("a");
+ CreateTempDir("b");
Run("protocol_compiler "
- "--test1_out=$tmpdir/a "
- "--test2_out=$tmpdir/b "
+ "--test_out=$tmpdir/a "
+ "--alt_out=$tmpdir/b "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator_1", "", "foo.proto", "Foo", "a/output1.test");
- ExpectGenerated("test_generator_2", "", "foo.proto", "Foo", "b/output2.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo", "a");
+ ExpectGenerated("alt_generator", "", "foo.proto", "Foo", "b");
}
TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) {
// Test that --disallow_services doesn't cause a problem when there are no
// services.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -674,15 +614,12 @@ TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) {
// Test that --disallow_services produces an error when there are services.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n"
@@ -697,9 +634,6 @@ TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) {
TEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
// Test that services work fine as long as --disallow_services is not used.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n"
@@ -709,7 +643,7 @@ TEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
@@ -717,9 +651,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -728,7 +659,7 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
"--proto_path=$tmpdir $tmpdir/foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
@@ -787,9 +718,6 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
TEST_F(CommandLineInterfaceTest, ParseErrors) {
// Test that parse errors are reported.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"badsyntax\n");
@@ -804,9 +732,6 @@ TEST_F(CommandLineInterfaceTest, ParseErrors) {
TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
// Test that parse errors are reported from multiple files.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
// We set up files such that foo.proto actually depends on bar.proto in
// two ways: Directly and through baz.proto. bar.proto's errors should
// only be reported once.
@@ -834,9 +759,6 @@ TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
TEST_F(CommandLineInterfaceTest, InputNotFoundError) {
// Test what happens if the input file is not found.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir foo.proto");
@@ -850,9 +772,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir $tmpdir/foo.proto");
@@ -866,9 +785,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -895,9 +811,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
// Create a directory called "bar" so that we can point --proto_path at it.
CreateTempFile("bar/dummy", "");
@@ -914,9 +827,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo/foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -938,9 +848,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) {
TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) {
// Test what happens if the input file is not found.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir/foo foo.proto");
@@ -952,9 +859,6 @@ TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) {
TEST_F(CommandLineInterfaceTest, MissingInputError) {
// Test that we get an error if no inputs are given.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir");
@@ -962,9 +866,6 @@ TEST_F(CommandLineInterfaceTest, MissingInputError) {
}
TEST_F(CommandLineInterfaceTest, MissingOutputError) {
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -975,35 +876,56 @@ TEST_F(CommandLineInterfaceTest, MissingOutputError) {
}
TEST_F(CommandLineInterfaceTest, OutputWriteError) {
- MockCodeGenerator* generator =
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
- generator->set_expect_write_error(true);
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
+ string output_file =
+ MockCodeGenerator::GetOutputFileName("test_generator", "foo.proto");
+
// Create a directory blocking our output location.
- CreateTempFile("output.test.foo.proto/foo", "");
+ CreateTempDir(output_file);
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir foo.proto");
+ ExpectErrorSubstring("MockCodeGenerator detected write error.");
+
#if defined(_WIN32) && !defined(__CYGWIN__)
// Windows with MSVCRT.dll produces EPERM instead of EISDIR.
- if (HasAlternateErrorSubstring("output.test.foo.proto: Permission denied")) {
+ if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
return;
}
#endif
- ExpectErrorSubstring("output.test.foo.proto: Is a directory");
+ ExpectErrorSubstring(output_file + ": Is a directory");
}
-TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
+TEST_F(CommandLineInterfaceTest, PluginOutputWriteError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ string output_file =
+ MockCodeGenerator::GetOutputFileName("test_plugin", "foo.proto");
+
+ // Create a directory blocking our output location.
+ CreateTempDir(output_file);
+
+ Run("protocol_compiler --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Windows with MSVCRT.dll produces EPERM instead of EISDIR.
+ if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
+ return;
+ }
+#endif
+
+ ExpectErrorSubstring(output_file + ": Is a directory");
+}
+TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1011,14 +933,21 @@ TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
Run("protocol_compiler --test_out=$tmpdir/nosuchdir "
"--proto_path=$tmpdir foo.proto");
- ExpectErrorSubstring("nosuchdir/: "
- "No such file or directory");
+ ExpectErrorSubstring("nosuchdir/: No such file or directory");
}
-TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
+TEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ Run("protocol_compiler --plug_out=$tmpdir/nosuchdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("nosuchdir/: No such file or directory");
+}
+
+TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1037,45 +966,109 @@ TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
}
TEST_F(CommandLineInterfaceTest, GeneratorError) {
- RegisterErrorGenerator("error_generator", "Test error message.",
- "--error_out", "output.test", "Test error output.");
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Error {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring(
+ "--test_out: foo.proto: Saw message type MockCodeGenerator_Error.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginError) {
+ // Test a generator plugin that returns an error.
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
- "message Foo {}\n");
+ "message MockCodeGenerator_Error {}\n");
- Run("protocol_compiler --error_out=$tmpdir "
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
"--proto_path=$tmpdir foo.proto");
- ExpectErrorSubstring("--error_out: Test error message.");
+ ExpectErrorSubstring(
+ "--plug_out: foo.proto: Saw message type MockCodeGenerator_Error.");
}
-TEST_F(CommandLineInterfaceTest, HelpText) {
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
- RegisterErrorGenerator("error_generator", "Test error message.",
- "--error_out", "output.test", "Test error output.");
+TEST_F(CommandLineInterfaceTest, GeneratorPluginFail) {
+ // Test a generator plugin that exits with an error code.
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Exit {}\n");
+
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("Saw message type MockCodeGenerator_Exit.");
+ ExpectErrorSubstring(
+ "--plug_out: prefix-gen-plug: Plugin failed with status code 123.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) {
+ // Test a generator plugin that crashes.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Abort {}\n");
+
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("Saw message type MockCodeGenerator_Abort.");
+
+ // Don't depend on the exact signal number.
+ ExpectErrorSubstring(
+ "--plug_out: prefix-gen-plug: Plugin killed by signal");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
+ // Test what happens if the plugin isn't found.
+
+ CreateTempFile("error.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --badplug_out=TestParameter:$tmpdir "
+ "--plugin=prefix-gen-badplug=no_such_file "
+ "--proto_path=$tmpdir error.proto");
+
+ ExpectErrorSubstring(
+ "no_such_file: program not found or is not executable");
+
+ ExpectErrorSubstring(
+ "--badplug_out: prefix-gen-badplug: Plugin failed with status code 1.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) {
+ // Test what happens if plugins aren't allowed.
+
+ CreateTempFile("error.proto",
+ "syntax = \"proto2\";\n"
"message Foo {}\n");
+ DisallowPlugins();
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir error.proto");
+
+ ExpectErrorSubstring("Unknown flag: --plug_out");
+}
+
+TEST_F(CommandLineInterfaceTest, HelpText) {
Run("test_exec_name --help");
ExpectErrorSubstring("Usage: test_exec_name ");
ExpectErrorSubstring("--test_out=OUT_DIR");
ExpectErrorSubstring("Test output.");
- ExpectErrorSubstring("--error_out=OUT_DIR");
- ExpectErrorSubstring("Test error output.");
+ ExpectErrorSubstring("--alt_out=OUT_DIR");
+ ExpectErrorSubstring("Alt output.");
}
TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
// Test --error_format=gcc (which is the default, but we want to verify
// that it can be set explicitly).
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"badsyntax\n");
@@ -1090,9 +1083,6 @@ TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
// Test --error_format=msvs
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"badsyntax\n");
@@ -1108,9 +1098,6 @@ TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
// Test --error_format=msvs
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"badsyntax\n");
@@ -1128,9 +1115,6 @@ TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) {
// Test that a single-character flag works.
- RegisterGenerator("test_generator", "-t",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1139,15 +1123,12 @@ TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) {
// Test that separating the flag value with a space works.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1156,16 +1137,13 @@ TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) {
// Test that separating the flag value with a space works for
// single-character flags.
- RegisterGenerator("test_generator", "-t",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1174,15 +1152,12 @@ TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, MissingValueError) {
// Test that we get an error if a flag is missing its value.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out --proto_path=$tmpdir foo.proto");
ExpectErrorText("Missing value for flag: --test_out\n");
@@ -1192,9 +1167,6 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) {
// Test that we get an error if the last argument is a flag requiring a
// value.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out");
ExpectErrorText("Missing value for flag: --test_out\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index a7bc35bd..30b1d2bf 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -123,8 +123,11 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
Importer importer(&source_tree, &error_collector);
const FileDescriptor* proto_file =
importer.Import("google/protobuf/descriptor.proto");
+ const FileDescriptor* plugin_proto_file =
+ importer.Import("google/protobuf/compiler/plugin.proto");
EXPECT_EQ("", error_collector.text_);
ASSERT_TRUE(proto_file != NULL);
+ ASSERT_TRUE(plugin_proto_file != NULL);
CppGenerator generator;
MockOutputDirectory output_directory;
@@ -133,11 +136,18 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
ASSERT_TRUE(generator.Generate(proto_file, parameter,
&output_directory, &error));
+ parameter = "dllexport_decl=LIBPROTOC_EXPORT";
+ ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
+ &output_directory, &error));
output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.h",
"google/protobuf/descriptor.pb.h");
output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
"google/protobuf/descriptor.pb.cc");
+ output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
+ "google/protobuf/compiler/plugin.pb.h");
+ output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
+ "google/protobuf/compiler/plugin.pb.cc");
}
} // namespace
@@ -145,5 +155,4 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
} // namespace cpp
} // namespace compiler
} // namespace protobuf
-
} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 90e9172a..76d2b798 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -98,6 +98,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
"$dllexport$bool $classname$_IsValid(int value);\n"
"const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
"const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
+ "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n"
"\n");
if (HasDescriptorMethods(descriptor_->file())) {
@@ -149,17 +150,21 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
"static const $nested_name$ $nested_name$_MIN =\n"
" $classname$_$nested_name$_MIN;\n"
"static const $nested_name$ $nested_name$_MAX =\n"
- " $classname$_$nested_name$_MAX;\n");
+ " $classname$_$nested_name$_MAX;\n"
+ "static const int $nested_name$_ARRAYSIZE =\n"
+ " $classname$_$nested_name$_ARRAYSIZE;\n");
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(vars,
"static inline const ::google::protobuf::EnumDescriptor*\n"
"$nested_name$_descriptor() {\n"
" return $classname$_descriptor();\n"
- "}\n"
+ "}\n");
+ printer->Print(vars,
"static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
" return $classname$_Name(value);\n"
- "}\n"
+ "}\n");
+ printer->Print(vars,
"static inline bool $nested_name$_Parse(const ::std::string& name,\n"
" $nested_name$* value) {\n"
" return $classname$_Parse(name, value);\n"
@@ -240,7 +245,8 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
}
printer->Print(vars,
"const $classname$ $parent$::$nested_name$_MIN;\n"
- "const $classname$ $parent$::$nested_name$_MAX;\n");
+ "const $classname$ $parent$::$nested_name$_MAX;\n"
+ "const int $parent$::$nested_name$_ARRAYSIZE;\n");
printer->Print("#endif // _MSC_VER\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 7ca11c8c..91ce493a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -114,7 +114,9 @@ void EnumFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"int value;\n"
- "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
+ "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+ " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
+ " input, &value)));\n"
"if ($type$_IsValid(value)) {\n"
" set_$name$(static_cast< $type$ >(value));\n");
if (HasUnknownFields(descriptor_->file())) {
@@ -170,24 +172,17 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
- "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n"
"inline $type$ $name$(int index) const$deprecation$;\n"
"inline void set_$name$(int index, $type$ value)$deprecation$;\n"
"inline void add_$name$($type$ value)$deprecation$;\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
+ "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
}
void RepeatedEnumFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField<int>&\n"
- "$classname$::$name$() const {\n"
- " return $name$_;\n"
- "}\n"
- "inline ::google::protobuf::RepeatedField<int>*\n"
- "$classname$::mutable_$name$() {\n"
- " return &$name$_;\n"
- "}\n"
"inline $type$ $classname$::$name$(int index) const {\n"
" return static_cast< $type$ >($name$_.Get(index));\n"
"}\n"
@@ -199,6 +194,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GOOGLE_DCHECK($type$_IsValid(value));\n"
" $name$_.Add(value);\n"
"}\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedField<int>&\n"
+ "$classname$::$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::google::protobuf::RepeatedField<int>*\n"
+ "$classname$::mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n");
}
void RepeatedEnumFieldGenerator::
@@ -223,7 +227,33 @@ GenerateConstructorCode(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ // Don't use ReadRepeatedPrimitive here so that the enum can be validated.
+ printer->Print(variables_,
+ "int value;\n"
+ "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+ " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
+ " input, &value)));\n"
+ "if ($type$_IsValid(value)) {\n"
+ " add_$name$(static_cast< $type$ >(value));\n");
+ if (HasUnknownFields(descriptor_->file())) {
+ printer->Print(variables_,
+ "} else {\n"
+ " mutable_unknown_fields()->AddVarint($number$, value);\n");
+ }
+ printer->Print("}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
+ if (!descriptor_->options().packed()) {
+ // We use a non-inlined implementation in this case, since this path will
+ // rarely be executed.
+ printer->Print(variables_,
+ "DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
+ " input,\n"
+ " &$type$_IsValid,\n"
+ " this->mutable_$name$())));\n");
+ } else {
printer->Print(variables_,
"::google::protobuf::uint32 length;\n"
"DO_(input->ReadVarint32(&length));\n"
@@ -231,25 +261,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"input->PushLimit(length);\n"
"while (input->BytesUntilLimit() > 0) {\n"
" int value;\n"
- " DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
+ " DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+ " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
+ " input, &value)));\n"
" if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n"
" }\n"
"}\n"
"input->PopLimit(limit);\n");
- } else {
- printer->Print(variables_,
- "int value;\n"
- "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
- "if ($type$_IsValid(value)) {\n"
- " add_$name$(static_cast< $type$ >(value));\n");
- if (HasUnknownFields(descriptor_->file())) {
- printer->Print(variables_,
- "} else {\n"
- " mutable_unknown_fields()->AddVarint($number$, value);\n");
- }
- printer->Print(variables_,
- "}\n");
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 20dd57bb..0793430c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -83,6 +83,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
+ void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index 7208ed3a..658a7077 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/cpp/cpp_extension.h>
+#include <map>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
@@ -43,6 +44,18 @@ namespace protobuf {
namespace compiler {
namespace cpp {
+namespace {
+
+// Returns the fully-qualified class name of the message that this field
+// extends. This function is used in the Google-internal code to handle some
+// legacy cases.
+string ExtendeeClassName(const FieldDescriptor* descriptor) {
+ const Descriptor* extendee = descriptor->containing_type();
+ return ClassName(extendee, true);
+}
+
+} // anonymous namespace
+
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
const string& dllexport_decl)
: descriptor_(descriptor),
@@ -80,7 +93,7 @@ ExtensionGenerator::~ExtensionGenerator() {}
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
map<string, string> vars;
- vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
+ vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["number" ] = SimpleItoa(descriptor_->number());
vars["type_traits" ] = type_traits_;
vars["name" ] = descriptor_->name();
@@ -106,6 +119,7 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
" ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
" $name$;\n"
);
+
}
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
@@ -115,7 +129,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
string name = scope + descriptor_->name();
map<string, string> vars;
- vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
+ vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["type_traits" ] = type_traits_;
vars["name" ] = name;
vars["constant_name"] = FieldConstantName(descriptor_);
@@ -154,7 +168,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
map<string, string> vars;
- vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
+ vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["number" ] = SimpleItoa(descriptor_->number());
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
@@ -193,5 +207,4 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
} // namespace cpp
} // namespace compiler
} // namespace protobuf
-
} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index c546e964..103cac4a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -40,6 +40,7 @@
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
@@ -61,11 +62,24 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["tag_size"] = SimpleItoa(
WireFormat::TagSize(descriptor->number(), descriptor->type()));
(*variables)["deprecation"] = descriptor->options().deprecated()
- ? " DEPRECATED_PROTOBUF_FIELD" : "";
+ ? " PROTOBUF_DEPRECATED" : "";
+
}
FieldGenerator::~FieldGenerator() {}
+void FieldGenerator::
+GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
+ // Reaching here indicates a bug. Cases are:
+ // - This FieldGenerator should support packing, but this method should be
+ // overridden.
+ // - This FieldGenerator doesn't support packing, and this method should
+ // never have been called.
+ GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
+ << "called on field generator that does not support packing.";
+
+}
+
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
: descriptor_(descriptor),
field_generators_(
@@ -82,7 +96,11 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new RepeatedMessageFieldGenerator(field);
case FieldDescriptor::CPPTYPE_STRING:
- return new RepeatedStringFieldGenerator(field);
+ switch (field->options().ctype()) {
+ default: // RepeatedStringFieldGenerator handles unknown ctypes.
+ case FieldOptions::STRING:
+ return new RepeatedStringFieldGenerator(field);
+ }
case FieldDescriptor::CPPTYPE_ENUM:
return new RepeatedEnumFieldGenerator(field);
default:
@@ -93,7 +111,11 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new MessageFieldGenerator(field);
case FieldDescriptor::CPPTYPE_STRING:
- return new StringFieldGenerator(field);
+ switch (field->options().ctype()) {
+ default: // StringFieldGenerator handles unknown ctypes.
+ case FieldOptions::STRING:
+ return new StringFieldGenerator(field);
+ }
case FieldDescriptor::CPPTYPE_ENUM:
return new EnumFieldGenerator(field);
default:
@@ -110,6 +132,7 @@ const FieldGenerator& FieldGeneratorMap::get(
return *field_generators_[field->index()];
}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 00ec2c7c..c303a337 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -118,6 +118,11 @@ class FieldGenerator {
// message's MergeFromCodedStream() method.
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
+ // Generate lines to decode this field from a packed value, which will be
+ // placed inside the message's MergeFromCodedStream() method.
+ virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer)
+ const;
+
// Generate lines to serialize this field, which are placed within the
// message's SerializeWithCachedSizes() method.
virtual void GenerateSerializeWithCachedSizes(io::Printer* printer) const = 0;
@@ -153,6 +158,7 @@ class FieldGeneratorMap {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 51859bb3..80da7e40 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/compiler/cpp/cpp_extension.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_message.h>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
@@ -93,12 +94,14 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// Generate top of header.
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
"\n"
"#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
"#define PROTOBUF_$filename_identifier$__INCLUDED\n"
"\n"
"#include <string>\n"
"\n",
+ "filename", file_->name(),
"filename_identifier", filename_identifier);
printer->Print(
@@ -132,19 +135,23 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
if (HasDescriptorMethods(file_)) {
printer->Print(
"#include <google/protobuf/generated_message_reflection.h>\n");
+ }
- if (file_->service_count() > 0) {
- printer->Print(
- "#include <google/protobuf/service.h>\n");
- }
+ if (HasGenericServices(file_)) {
+ printer->Print(
+ "#include <google/protobuf/service.h>\n");
}
+
for (int i = 0; i < file_->dependency_count(); i++) {
printer->Print(
"#include \"$dependency$.pb.h\"\n",
"dependency", StripProto(file_->dependency(i)->name()));
}
+ printer->Print(
+ "// @@protoc_insertion_point(includes)\n");
+
// Open namespace.
GenerateNamespaceOpeners(printer);
@@ -198,7 +205,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(kThickSeparator);
printer->Print("\n");
- if (HasDescriptorMethods(file_)) {
+ if (HasGenericServices(file_)) {
// Generate service definitions.
for (int i = 0; i < file_->service_count(); i++) {
if (i > 0) {
@@ -232,6 +239,10 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
message_generators_[i]->GenerateInlineMethods(printer);
}
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+
// Close up namespace.
GenerateNamespaceClosers(printer);
@@ -255,11 +266,15 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(
"\n"
"} // namespace google\n} // namespace protobuf\n"
- "#endif // SWIG\n"
- "\n");
+ "#endif // SWIG\n");
}
printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n"
+ "\n");
+
+ printer->Print(
"#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
"filename_identifier", filename_identifier);
}
@@ -285,6 +300,9 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"#include <google/protobuf/wire_format.h>\n");
}
+ printer->Print(
+ "// @@protoc_insertion_point(includes)\n");
+
GenerateNamespaceOpeners(printer);
if (HasDescriptorMethods(file_)) {
@@ -300,10 +318,13 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
"name", ClassName(file_->enum_type(i), false));
}
- for (int i = 0; i < file_->service_count(); i++) {
- printer->Print(
- "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
- "name", file_->service(i)->name());
+
+ if (HasGenericServices(file_)) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ printer->Print(
+ "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
+ "name", file_->service(i)->name());
+ }
}
printer->Print(
@@ -329,7 +350,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
message_generators_[i]->GenerateClassMethods(printer);
}
- if (HasDescriptorMethods(file_)) {
+ if (HasGenericServices(file_)) {
// Generate services.
for (int i = 0; i < file_->service_count(); i++) {
if (i == 0) printer->Print("\n");
@@ -344,7 +365,15 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
extension_generators_[i]->GenerateDefinition(printer);
}
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+
GenerateNamespaceClosers(printer);
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n");
}
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
@@ -397,8 +426,10 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
for (int i = 0; i < file_->enum_type_count(); i++) {
enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
}
- for (int i = 0; i < file_->service_count(); i++) {
- service_generators_[i]->GenerateDescriptorInitializer(printer, i);
+ if (HasGenericServices(file_)) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ service_generators_[i]->GenerateDescriptorInitializer(printer, i);
+ }
}
printer->Outdent();
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 723a8b45..e3df88b0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -32,6 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <limits>
#include <vector>
#include <google/protobuf/stubs/hash.h>
@@ -40,6 +41,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
+
namespace google {
namespace protobuf {
namespace compiler {
@@ -111,6 +113,7 @@ const char kThinSeparator[] =
"// -------------------------------------------------------------------\n";
string ClassName(const Descriptor* descriptor, bool qualified) {
+
// Find "outer", the descriptor of the top-level message in which
// "descriptor" is embedded.
const Descriptor* outer = descriptor;
@@ -141,6 +144,12 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
}
}
+
+string SuperClassName(const Descriptor* descriptor) {
+ return HasDescriptorMethods(descriptor->file()) ?
+ "::google::protobuf::Message" : "::google::protobuf::MessageLite";
+}
+
string FieldName(const FieldDescriptor* field) {
string result = field->name();
LowerString(&result);
@@ -166,6 +175,12 @@ string FieldConstantName(const FieldDescriptor *field) {
return result;
}
+string FieldMessageTypeName(const FieldDescriptor* field) {
+ // Note: The Google-internal version of Protocol Buffers uses this function
+ // as a hook point for hacks to support legacy code.
+ return ClassName(field->message_type(), true);
+}
+
string StripProto(const string& filename) {
if (HasSuffixString(filename, ".protodevel")) {
return StripSuffixString(filename, ".protodevel");
@@ -235,17 +250,37 @@ string DefaultValue(const FieldDescriptor* field) {
return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
case FieldDescriptor::CPPTYPE_UINT64:
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
- case FieldDescriptor::CPPTYPE_DOUBLE:
- return SimpleDtoa(field->default_value_double());
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
+ double value = field->default_value_double();
+ if (value == numeric_limits<double>::infinity()) {
+ return "::google::protobuf::internal::Infinity()";
+ } else if (value == -numeric_limits<double>::infinity()) {
+ return "-::google::protobuf::internal::Infinity()";
+ } else if (value != value) {
+ return "::google::protobuf::internal::NaN()";
+ } else {
+ return SimpleDtoa(value);
+ }
+ }
case FieldDescriptor::CPPTYPE_FLOAT:
{
- // If floating point value contains a period (.) or an exponent (either
- // E or e), then append suffix 'f' to make it a floating-point literal.
- string float_value = SimpleFtoa(field->default_value_float());
- if (float_value.find_first_of(".eE") != string::npos) {
- float_value.push_back('f');
+ float value = field->default_value_float();
+ if (value == numeric_limits<float>::infinity()) {
+ return "static_cast<float>(::google::protobuf::internal::Infinity())";
+ } else if (value == -numeric_limits<float>::infinity()) {
+ return "static_cast<float>(-::google::protobuf::internal::Infinity())";
+ } else if (value != value) {
+ return "static_cast<float>(::google::protobuf::internal::NaN())";
+ } else {
+ string float_value = SimpleFtoa(value);
+ // If floating point value contains a period (.) or an exponent
+ // (either E or e), then append suffix 'f' to make it a float
+ // literal.
+ if (float_value.find_first_of(".eE") != string::npos) {
+ float_value.push_back('f');
+ }
+ return float_value;
}
- return float_value;
}
case FieldDescriptor::CPPTYPE_BOOL:
return field->default_value_bool() ? "true" : "false";
@@ -259,7 +294,7 @@ string DefaultValue(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_STRING:
return "\"" + CEscape(field->default_value_string()) + "\"";
case FieldDescriptor::CPPTYPE_MESSAGE:
- return ClassName(field->message_type(), true) + "::default_instance()";
+ return FieldMessageTypeName(field) + "::default_instance()";
}
// Can't actually get here; make compiler happy. (We could add a default
// case above but then we wouldn't get the nice compiler warning when a
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 83e12501..f99b5fe8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -60,6 +60,8 @@ extern const char kThinSeparator[];
string ClassName(const Descriptor* descriptor, bool qualified);
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
+string SuperClassName(const Descriptor* descriptor);
+
// Get the (unqualified) name that should be used for this field in C++ code.
// The name is coerced to lower-case to emulate proto1 behavior. People
// should be using lowercase-with-underscores style for proto field names
@@ -77,6 +79,10 @@ inline const Descriptor* FieldScope(const FieldDescriptor* field) {
field->extension_scope() : field->containing_type();
}
+// Returns the fully-qualified type name field->message_type(). Usually this
+// is just ClassName(field->message_type(), true);
+string FieldMessageTypeName(const FieldDescriptor* field);
+
// Strips ".proto" or ".protodevel" from the end of a filename.
string StripProto(const string& filename);
@@ -107,33 +113,41 @@ string GlobalAssignDescriptorsName(const string& filename);
string GlobalShutdownFileName(const string& filename);
// Do message classes in this file keep track of unknown fields?
-inline const bool HasUnknownFields(const FileDescriptor *file) {
+inline bool HasUnknownFields(const FileDescriptor *file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
// Does this file have generated parsing, serialization, and other
// standard methods for which reflection-based fallback implementations exist?
-inline const bool HasGeneratedMethods(const FileDescriptor *file) {
+inline bool HasGeneratedMethods(const FileDescriptor *file) {
return file->options().optimize_for() != FileOptions::CODE_SIZE;
}
// Do message classes in this file have descriptor and refelction methods?
-inline const bool HasDescriptorMethods(const FileDescriptor *file) {
+inline bool HasDescriptorMethods(const FileDescriptor *file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file) {
+ return file->service_count() > 0 &&
+ file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+ file->options().cc_generic_services();
+}
+
// Should string fields in this file verify that their contents are UTF-8?
-inline const bool HasUtf8Verification(const FileDescriptor* file) {
+inline bool HasUtf8Verification(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
// Should we generate a separate, super-optimized code path for serializing to
// flat arrays? We don't do this in Lite mode because we'd rather reduce code
// size.
-inline const bool HasFastArraySerialization(const FileDescriptor* file) {
+inline bool HasFastArraySerialization(const FileDescriptor* file) {
return file->options().optimize_for() == FileOptions::SPEED;
}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index eb836418..cbdcce8f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -308,11 +308,10 @@ GenerateClassDefinition(io::Printer* printer) {
} else {
vars["dllexport"] = dllexport_decl_ + " ";
}
- vars["superclass"] = HasDescriptorMethods(descriptor_->file()) ?
- "Message" : "MessageLite";
+ vars["superclass"] = SuperClassName(descriptor_);
printer->Print(vars,
- "class $dllexport$$classname$ : public ::google::protobuf::$superclass$ {\n"
+ "class $dllexport$$classname$ : public $superclass$ {\n"
" public:\n");
printer->Indent();
@@ -349,6 +348,10 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print(vars,
"static const $classname$& default_instance();\n"
+ "\n");
+
+
+ printer->Print(vars,
"void Swap($classname$* other);\n"
"\n"
"// implements Message ----------------------------------------------\n"
@@ -387,7 +390,7 @@ GenerateClassDefinition(io::Printer* printer) {
"private:\n"
"void SharedCtor();\n"
"void SharedDtor();\n"
- "void SetCachedSize(int size) const { _cached_size_ = size; }\n"
+ "void SetCachedSize(int size) const;\n"
"public:\n"
"\n");
@@ -436,6 +439,11 @@ GenerateClassDefinition(io::Printer* printer) {
extension_generators_[i]->GenerateDeclaration(printer);
}
+
+ printer->Print(
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
// Generate private members for fields.
printer->Outdent();
printer->Print(" private:\n");
@@ -623,6 +631,7 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) {
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
nested_generators_[i]->GenerateDefaultInstanceAllocator(printer);
}
+
}
void MessageGenerator::
@@ -751,6 +760,7 @@ GenerateClassMethods(io::Printer* printer) {
"classname", classname_,
"type_name", descriptor_->full_name());
}
+
}
void MessageGenerator::
@@ -833,9 +843,8 @@ GenerateSharedDestructorCode(io::Printer* printer) {
void MessageGenerator::
GenerateStructors(io::Printer* printer) {
- string superclass = HasDescriptorMethods(descriptor_->file()) ?
- "Message" : "MessageLite";
-
+ string superclass = SuperClassName(descriptor_);
+
// Generate the default constructor.
printer->Print(
"$classname$::$classname$()\n"
@@ -864,7 +873,7 @@ GenerateStructors(io::Printer* printer) {
printer->Print(
" $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
"name", FieldName(field),
- "type", ClassName(field->message_type(), true));
+ "type", FieldMessageTypeName(field));
}
}
printer->Print(
@@ -896,6 +905,15 @@ GenerateStructors(io::Printer* printer) {
// Generate the shared destructor code.
GenerateSharedDestructorCode(printer);
+ // Generate SetCachedSize.
+ printer->Print(
+ "void $classname$::SetCachedSize(int size) const {\n"
+ " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
+ " _cached_size_ = size;\n"
+ " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
+ "}\n",
+ "classname", classname_);
+
// Only generate this member if it's not disabled.
if (HasDescriptorMethods(descriptor_->file()) &&
!descriptor_->options().no_standard_descriptor_accessor()) {
@@ -924,6 +942,7 @@ GenerateStructors(io::Printer* printer) {
"classname", classname_,
"adddescriptorsname",
GlobalAddDescriptorsName(descriptor_->file()->name()));
+
}
void MessageGenerator::
@@ -1237,12 +1256,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
PrintFieldComment(printer, field);
printer->Print(
- "case $number$: {\n"
- " if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=\n"
- " ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n"
- " goto handle_uninterpreted;\n"
- " }\n",
- "number", SimpleItoa(field->number()),
+ "case $number$: {\n",
+ "number", SimpleItoa(field->number()));
+ printer->Indent();
+ const FieldGenerator& field_generator = field_generators_.get(field);
+
+ // Emit code to parse the common, expected case.
+ printer->Print(
+ "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
+ " ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n",
"wiretype", kWireTypeNames[WireFormat::WireTypeForField(field)]);
if (i > 0 || (field->is_repeated() && !field->options().packed())) {
@@ -1252,8 +1274,38 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
printer->Indent();
+ if (field->options().packed()) {
+ field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
+ } else {
+ field_generator.GenerateMergeFromCodedStream(printer);
+ }
+ printer->Outdent();
- field_generators_.get(field).GenerateMergeFromCodedStream(printer);
+ // Emit code to parse unexpectedly packed or unpacked values.
+ if (field->is_packable() && field->options().packed()) {
+ printer->Print(
+ "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n"
+ " == ::google::protobuf::internal::WireFormatLite::\n"
+ " WIRETYPE_$wiretype$) {\n",
+ "wiretype",
+ kWireTypeNames[WireFormat::WireTypeForFieldType(field->type())]);
+ printer->Indent();
+ field_generator.GenerateMergeFromCodedStream(printer);
+ printer->Outdent();
+ } else if (field->is_packable() && !field->options().packed()) {
+ printer->Print(
+ "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n"
+ " == ::google::protobuf::internal::WireFormatLite::\n"
+ " WIRETYPE_LENGTH_DELIMITED) {\n");
+ printer->Indent();
+ field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
+ printer->Outdent();
+ }
+
+ printer->Print(
+ "} else {\n"
+ " goto handle_uninterpreted;\n"
+ "}\n");
// switch() is slow since it can't be predicted well. Insert some if()s
// here that attempt to predict the next tag.
@@ -1434,18 +1486,6 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) {
"classname", classname_);
printer->Indent();
- if (HasFastArraySerialization(descriptor_->file())) {
- printer->Print(
- "::google::protobuf::uint8* raw_buffer = "
- "output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n"
- "if (raw_buffer != NULL) {\n"
- " $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n"
- " return;\n"
- "}\n"
- "\n",
- "classname", classname_);
- }
-
GenerateSerializeWithCachedSizesBody(printer, false);
printer->Outdent();
@@ -1555,7 +1595,9 @@ GenerateByteSize(io::Printer* printer) {
" ComputeUnknownMessageSetItemsSize(unknown_fields());\n");
}
printer->Print(
+ " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
" _cached_size_ = total_size;\n"
+ " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
" return total_size;\n"
"}\n");
return;
@@ -1647,7 +1689,9 @@ GenerateByteSize(io::Printer* printer) {
// exact same value, it works on all common processors. In a future version
// of C++, _cached_size_ should be made into an atomic<int>.
printer->Print(
+ "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
"_cached_size_ = total_size;\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"return total_size;\n");
printer->Outdent();
@@ -1719,6 +1763,7 @@ GenerateIsInitialized(io::Printer* printer) {
"}\n");
}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index f1c57141..04778f6d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -150,6 +150,7 @@ class MessageGenerator {
io::Printer* printer, const Descriptor::ExtensionRange* range,
bool unbounded);
+
const Descriptor* descriptor_;
string classname_;
string dllexport_decl_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index 059fba6e..c04bdc66 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -47,7 +47,11 @@ namespace {
void SetMessageVariables(const FieldDescriptor* descriptor,
map<string, string>* variables) {
SetCommonFieldVariables(descriptor, variables);
- (*variables)["type"] = ClassName(descriptor->message_type(), true);
+ (*variables)["type"] = FieldMessageTypeName(descriptor);
+ (*variables)["stream_writer"] = (*variables)["declared_type"] +
+ (HasFastArraySerialization(descriptor->message_type()->file()) ?
+ "MaybeToArray" :
+ "");
}
} // namespace
@@ -125,7 +129,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
- "::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n"
+ "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
" $number$, this->$name$(), output);\n");
}
@@ -164,26 +168,19 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const"
- "$deprecation$;\n"
- "inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$()"
- "$deprecation$;\n"
"inline const $type$& $name$(int index) const$deprecation$;\n"
"inline $type$* mutable_$name$(int index)$deprecation$;\n"
"inline $type$* add_$name$()$deprecation$;\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const$deprecation$;\n"
+ "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ " mutable_$name$()$deprecation$;\n");
}
void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- "$classname$::$name$() const {\n"
- " return $name$_;\n"
- "}\n"
- "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
- "$classname$::mutable_$name$() {\n"
- " return &$name$_;\n"
- "}\n"
"inline const $type$& $classname$::$name$(int index) const {\n"
" return $name$_.Get(index);\n"
"}\n"
@@ -193,6 +190,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"inline $type$* $classname$::add_$name$() {\n"
" return $name$_.Add();\n"
"}\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ "$classname$::$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "$classname$::mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n");
}
void RepeatedMessageFieldGenerator::
@@ -232,7 +238,7 @@ void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n"
- " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n"
+ " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
" $number$, this->$name$(i), output);\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 81f5ce07..a69c48b5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -84,10 +84,14 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
SetCommonFieldVariables(descriptor, variables);
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
(*variables)["default"] = DefaultValue(descriptor);
+ (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
int fixed_size = FixedSize(descriptor->type());
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
}
+ (*variables)["wire_format_field_type"] =
+ "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
+ static_cast<FieldDescriptorProto_Type>(descriptor->type()));
}
} // namespace
@@ -149,8 +153,9 @@ GenerateConstructorCode(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
- " input, &$name$_));\n"
+ "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+ " $type$, $wire_format_field_type$>(\n"
+ " input, &$name$_)));\n"
"_set_bit($index$);\n");
}
@@ -188,6 +193,14 @@ RepeatedPrimitiveFieldGenerator::
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
: descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, &variables_);
+
+ if (descriptor->options().packed()) {
+ variables_["packed_reader"] = "ReadPackedPrimitive";
+ variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
+ } else {
+ variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
+ variables_["repeated_reader"] = "ReadRepeatedPrimitive";
+ }
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
@@ -205,25 +218,19 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const\n"
- " $deprecation$;\n"
- "inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$()$deprecation$;\n"
"inline $type$ $name$(int index) const$deprecation$;\n"
"inline void set_$name$(int index, $type$ value)$deprecation$;\n"
"inline void add_$name$($type$ value)$deprecation$;\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ " $name$() const$deprecation$;\n"
+ "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ " mutable_$name$()$deprecation$;\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
- "$classname$::$name$() const {\n"
- " return $name$_;\n"
- "}\n"
- "inline ::google::protobuf::RepeatedField< $type$ >*\n"
- "$classname$::mutable_$name$() {\n"
- " return &$name$_;\n"
- "}\n"
"inline $type$ $classname$::$name$(int index) const {\n"
" return $name$_.Get(index);\n"
"}\n"
@@ -233,6 +240,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"inline void $classname$::add_$name$($type$ value) {\n"
" $name$_.Add(value);\n"
"}\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ "$classname$::$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ "$classname$::mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n");
}
void RepeatedPrimitiveFieldGenerator::
@@ -257,30 +273,18 @@ GenerateConstructorCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
- printer->Print("{\n");
- printer->Indent();
- printer->Print(variables_,
- "::google::protobuf::uint32 length;\n"
- "DO_(input->ReadVarint32(&length));\n"
- "::google::protobuf::io::CodedInputStream::Limit limit =\n"
- " input->PushLimit(length);\n"
- "while (input->BytesUntilLimit() > 0) {\n"
- " $type$ value;\n"
- " DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
- " input, &value));\n"
- " add_$name$(value);\n"
- "}\n"
- "input->PopLimit(limit);\n");
- printer->Outdent();
- printer->Print("}\n");
- } else {
- printer->Print(variables_,
- "$type$ value;\n"
- "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
- " input, &value));\n"
- "add_$name$(value);\n");
- }
+ printer->Print(variables_,
+ "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
+ " $type$, $wire_format_field_type$>(\n"
+ " $tag_size$, $tag$, input, this->mutable_$name$())));\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
+ printer->Print(variables_,
+ "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
+ " $type$, $wire_format_field_type$>(\n"
+ " input, this->mutable_$name$())));\n");
}
void RepeatedPrimitiveFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 6b96614c..8fcd74ae 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -83,6 +83,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
+ void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 72258e89..ea6809a9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -91,7 +91,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
// files that applied the ctype. The field can still be accessed via the
// reflection interface since the reflection interface is independent of
// the string's underlying representation.
- if (descriptor_->options().has_ctype()) {
+ if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(
" private:\n"
@@ -107,7 +107,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"$deprecation$;\n"
"inline ::std::string* mutable_$name$()$deprecation$;\n");
- if (descriptor_->options().has_ctype()) {
+ if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
@@ -278,7 +278,7 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
// See comment above about unknown ctypes.
- if (descriptor_->options().has_ctype()) {
+ if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(
" private:\n"
@@ -287,10 +287,6 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
- "$deprecation$;\n"
- "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
- "$deprecation$;\n"
"inline const ::std::string& $name$(int index) const$deprecation$;\n"
"inline ::std::string* mutable_$name$(int index)$deprecation$;\n"
"inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
@@ -304,7 +300,13 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"inline void add_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n");
- if (descriptor_->options().has_ctype()) {
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
+ "$deprecation$;\n"
+ "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+ "$deprecation$;\n");
+
+ if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
@@ -314,14 +316,6 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
- "$classname$::$name$() const {\n"
- " return $name$_;\n"
- "}\n"
- "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
- "$classname$::mutable_$name$() {\n"
- " return &$name$_;\n"
- "}\n"
"inline const ::std::string& $classname$::$name$(int index) const {\n"
" return $name$_.Get(index);\n"
"}\n"
@@ -353,6 +347,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
" $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
"}\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
+ "$classname$::$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
+ "$classname$::mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n");
}
void RepeatedStringFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index d7575c05..a7e852de 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -49,6 +49,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_optimize_for.pb.h>
#include <google/protobuf/unittest_embed_optimize_for.pb.h>
+#include <google/protobuf/unittest_no_generic_services.pb.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h>
#include <google/protobuf/compiler/importer.h>
@@ -154,6 +155,16 @@ TEST(GeneratedMessageTest, FloatingPointDefaults) {
EXPECT_EQ(-1.5f, extreme_default.negative_float());
EXPECT_EQ(2.0e8f, extreme_default.large_float());
EXPECT_EQ(-8e-28f, extreme_default.small_negative_float());
+ EXPECT_EQ(numeric_limits<double>::infinity(),
+ extreme_default.inf_double());
+ EXPECT_EQ(-numeric_limits<double>::infinity(),
+ extreme_default.neg_inf_double());
+ EXPECT_TRUE(extreme_default.nan_double() != extreme_default.nan_double());
+ EXPECT_EQ(numeric_limits<float>::infinity(),
+ extreme_default.inf_float());
+ EXPECT_EQ(-numeric_limits<float>::infinity(),
+ extreme_default.neg_inf_float());
+ EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float());
}
TEST(GeneratedMessageTest, Accessors) {
@@ -779,22 +790,39 @@ TEST(GeneratedEnumTest, IsValidValue) {
}
TEST(GeneratedEnumTest, MinAndMax) {
- EXPECT_EQ(unittest::TestAllTypes::FOO,unittest::TestAllTypes::NestedEnum_MIN);
- EXPECT_EQ(unittest::TestAllTypes::BAZ,unittest::TestAllTypes::NestedEnum_MAX);
+ EXPECT_EQ(unittest::TestAllTypes::FOO,
+ unittest::TestAllTypes::NestedEnum_MIN);
+ EXPECT_EQ(unittest::TestAllTypes::BAZ,
+ unittest::TestAllTypes::NestedEnum_MAX);
+ EXPECT_EQ(4, unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
EXPECT_EQ(unittest::FOREIGN_FOO, unittest::ForeignEnum_MIN);
EXPECT_EQ(unittest::FOREIGN_BAZ, unittest::ForeignEnum_MAX);
+ EXPECT_EQ(7, unittest::ForeignEnum_ARRAYSIZE);
EXPECT_EQ(1, unittest::TestEnumWithDupValue_MIN);
EXPECT_EQ(3, unittest::TestEnumWithDupValue_MAX);
+ EXPECT_EQ(4, unittest::TestEnumWithDupValue_ARRAYSIZE);
EXPECT_EQ(unittest::SPARSE_E, unittest::TestSparseEnum_MIN);
EXPECT_EQ(unittest::SPARSE_C, unittest::TestSparseEnum_MAX);
+ EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE);
- // Make sure we can use _MIN and _MAX as switch cases.
- switch(unittest::SPARSE_A) {
+ // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE.
+ void* nullptr = 0; // NULL may be integer-type, not pointer-type.
+ EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MIN);
+ EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MAX);
+ EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
+
+ EXPECT_NE(nullptr, &unittest::ForeignEnum_MIN);
+ EXPECT_NE(nullptr, &unittest::ForeignEnum_MAX);
+ EXPECT_NE(nullptr, &unittest::ForeignEnum_ARRAYSIZE);
+
+ // Make sure we can use _MIN, _MAX and _ARRAYSIZE as switch cases.
+ switch (unittest::SPARSE_A) {
case unittest::TestSparseEnum_MIN:
case unittest::TestSparseEnum_MAX:
+ case unittest::TestSparseEnum_ARRAYSIZE:
break;
default:
break;
@@ -1136,6 +1164,43 @@ TEST_F(GeneratedServiceTest, NotImplemented) {
EXPECT_TRUE(controller.called_);
}
+} // namespace cpp_unittest
+} // namespace cpp
+} // namespace compiler
+
+namespace no_generic_services_test {
+ // Verify that no class called "TestService" was defined in
+ // unittest_no_generic_services.pb.h by defining a different type by the same
+ // name. If such a service was generated, this will not compile.
+ struct TestService {
+ int i;
+ };
+}
+
+namespace compiler {
+namespace cpp {
+namespace cpp_unittest {
+
+TEST_F(GeneratedServiceTest, NoGenericServices) {
+ // Verify that non-services in unittest_no_generic_services.proto were
+ // generated.
+ no_generic_services_test::TestMessage message;
+ message.set_a(1);
+ message.SetExtension(no_generic_services_test::test_extension, 123);
+ no_generic_services_test::TestEnum e = no_generic_services_test::FOO;
+ EXPECT_EQ(e, 1);
+
+ // Verify that a ServiceDescriptor is generated for the service even if the
+ // class itself is not.
+ const FileDescriptor* file =
+ no_generic_services_test::TestMessage::descriptor()->file();
+
+ ASSERT_EQ(1, file->service_count());
+ EXPECT_EQ("TestService", file->service(0)->name());
+ ASSERT_EQ(1, file->service(0)->method_count());
+ EXPECT_EQ("Foo", file->service(0)->method(0)->name());
+}
+
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
// ===================================================================
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 8ade50c9..85e39f53 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -223,6 +223,11 @@ void EnumGenerator::Generate(io::Printer* printer) {
"file", ClassName(descriptor_->file()));
}
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
printer->Outdent();
printer->Print("}\n\n");
}
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index dc36e06e..af6b1cd2 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -62,7 +62,7 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
- internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
}
} // namespace
@@ -81,7 +81,7 @@ void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private boolean has$capitalized_name$;\n"
- "private $type$ $name$_ = $default$;\n"
+ "private $type$ $name$_;\n"
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
"public $type$ get$capitalized_name$() { return $name$_; }\n");
}
@@ -111,6 +111,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void EnumFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void EnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -241,6 +246,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void RepeatedEnumFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
@@ -262,15 +272,6 @@ GenerateBuildingCode(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- // If packed, set up the while loop
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "int length = input.readRawVarint32();\n"
- "int oldLimit = input.pushLimit(length);\n"
- "while(input.getBytesUntilLimit() > 0) {\n");
- printer->Indent();
- }
-
// Read and store the enum
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
@@ -287,13 +288,24 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
" add$capitalized_name$(value);\n"
"}\n");
+}
- if (descriptor_->options().packed()) {
- printer->Outdent();
- printer->Print(variables_,
- "}\n"
- "input.popLimit(oldLimit);\n");
- }
+void RepeatedEnumFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ // Wrap GenerateParsingCode's contents with a while loop.
+
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int oldLimit = input.pushLimit(length);\n"
+ "while(input.getBytesUntilLimit() > 0) {\n");
+ printer->Indent();
+
+ GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(variables_,
+ "}\n"
+ "input.popLimit(oldLimit);\n");
}
void RepeatedEnumFieldGenerator::
diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
index 63f68153..c54a0faf 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -52,6 +52,7 @@ class EnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -75,9 +76,11 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 4403220b..5932433f 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -133,7 +133,7 @@ void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) {
vars["extendee"] = ClassName(descriptor_->containing_type());
vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_);
vars["number"] = SimpleItoa(descriptor_->number());
- vars["type_constant"] = TypeName(descriptor_->type());
+ vars["type_constant"] = TypeName(GetType(descriptor_));
vars["packed"] = descriptor_->options().packed() ? "true" : "false";
vars["enum_map"] = "null";
vars["prototype"] = "null";
@@ -208,5 +208,4 @@ void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) {
} // namespace java
} // namespace compiler
} // namespace protobuf
-
} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index f9d34ad7..978c8f33 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -46,6 +46,16 @@ namespace java {
FieldGenerator::~FieldGenerator() {}
+void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ // Reaching here indicates a bug. Cases are:
+ // - This FieldGenerator should support packing, but this method should be
+ // overridden.
+ // - This FieldGenerator doesn't support packing, and this method should
+ // never have been called.
+ GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
+ << "called on field generator that does not support packing.";
+}
+
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
: descriptor_(descriptor),
field_generators_(
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index cab463c8..f5bef7ab 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -57,9 +57,11 @@ class FieldGenerator {
virtual void GenerateMembers(io::Printer* printer) const = 0;
virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
+ virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
virtual void GenerateParsingCode(io::Printer* printer) const = 0;
+ virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 2aedde5e..7ea127c0 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -64,7 +64,7 @@ bool UsesExtensions(const Message& message) {
for (int i = 0; i < fields.size(); i++) {
if (fields[i]->is_extension()) return true;
- if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
if (fields[i]->is_repeated()) {
int size = reflection->FieldSize(message, fields[i]);
for (int j = 0; j < size; j++) {
@@ -82,6 +82,7 @@ bool UsesExtensions(const Message& message) {
return false;
}
+
} // namespace
FileGenerator::FileGenerator(const FileDescriptor* file)
@@ -134,7 +135,9 @@ void FileGenerator::Generate(io::Printer* printer) {
// fully-qualified names in the generated source.
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "\n");
+ "// source: $filename$\n"
+ "\n",
+ "filename", file_->name());
if (!java_package_.empty()) {
printer->Print(
"package $package$;\n"
@@ -178,8 +181,10 @@ void FileGenerator::Generate(io::Printer* printer) {
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i)).Generate(printer);
}
- for (int i = 0; i < file_->service_count(); i++) {
- ServiceGenerator(file_->service(i)).Generate(printer);
+ if (HasGenericServices(file_)) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ ServiceGenerator(file_->service(i)).Generate(printer);
+ }
}
}
@@ -228,6 +233,10 @@ void FileGenerator::Generate(io::Printer* printer) {
"\n"
"public static void internalForceInit() {}\n");
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(outer_class_scope)\n");
+
printer->Outdent();
printer->Print("}\n");
}
@@ -245,6 +254,7 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
// embedded raw, which is what we want.
FileDescriptorProto file_proto;
file_->CopyTo(&file_proto);
+
string file_data;
file_proto.SerializeToString(&file_data);
@@ -343,9 +353,11 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
" new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
for (int i = 0; i < file_->dependency_count(); i++) {
- printer->Print(
- " $dependency$.getDescriptor(),\n",
- "dependency", ClassName(file_->dependency(i)));
+ if (ShouldIncludeDependency(file_->dependency(i))) {
+ printer->Print(
+ " $dependency$.getDescriptor(),\n",
+ "dependency", ClassName(file_->dependency(i)));
+ }
}
printer->Print(
@@ -396,14 +408,20 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
file_->message_type(i),
output_directory, file_list);
}
- for (int i = 0; i < file_->service_count(); i++) {
- GenerateSibling<ServiceGenerator>(package_dir, java_package_,
- file_->service(i),
- output_directory, file_list);
+ if (HasGenericServices(file_)) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ GenerateSibling<ServiceGenerator>(package_dir, java_package_,
+ file_->service(i),
+ output_directory, file_list);
+ }
}
}
}
+bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) {
+ return true;
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index cb82cea2..9e35d330 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -77,6 +77,11 @@ class FileGenerator {
const string& classname() { return classname_; }
private:
+ // Returns whether the dependency should be included in the output file.
+ // Always returns true for opensource, but used internally at Google to help
+ // improve compatibility with version 1 of protocol buffers.
+ bool ShouldIncludeDependency(const FileDescriptor* descriptor);
+
const FileDescriptor* file_;
string java_package_;
string classname_;
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 8ed3affb..745b55ae 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -45,6 +45,7 @@ namespace protobuf {
namespace compiler {
namespace java {
+
JavaGenerator::JavaGenerator() {}
JavaGenerator::~JavaGenerator() {}
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index dc6748e3..7ed0c3cc 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -32,6 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <limits>
#include <vector>
#include <google/protobuf/compiler/java/java_helpers.h>
@@ -57,7 +58,7 @@ const string& FieldName(const FieldDescriptor* field) {
// Groups are hacky: The name of the field is just the lower-cased name
// of the group type. In Java, though, we would like to retain the original
// capitalization of the type name.
- if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
return field->message_type()->name();
} else {
return field->name();
@@ -178,8 +179,12 @@ string FieldConstantName(const FieldDescriptor *field) {
return name;
}
-JavaType GetJavaType(FieldDescriptor::Type field_type) {
- switch (field_type) {
+FieldDescriptor::Type GetType(const FieldDescriptor* field) {
+ return field->type();
+}
+
+JavaType GetJavaType(const FieldDescriptor* field) {
+ switch (GetType(field)) {
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SINT32:
@@ -254,7 +259,7 @@ bool AllAscii(const string& text) {
}
string DefaultValue(const FieldDescriptor* field) {
- // Switch on cpp_type since we need to know which default_value_* method
+ // Switch on CppType since we need to know which default_value_* method
// of FieldDescriptor to call.
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
@@ -267,14 +272,34 @@ string DefaultValue(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_UINT64:
return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
"L";
- case FieldDescriptor::CPPTYPE_DOUBLE:
- return SimpleDtoa(field->default_value_double()) + "D";
- case FieldDescriptor::CPPTYPE_FLOAT:
- return SimpleFtoa(field->default_value_float()) + "F";
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
+ double value = field->default_value_double();
+ if (value == numeric_limits<double>::infinity()) {
+ return "Double.POSITIVE_INFINITY";
+ } else if (value == -numeric_limits<double>::infinity()) {
+ return "Double.NEGATIVE_INFINITY";
+ } else if (value != value) {
+ return "Double.NaN";
+ } else {
+ return SimpleDtoa(value) + "D";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = field->default_value_float();
+ if (value == numeric_limits<float>::infinity()) {
+ return "Float.POSITIVE_INFINITY";
+ } else if (value == -numeric_limits<float>::infinity()) {
+ return "Float.NEGATIVE_INFINITY";
+ } else if (value != value) {
+ return "Float.NaN";
+ } else {
+ return SimpleFtoa(value) + "F";
+ }
+ }
case FieldDescriptor::CPPTYPE_BOOL:
return field->default_value_bool() ? "true" : "false";
case FieldDescriptor::CPPTYPE_STRING:
- if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
if (field->has_default_value()) {
// See comments in Internal.java for gory details.
return strings::Substitute(
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index f1b643c3..3c8974c9 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -93,6 +93,11 @@ string ClassName(const FileDescriptor* descriptor);
// number constant.
string FieldConstantName(const FieldDescriptor *field);
+// Returns the type of the FieldDescriptor.
+// This does nothing interesting for the open source release, but is used for
+// hacks that improve compatability with version 1 protocol buffers at Google.
+FieldDescriptor::Type GetType(const FieldDescriptor* field);
+
enum JavaType {
JAVATYPE_INT,
JAVATYPE_LONG,
@@ -105,11 +110,7 @@ enum JavaType {
JAVATYPE_MESSAGE
};
-JavaType GetJavaType(FieldDescriptor::Type field_type);
-
-inline JavaType GetJavaType(const FieldDescriptor* field) {
- return GetJavaType(field->type());
-}
+JavaType GetJavaType(const FieldDescriptor* field);
// Get the fully-qualified class name for a boxed primitive type, e.g.
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
@@ -145,6 +146,13 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
FileOptions::LITE_RUNTIME;
}
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file) {
+ return file->service_count() > 0 &&
+ file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+ file->options().java_generic_services();
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 99b57c95..1f8e209c 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -127,7 +127,7 @@ static bool HasRequiredFields(
if (field->is_required()) {
return true;
}
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
if (HasRequiredFields(field->message_type(), already_seen)) {
return true;
}
@@ -292,9 +292,14 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Indent();
printer->Print(
"// Use $classname$.newBuilder() to construct.\n"
- "private $classname$() {}\n"
+ "private $classname$() {\n"
+ " initFields();\n"
+ "}\n"
+ // Used when constructing the default instance, which cannot be initialized
+ // immediately because it may cyclically refer to other default instances.
+ "private $classname$(boolean noInit) {}\n"
"\n"
- "private static final $classname$ defaultInstance = new $classname$();\n"
+ "private static final $classname$ defaultInstance;\n"
"public static $classname$ getDefaultInstance() {\n"
" return defaultInstance;\n"
"}\n"
@@ -344,6 +349,17 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Print("\n");
}
+ // Called by the constructor, except in the case of the default instance,
+ // in which case this is called by static init code later on.
+ printer->Print("private void initFields() {\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitializationCode(printer);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+
if (HasGeneratedMethods(descriptor_)) {
GenerateIsInitialized(printer);
GenerateMessageSerializationMethods(printer);
@@ -352,25 +368,23 @@ void MessageGenerator::Generate(io::Printer* printer) {
GenerateParseFromMethods(printer);
GenerateBuilder(printer);
- if (HasDescriptorMethods(descriptor_)) {
- // Force the static initialization code for the file to run, since it may
- // initialize static variables declared in this class.
- printer->Print(
- "\n"
- "static {\n"
- " $file$.getDescriptor();\n"
- "}\n",
- "file", ClassName(descriptor_->file()));
- }
-
// Force initialization of outer class. Otherwise, nested extensions may
- // not be initialized.
+ // not be initialized. Also carefully initialize the default instance in
+ // such a way that it doesn't conflict with other initialization.
printer->Print(
"\n"
"static {\n"
+ " defaultInstance = new $classname$(true);\n"
" $file$.internalForceInit();\n"
+ " defaultInstance.initFields();\n"
"}\n",
- "file", ClassName(descriptor_->file()));
+ "file", ClassName(descriptor_->file()),
+ "classname", descriptor_->name());
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
printer->Outdent();
printer->Print("}\n\n");
@@ -529,14 +543,23 @@ GenerateParseFromMethods(io::Printer* printer) {
"}\n"
"public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeDelimitedFrom(input).buildParsed();\n"
+ " Builder builder = newBuilder();\n"
+ " if (builder.mergeDelimitedFrom(input)) {\n"
+ " return builder.buildParsed();\n"
+ " } else {\n"
+ " return null;\n"
+ " }\n"
"}\n"
"public static $classname$ parseDelimitedFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n"
- " .buildParsed();\n"
+ " Builder builder = newBuilder();\n"
+ " if (builder.mergeDelimitedFrom(input, extensionRegistry)) {\n"
+ " return builder.buildParsed();\n"
+ " } else {\n"
+ " return null;\n"
+ " }\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input)\n"
@@ -827,7 +850,7 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
uint32 tag = WireFormatLite::MakeTag(field->number(),
- WireFormat::WireTypeForField(field));
+ WireFormat::WireTypeForFieldType(field->type()));
printer->Print(
"case $tag$: {\n",
@@ -840,6 +863,24 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
printer->Print(
" break;\n"
"}\n");
+
+ if (field->is_packable()) {
+ // To make packed = true wire compatible, we generate parsing code from a
+ // packed version of this field regardless of field->options().packed().
+ uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(packed_tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
}
printer->Outdent();
@@ -875,7 +916,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
// Now check that all embedded messages are initialized.
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
HasRequiredFields(field->message_type())) {
switch (field->label()) {
case FieldDescriptor::LABEL_REQUIRED:
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index bbddddde..71edc024 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -59,7 +59,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["type"] = ClassName(descriptor->message_type());
(*variables)["group_or_message"] =
- (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
+ (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
"Group" : "Message";
}
@@ -79,7 +79,7 @@ void MessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private boolean has$capitalized_name$;\n"
- "private $type$ $name$_ = $type$.getDefaultInstance();\n"
+ "private $type$ $name$_;\n"
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
"public $type$ get$capitalized_name$() { return $name$_; }\n");
}
@@ -125,6 +125,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
+}
+
+void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -145,7 +150,7 @@ GenerateParsingCode(io::Printer* printer) const {
" subBuilder.mergeFrom(get$capitalized_name$());\n"
"}\n");
- if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup($number$, subBuilder, extensionRegistry);\n");
} else {
@@ -262,6 +267,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
@@ -286,7 +296,7 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"$type$.Builder subBuilder = $type$.newBuilder();\n");
- if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup($number$, subBuilder, extensionRegistry);\n");
} else {
diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h
index 90a90976..66bdd884 100644
--- a/src/google/protobuf/compiler/java/java_message_field.h
+++ b/src/google/protobuf/compiler/java/java_message_field.h
@@ -52,6 +52,7 @@ class MessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -75,6 +76,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 1fbca5a2..f6179bfa 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -93,7 +93,7 @@ bool IsReferenceType(JavaType type) {
}
const char* GetCapitalizedType(const FieldDescriptor* field) {
- switch (field->type()) {
+ switch (GetType(field)) {
case FieldDescriptor::TYPE_INT32 : return "Int32" ;
case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
@@ -166,7 +166,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
- WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
if (IsReferenceType(GetJavaType(descriptor))) {
(*variables)["null_check"] =
" if (value == null) {\n"
@@ -175,7 +175,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
} else {
(*variables)["null_check"] = "";
}
- int fixed_size = FixedSize(descriptor->type());
+ int fixed_size = FixedSize(GetType(descriptor));
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
}
@@ -218,7 +218,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n"
"public Builder clear$capitalized_name$() {\n"
" result.has$capitalized_name$ = false;\n");
- if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ JavaType type = GetJavaType(descriptor_);
+ if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
// The default value is not a simple literal so we want to avoid executing
// it multiple times. Instead, get the default out of the default instance.
printer->Print(variables_,
@@ -233,6 +234,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void PrimitiveFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -346,6 +352,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void RepeatedPrimitiveFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
@@ -367,18 +378,19 @@ GenerateBuildingCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "int length = input.readRawVarint32();\n"
- "int limit = input.pushLimit(length);\n"
- "while (input.getBytesUntilLimit() > 0) {\n"
- " add$capitalized_name$(input.read$capitalized_type$());\n"
- "}\n"
- "input.popLimit(limit);\n");
- } else {
- printer->Print(variables_,
- "add$capitalized_name$(input.read$capitalized_type$());\n");
- }
+ printer->Print(variables_,
+ "add$capitalized_name$(input.read$capitalized_type$());\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " add$capitalized_name$(input.read$capitalized_type$());\n"
+ "}\n"
+ "input.popLimit(limit);\n");
}
void RepeatedPrimitiveFieldGenerator::
@@ -407,7 +419,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
" int dataSize = 0;\n");
printer->Indent();
- if (FixedSize(descriptor_->type()) == -1) {
+ if (FixedSize(GetType(descriptor_)) == -1) {
printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\n"
" dataSize += com.google.protobuf.CodedOutputStream\n"
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h
index f9da0a62..4e482a05 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -52,6 +52,7 @@ class PrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -75,9 +76,11 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 0a2c0b2c..d9b0c3f9 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -39,6 +39,7 @@
int main(int argc, char* argv[]) {
google::protobuf::compiler::CommandLineInterface cli;
+ cli.AllowPlugins("protoc-");
// Proto2 C++
google::protobuf::compiler::cpp::CppGenerator cpp_generator;
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 02304d6d..758f70dc 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -34,8 +34,9 @@
//
// Recursive descent FTW.
-#include <google/protobuf/stubs/hash.h>
#include <float.h>
+#include <google/protobuf/stubs/hash.h>
+#include <limits>
#include <google/protobuf/compiler/parser.h>
@@ -206,6 +207,14 @@ bool Parser::ConsumeNumber(double* output, const char* error) {
*output = value;
input_->Next();
return true;
+ } else if (LookingAt("inf")) {
+ *output = numeric_limits<double>::infinity();
+ input_->Next();
+ return true;
+ } else if (LookingAt("nan")) {
+ *output = numeric_limits<double>::quiet_NaN();
+ input_->Next();
+ return true;
} else {
AddError(error);
return false;
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index c4f08e7f..e2262b8b 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -336,6 +336,9 @@ TEST_F(ParseMessageTest, FieldDefaults) {
" required double foo = 1 [default= 10.5];\n"
" required double foo = 1 [default=-11.5];\n"
" required double foo = 1 [default= 12 ];\n"
+ " required double foo = 1 [default= inf ];\n"
+ " required double foo = 1 [default=-inf ];\n"
+ " required double foo = 1 [default= nan ];\n"
" required string foo = 1 [default='13\\001'];\n"
" required string foo = 1 [default='a' \"b\" \n \"c\"];\n"
" required bytes foo = 1 [default='14\\002'];\n"
@@ -367,6 +370,9 @@ TEST_F(ParseMessageTest, FieldDefaults) {
" field { type:TYPE_DOUBLE default_value:\"10.5\" "ETC" }"
" field { type:TYPE_DOUBLE default_value:\"-11.5\" "ETC" }"
" field { type:TYPE_DOUBLE default_value:\"12\" "ETC" }"
+ " field { type:TYPE_DOUBLE default_value:\"inf\" "ETC" }"
+ " field { type:TYPE_DOUBLE default_value:\"-inf\" "ETC" }"
+ " field { type:TYPE_DOUBLE default_value:\"nan\" "ETC" }"
" field { type:TYPE_STRING default_value:\"13\\001\" "ETC" }"
" field { type:TYPE_STRING default_value:\"abc\" "ETC" }"
" field { type:TYPE_BYTES default_value:\"14\\\\002\" "ETC" }"
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index d301f015..54ab0a2d 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -42,8 +42,9 @@
// performance-minded Python code leverage the fast C++ implementation
// directly.
-#include <utility>
+#include <limits>
#include <map>
+#include <utility>
#include <string>
#include <vector>
@@ -105,6 +106,13 @@ string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
const char kDescriptorKey[] = "DESCRIPTOR";
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file) {
+ return file->service_count() > 0 &&
+ file->options().py_generic_services();
+}
+
+
// Prints the common boilerplate needed at the top of every .py
// file output by this generator.
void PrintTopBoilerplate(
@@ -115,14 +123,21 @@ void PrintTopBoilerplate(
"\n"
"from google.protobuf import descriptor\n"
"from google.protobuf import message\n"
- "from google.protobuf import reflection\n"
- "from google.protobuf import service\n"
- "from google.protobuf import service_reflection\n");
+ "from google.protobuf import reflection\n");
+ if (HasGenericServices(file)) {
+ printer->Print(
+ "from google.protobuf import service\n"
+ "from google.protobuf import service_reflection\n");
+ }
+
// Avoid circular imports if this module is descriptor_pb2.
if (!descriptor_proto) {
printer->Print(
"from google.protobuf import descriptor_pb2\n");
}
+ printer->Print(
+ "# @@protoc_insertion_point(imports)\n");
+ printer->Print("\n\n");
}
@@ -150,10 +165,30 @@ string StringifyDefaultValue(const FieldDescriptor& field) {
return SimpleItoa(field.default_value_int64());
case FieldDescriptor::CPPTYPE_UINT64:
return SimpleItoa(field.default_value_uint64());
- case FieldDescriptor::CPPTYPE_DOUBLE:
- return SimpleDtoa(field.default_value_double());
- case FieldDescriptor::CPPTYPE_FLOAT:
- return SimpleFtoa(field.default_value_float());
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
+ double value = field.default_value_double();
+ if (value == numeric_limits<double>::infinity()) {
+ return "float('inf')";
+ } else if (value == -numeric_limits<double>::infinity()) {
+ return "float('-inf')";
+ } else if (value != value) {
+ return "float('nan')";
+ } else {
+ return SimpleDtoa(value);
+ }
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = field.default_value_float();
+ if (value == numeric_limits<float>::infinity()) {
+ return "float('inf')";
+ } else if (value == -numeric_limits<float>::infinity()) {
+ return "float('-inf')";
+ } else if (value != value) {
+ return "float('nan')";
+ } else {
+ return SimpleFtoa(value);
+ }
+ }
case FieldDescriptor::CPPTYPE_BOOL:
return field.default_value_bool() ? "True" : "False";
case FieldDescriptor::CPPTYPE_ENUM:
@@ -204,6 +239,10 @@ bool Generator::Generate(const FileDescriptor* file,
StripString(&filename, ".", '/');
filename += ".py";
+ FileDescriptorProto fdp;
+ file_->CopyTo(&fdp);
+ fdp.SerializeToString(&file_descriptor_serialized_);
+
scoped_ptr<io::ZeroCopyOutputStream> output(output_directory->Open(filename));
GOOGLE_CHECK(output.get());
@@ -211,6 +250,7 @@ bool Generator::Generate(const FileDescriptor* file,
printer_ = &printer;
PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
+ PrintFileDescriptor();
PrintTopLevelEnums();
PrintTopLevelExtensions();
PrintAllNestedEnumsInFile();
@@ -224,7 +264,13 @@ bool Generator::Generate(const FileDescriptor* file,
// since they need to call static RegisterExtension() methods on these
// classes.
FixForeignFieldsInExtensions();
- PrintServices();
+ if (HasGenericServices(file)) {
+ PrintServices();
+ }
+
+ printer.Print(
+ "# @@protoc_insertion_point(module_scope)\n");
+
return !printer.failed();
}
@@ -238,6 +284,30 @@ void Generator::PrintImports() const {
printer_->Print("\n");
}
+// Prints the single file descriptor for this file.
+void Generator::PrintFileDescriptor() const {
+ map<string, string> m;
+ m["descriptor_name"] = kDescriptorKey;
+ m["name"] = file_->name();
+ m["package"] = file_->package();
+ const char file_descriptor_template[] =
+ "$descriptor_name$ = descriptor.FileDescriptor(\n"
+ " name='$name$',\n"
+ " package='$package$',\n";
+ printer_->Print(m, file_descriptor_template);
+ printer_->Indent();
+ printer_->Print(
+ "serialized_pb='$value$'",
+ "value", strings::CHexEscape(file_descriptor_serialized_));
+
+ // TODO(falk): Also print options and fix the message_type, enum_type,
+ // service and extension later in the generation.
+
+ printer_->Outdent();
+ printer_->Print(")\n");
+ printer_->Print("\n");
+}
+
// Prints descriptors and module-level constants for all top-level
// enums defined in |file|.
void Generator::PrintTopLevelEnums() const {
@@ -277,12 +347,13 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor);
m["name"] = enum_descriptor.name();
m["full_name"] = enum_descriptor.full_name();
- m["filename"] = enum_descriptor.name();
+ m["file"] = kDescriptorKey;
const char enum_descriptor_template[] =
"$descriptor_name$ = descriptor.EnumDescriptor(\n"
" name='$name$',\n"
" full_name='$full_name$',\n"
- " filename='$filename$',\n"
+ " filename=None,\n"
+ " file=$file$,\n"
" values=[\n";
string options_string;
enum_descriptor.options().SerializeToString(&options_string);
@@ -295,9 +366,12 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
}
printer_->Outdent();
printer_->Print("],\n");
+ printer_->Print("containing_type=None,\n");
printer_->Print("options=$options_value$,\n",
"options_value",
OptionsValue("EnumOptions", CEscape(options_string)));
+ EnumDescriptorProto edp;
+ PrintSerializedPbInterval(enum_descriptor, edp);
printer_->Outdent();
printer_->Print(")\n");
printer_->Print("\n");
@@ -362,15 +436,21 @@ void Generator::PrintServiceDescriptor(
map<string, string> m;
m["name"] = descriptor.name();
m["full_name"] = descriptor.full_name();
+ m["file"] = kDescriptorKey;
m["index"] = SimpleItoa(descriptor.index());
m["options_value"] = OptionsValue("ServiceOptions", options_string);
const char required_function_arguments[] =
"name='$name$',\n"
"full_name='$full_name$',\n"
+ "file=$file$,\n"
"index=$index$,\n"
- "options=$options_value$,\n"
- "methods=[\n";
+ "options=$options_value$,\n";
printer_->Print(m, required_function_arguments);
+
+ ServiceDescriptorProto sdp;
+ PrintSerializedPbInterval(descriptor, sdp);
+
+ printer_->Print("methods=[\n");
for (int i = 0; i < descriptor.method_count(); ++i) {
const MethodDescriptor* method = descriptor.method(i);
string options_string;
@@ -444,17 +524,27 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
map<string, string> m;
m["name"] = message_descriptor.name();
m["full_name"] = message_descriptor.full_name();
- m["filename"] = message_descriptor.file()->name();
+ m["file"] = kDescriptorKey;
const char required_function_arguments[] =
"name='$name$',\n"
"full_name='$full_name$',\n"
- "filename='$filename$',\n"
- "containing_type=None,\n"; // TODO(robinson): Implement containing_type.
+ "filename=None,\n"
+ "file=$file$,\n"
+ "containing_type=None,\n";
printer_->Print(m, required_function_arguments);
PrintFieldsInDescriptor(message_descriptor);
PrintExtensionsInDescriptor(message_descriptor);
- // TODO(robinson): implement printing of nested_types.
- printer_->Print("nested_types=[], # TODO(robinson): Implement.\n");
+
+ // Nested types
+ printer_->Print("nested_types=[");
+ for (int i = 0; i < message_descriptor.nested_type_count(); ++i) {
+ const string nested_name = ModuleLevelDescriptorName(
+ *message_descriptor.nested_type(i));
+ printer_->Print("$name$, ", "name", nested_name);
+ }
+ printer_->Print("],\n");
+
+ // Enum types
printer_->Print("enum_types=[\n");
printer_->Indent();
for (int i = 0; i < message_descriptor.enum_type_count(); ++i) {
@@ -468,8 +558,28 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
string options_string;
message_descriptor.options().SerializeToString(&options_string);
printer_->Print(
- "options=$options_value$",
- "options_value", OptionsValue("MessageOptions", options_string));
+ "options=$options_value$,\n"
+ "is_extendable=$extendable$",
+ "options_value", OptionsValue("MessageOptions", options_string),
+ "extendable", message_descriptor.extension_range_count() > 0 ?
+ "True" : "False");
+ printer_->Print(",\n");
+
+ // Extension ranges
+ printer_->Print("extension_ranges=[");
+ for (int i = 0; i < message_descriptor.extension_range_count(); ++i) {
+ const Descriptor::ExtensionRange* range =
+ message_descriptor.extension_range(i);
+ printer_->Print("($start$, $end$), ",
+ "start", SimpleItoa(range->start),
+ "end", SimpleItoa(range->end));
+ }
+ printer_->Print("],\n");
+
+ // Serialization of proto
+ DescriptorProto edp;
+ PrintSerializedPbInterval(message_descriptor, edp);
+
printer_->Outdent();
printer_->Print(")\n");
}
@@ -511,6 +621,12 @@ void Generator::PrintMessage(
m["descriptor_key"] = kDescriptorKey;
m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
printer_->Print(m, "$descriptor_key$ = $descriptor_name$\n");
+
+ printer_->Print(
+ "\n"
+ "# @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", message_descriptor.full_name());
+
printer_->Outdent();
}
@@ -527,16 +643,27 @@ void Generator::PrintNestedMessages(
// Recursively fixes foreign fields in all nested types in |descriptor|, then
// sets the message_type and enum_type of all message and enum fields to point
// to their respective descriptors.
+// Args:
+// descriptor: descriptor to print fields for.
+// containing_descriptor: if descriptor is a nested type, this is its
+// containing type, or NULL if this is a root/top-level type.
void Generator::FixForeignFieldsInDescriptor(
- const Descriptor& descriptor) const {
+ const Descriptor& descriptor,
+ const Descriptor* containing_descriptor) const {
for (int i = 0; i < descriptor.nested_type_count(); ++i) {
- FixForeignFieldsInDescriptor(*descriptor.nested_type(i));
+ FixForeignFieldsInDescriptor(*descriptor.nested_type(i), &descriptor);
}
for (int i = 0; i < descriptor.field_count(); ++i) {
const FieldDescriptor& field_descriptor = *descriptor.field(i);
FixForeignFieldsInField(&descriptor, field_descriptor, "fields_by_name");
}
+
+ FixContainingTypeInDescriptor(descriptor, containing_descriptor);
+ for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+ const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i);
+ FixContainingTypeInDescriptor(enum_descriptor, &descriptor);
+ }
}
// Sets any necessary message_type and enum_type attributes
@@ -593,13 +720,29 @@ string Generator::FieldReferencingExpression(
python_dict_name, field.name());
}
+// Prints containing_type for nested descriptors or enum descriptors.
+template <typename DescriptorT>
+void Generator::FixContainingTypeInDescriptor(
+ const DescriptorT& descriptor,
+ const Descriptor* containing_descriptor) const {
+ if (containing_descriptor != NULL) {
+ const string nested_name = ModuleLevelDescriptorName(descriptor);
+ const string parent_name = ModuleLevelDescriptorName(
+ *containing_descriptor);
+ printer_->Print(
+ "$nested_name$.containing_type = $parent_name$;\n",
+ "nested_name", nested_name,
+ "parent_name", parent_name);
+ }
+}
+
// Prints statements setting the message_type and enum_type fields in the
// Python descriptor objects we've already output in ths file. We must
// do this in a separate step due to circular references (otherwise, we'd
// just set everything in the initial assignment statements).
void Generator::FixForeignFieldsInDescriptors() const {
for (int i = 0; i < file_->message_type_count(); ++i) {
- FixForeignFieldsInDescriptor(*file_->message_type(i));
+ FixForeignFieldsInDescriptor(*file_->message_type(i), NULL);
}
printer_->Print("\n");
}
@@ -696,6 +839,7 @@ void Generator::PrintFieldDescriptor(
m["type"] = SimpleItoa(field.type());
m["cpp_type"] = SimpleItoa(field.cpp_type());
m["label"] = SimpleItoa(field.label());
+ m["has_default_value"] = field.has_default_value() ? "True" : "False";
m["default_value"] = StringifyDefaultValue(field);
m["is_extension"] = is_extension ? "True" : "False";
m["options"] = OptionsValue("FieldOptions", options_string);
@@ -703,13 +847,13 @@ void Generator::PrintFieldDescriptor(
// these fields in correctly after all referenced descriptors have been
// defined and/or imported (see FixForeignFieldsInDescriptors()).
const char field_descriptor_decl[] =
- "descriptor.FieldDescriptor(\n"
- " name='$name$', full_name='$full_name$', index=$index$,\n"
- " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
- " default_value=$default_value$,\n"
- " message_type=None, enum_type=None, containing_type=None,\n"
- " is_extension=$is_extension$, extension_scope=None,\n"
- " options=$options$)";
+ "descriptor.FieldDescriptor(\n"
+ " name='$name$', full_name='$full_name$', index=$index$,\n"
+ " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
+ " has_default_value=$has_default_value$, default_value=$default_value$,\n"
+ " message_type=None, enum_type=None, containing_type=None,\n"
+ " is_extension=$is_extension$, extension_scope=None,\n"
+ " options=$options$)";
printer_->Print(m, field_descriptor_decl);
}
@@ -811,6 +955,29 @@ string Generator::ModuleLevelServiceDescriptorName(
return name;
}
+// Prints standard constructor arguments serialized_start and serialized_end.
+// Args:
+// descriptor: The cpp descriptor to have a serialized reference.
+// proto: A proto
+// Example printer output:
+// serialized_start=41,
+// serialized_end=43,
+//
+template <typename DescriptorT, typename DescriptorProtoT>
+void Generator::PrintSerializedPbInterval(
+ const DescriptorT& descriptor, DescriptorProtoT& proto) const {
+ descriptor.CopyTo(&proto);
+ string sp;
+ proto.SerializeToString(&sp);
+ int offset = file_descriptor_serialized_.find(sp);
+ GOOGLE_CHECK_GE(offset, 0);
+
+ printer_->Print("serialized_start=$serialized_start$,\n"
+ "serialized_end=$serialized_end$,\n",
+ "serialized_start", SimpleItoa(offset),
+ "serialized_end", SimpleItoa(offset + sp.size()));
+}
+
} // namespace python
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index 8b99d624..43c20876 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -71,6 +71,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
private:
void PrintImports() const;
+ void PrintFileDescriptor() const;
void PrintTopLevelEnums() const;
void PrintAllNestedEnumsInFile() const;
void PrintNestedEnums(const Descriptor& descriptor) const;
@@ -97,13 +98,19 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
void PrintNestedMessages(const Descriptor& containing_descriptor) const;
void FixForeignFieldsInDescriptors() const;
- void FixForeignFieldsInDescriptor(const Descriptor& descriptor) const;
+ void FixForeignFieldsInDescriptor(
+ const Descriptor& descriptor,
+ const Descriptor* containing_descriptor) const;
void FixForeignFieldsInField(const Descriptor* containing_type,
const FieldDescriptor& field,
const string& python_dict_name) const;
string FieldReferencingExpression(const Descriptor* containing_type,
const FieldDescriptor& field,
const string& python_dict_name) const;
+ template <typename DescriptorT>
+ void FixContainingTypeInDescriptor(
+ const DescriptorT& descriptor,
+ const Descriptor* containing_descriptor) const;
void FixForeignFieldsInExtensions() const;
void FixForeignFieldsInExtension(
@@ -126,10 +133,15 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
string ModuleLevelServiceDescriptorName(
const ServiceDescriptor& descriptor) const;
+ template <typename DescriptorT, typename DescriptorProtoT>
+ void PrintSerializedPbInterval(
+ const DescriptorT& descriptor, DescriptorProtoT& proto) const;
+
// Very coarse-grained lock to ensure that Generate() is reentrant.
- // Guards file_ and printer_.
+ // Guards file_, printer_ and file_descriptor_serialized_.
mutable Mutex mutex_;
mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_.
+ mutable string file_descriptor_serialized_;
mutable io::Printer* printer_; // Set in Generate(). Under mutex_.
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index a12e4e72..e0a95077 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -796,9 +796,10 @@ bool DescriptorPool::InternalIsFileLoaded(const string& filename) const {
namespace {
+
EncodedDescriptorDatabase* generated_database_ = NULL;
DescriptorPool* generated_pool_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
+GoogleOnceType generated_pool_init_;
void DeleteGeneratedPool() {
delete generated_database_;
@@ -810,6 +811,7 @@ void DeleteGeneratedPool() {
void InitGeneratedPool() {
generated_database_ = new EncodedDescriptorDatabase;
generated_pool_ = new DescriptorPool(generated_database_);
+
internal::OnShutdown(&DeleteGeneratedPool);
}
@@ -3651,17 +3653,11 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
}
// Only repeated primitive fields may be packed.
- if (field->options().packed()) {
- if (!field->is_repeated() ||
- field->type() == FieldDescriptor::TYPE_STRING ||
- field->type() == FieldDescriptor::TYPE_GROUP ||
- field->type() == FieldDescriptor::TYPE_MESSAGE ||
- field->type() == FieldDescriptor::TYPE_BYTES) {
- AddError(
- field->full_name(), proto,
- DescriptorPool::ErrorCollector::TYPE,
- "[packed = true] can only be specified for repeated primitive fields.");
- }
+ if (field->options().packed() && !field->is_packable()) {
+ AddError(
+ field->full_name(), proto,
+ DescriptorPool::ErrorCollector::TYPE,
+ "[packed = true] can only be specified for repeated primitive fields.");
}
// Note: Default instance may not yet be initialized here, so we have to
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 5b629a5d..7f87dd80 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -395,6 +395,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
bool is_required() const; // shorthand for label() == LABEL_REQUIRED
bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL
bool is_repeated() const; // shorthand for label() == LABEL_REPEATED
+ bool is_packable() const; // shorthand for is_repeated() &&
+ // IsTypePackable(type())
// Index of this field within the message's field array, or the file or
// extension scope's extensions array.
@@ -474,6 +476,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
// Helper method to get the CppType for a particular Type.
static CppType TypeToCppType(Type type);
+ // Return true iff [packed = true] is valid for fields of this type.
+ static inline bool IsTypePackable(Type field_type);
+
private:
typedef FieldOptions OptionsType;
@@ -1069,10 +1074,6 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// These methods may contain hidden pitfalls and may be removed in a
// future library version.
- // DEPRECATED: Use of underlays can lead to many subtle gotchas. Instead,
- // try to formulate what you want to do in terms of DescriptorDatabases.
- // This constructor will be removed soon.
- //
// Create a DescriptorPool which is overlaid on top of some other pool.
// If you search for a descriptor in the overlay and it is not found, the
// underlay will be searched as a backup. If the underlay has its own
@@ -1090,6 +1091,9 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// types directly into generated_pool(): this is not allowed, and would be
// bad design anyway. So, instead, you could use generated_pool() as an
// underlay for a new DescriptorPool in which you add only the new file.
+ //
+ // WARNING: Use of underlays can lead to many subtle gotchas. Instead,
+ // try to formulate what you want to do in terms of DescriptorDatabases.
explicit DescriptorPool(const DescriptorPool* underlay);
// Called by generated classes at init time to add their descriptors to
@@ -1294,6 +1298,10 @@ inline bool FieldDescriptor::is_repeated() const {
return label() == LABEL_REPEATED;
}
+inline bool FieldDescriptor::is_packable() const {
+ return is_repeated() && IsTypePackable(type());
+}
+
// To save space, index() is computed by looking at the descriptor's position
// in the parent's array of children.
inline int FieldDescriptor::index() const {
@@ -1342,6 +1350,13 @@ inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) {
return kTypeToCppTypeMap[type];
}
+inline bool FieldDescriptor::IsTypePackable(Type field_type) {
+ return (field_type != FieldDescriptor::TYPE_STRING &&
+ field_type != FieldDescriptor::TYPE_GROUP &&
+ field_type != FieldDescriptor::TYPE_MESSAGE &&
+ field_type != FieldDescriptor::TYPE_BYTES);
+}
+
inline const FileDescriptor* FileDescriptor::dependency(int index) const {
return dependencies_[index];
}
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 276c6009..f61e7cd0 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -8,6 +8,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
namespace google {
namespace protobuf {
@@ -250,11 +251,14 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
::google::protobuf::MessageFactory::generated_factory(),
sizeof(MethodDescriptorProto));
FileOptions_descriptor_ = file->message_type(8);
- static const int FileOptions_offsets_[5] = {
+ static const int FileOptions_offsets_[8] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_),
};
FileOptions_reflection_ =
@@ -552,43 +556,47 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"ptions\"\177\n\025MethodDescriptorProto\022\014\n\004name\030"
"\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output_type"
"\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.protobu"
- "f.MethodOptions\"\271\002\n\013FileOptions\022\024\n\014java_"
+ "f.MethodOptions\"\244\003\n\013FileOptions\022\024\n\014java_"
"package\030\001 \001(\t\022\034\n\024java_outer_classname\030\010 "
"\001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false\022"
"F\n\014optimize_for\030\t \001(\0162).google.protobuf."
- "FileOptions.OptimizeMode:\005SPEED\022C\n\024unint"
- "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
- ".UninterpretedOption\":\n\014OptimizeMode\022\t\n\005"
- "SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003"
- "*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOptions\022&\n\027messag"
- "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta"
- "ndard_descriptor_accessor\030\002 \001(\010:\005false\022C"
- "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p"
- "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\200"
- "\002\n\014FieldOptions\0222\n\005ctype\030\001 \001(\0162#.google."
- "protobuf.FieldOptions.CType\022\016\n\006packed\030\002 "
- "\001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experi"
- "mental_map_key\030\t \001(\t\022C\n\024uninterpreted_op"
- "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
- "tedOption\"#\n\005CType\022\010\n\004CORD\020\001\022\020\n\014STRING_P"
- "IECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024unin"
- "terpreted_option\030\347\007 \003(\0132$.google.protobu"
- "f.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020Enum"
- "ValueOptions\022C\n\024uninterpreted_option\030\347\007 "
- "\003(\0132$.google.protobuf.UninterpretedOptio"
- "n*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n\024uninte"
- "rpreted_option\030\347\007 \003(\0132$.google.protobuf."
- "UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethod"
- "Options\022C\n\024uninterpreted_option\030\347\007 \003(\0132$"
- ".google.protobuf.UninterpretedOption*\t\010\350"
- "\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedOption\022;\n\004name\030"
- "\002 \003(\0132-.google.protobuf.UninterpretedOpt"
- "ion.NamePart\022\030\n\020identifier_value\030\003 \001(\t\022\032"
- "\n\022positive_int_value\030\004 \001(\004\022\032\n\022negative_i"
- "nt_value\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014"
- "string_value\030\007 \001(\014\0323\n\010NamePart\022\021\n\tname_p"
- "art\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010B)\n\023com.g"
- "oogle.protobufB\020DescriptorProtosH\001", 3554);
+ "FileOptions.OptimizeMode:\005SPEED\022!\n\023cc_ge"
+ "neric_services\030\020 \001(\010:\004true\022#\n\025java_gener"
+ "ic_services\030\021 \001(\010:\004true\022!\n\023py_generic_se"
+ "rvices\030\022 \001(\010:\004true\022C\n\024uninterpreted_opti"
+ "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete"
+ "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO"
+ "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270"
+ "\001\n\016MessageOptions\022&\n\027message_set_wire_fo"
+ "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip"
+ "tor_accessor\030\002 \001(\010:\005false\022C\n\024uninterpret"
+ "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
+ "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptio"
+ "ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel"
+ "dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\031"
+ "\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experimenta"
+ "l_map_key\030\t \001(\t\022C\n\024uninterpreted_option\030"
+ "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
+ "tion\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014S"
+ "TRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022"
+ "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google."
+ "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\""
+ "b\n\020EnumValueOptions\022C\n\024uninterpreted_opt"
+ "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
+ "edOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n"
+ "\024uninterpreted_option\030\347\007 \003(\0132$.google.pr"
+ "otobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n"
+ "\rMethodOptions\022C\n\024uninterpreted_option\030\347"
+ "\007 \003(\0132$.google.protobuf.UninterpretedOpt"
+ "ion*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedOption\022;"
+ "\n\004name\030\002 \003(\0132-.google.protobuf.Uninterpr"
+ "etedOption.NamePart\022\030\n\020identifier_value\030"
+ "\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022neg"
+ "ative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 "
+ "\001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010NamePart\022\021\n"
+ "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010B)"
+ "\n\023com.google.protobufB\020DescriptorProtosH"
+ "\001", 3681);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -645,7 +653,7 @@ const int FileDescriptorSet::kFileFieldNumber;
#endif // !_MSC_VER
FileDescriptorSet::FileDescriptorSet()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -653,7 +661,7 @@ void FileDescriptorSet::InitAsDefaultInstance() {
}
FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -672,6 +680,11 @@ void FileDescriptorSet::SharedDtor() {
}
}
+void FileDescriptorSet::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FileDescriptorSet::descriptor() {
protobuf_AssignDescriptorsOnce();
return FileDescriptorSet_descriptor_;
@@ -701,13 +714,14 @@ bool FileDescriptorSet::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.FileDescriptorProto file = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_file()));
+ } else {
goto handle_uninterpreted;
}
- parse_file:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_file()));
if (input->ExpectTag(10)) goto parse_file;
if (input->ExpectAtEnd()) return true;
break;
@@ -731,15 +745,9 @@ bool FileDescriptorSet::MergePartialFromCodedStream(
void FileDescriptorSet::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FileDescriptorSet::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.FileDescriptorProto file = 1;
for (int i = 0; i < this->file_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
1, this->file(i), output);
}
@@ -781,7 +789,9 @@ int FileDescriptorSet::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -857,7 +867,7 @@ const int FileDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
FileDescriptorProto::FileDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -866,7 +876,7 @@ void FileDescriptorProto::InitAsDefaultInstance() {
}
FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -895,6 +905,11 @@ void FileDescriptorProto::SharedDtor() {
}
}
+void FileDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FileDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return FileDescriptorProto_descriptor_;
@@ -943,47 +958,50 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(18)) goto parse_package;
break;
}
// optional string package = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_package:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_package()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->package().data(), this->package().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_package:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_package()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->package().data(), this->package().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(26)) goto parse_dependency;
break;
}
// repeated string dependency = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_dependency:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->add_dependency()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->dependency(0).data(), this->dependency(0).length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_dependency:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->add_dependency()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->dependency(0).data(), this->dependency(0).length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(26)) goto parse_dependency;
if (input->ExpectTag(34)) goto parse_message_type;
break;
@@ -991,13 +1009,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.DescriptorProto message_type = 4;
case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_message_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_message_type()));
+ } else {
goto handle_uninterpreted;
}
- parse_message_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_message_type()));
if (input->ExpectTag(34)) goto parse_message_type;
if (input->ExpectTag(42)) goto parse_enum_type;
break;
@@ -1005,13 +1024,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_enum_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_enum_type()));
+ } else {
goto handle_uninterpreted;
}
- parse_enum_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_enum_type()));
if (input->ExpectTag(42)) goto parse_enum_type;
if (input->ExpectTag(50)) goto parse_service;
break;
@@ -1019,13 +1039,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_service:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_service()));
+ } else {
goto handle_uninterpreted;
}
- parse_service:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_service()));
if (input->ExpectTag(50)) goto parse_service;
if (input->ExpectTag(58)) goto parse_extension;
break;
@@ -1033,13 +1054,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
case 7: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_extension:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_extension()));
+ } else {
goto handle_uninterpreted;
}
- parse_extension:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_extension()));
if (input->ExpectTag(58)) goto parse_extension;
if (input->ExpectTag(66)) goto parse_options;
break;
@@ -1047,13 +1069,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.FileOptions options = 8;
case 8: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -1076,12 +1099,6 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
void FileDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FileDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1111,31 +1128,31 @@ void FileDescriptorProto::SerializeWithCachedSizes(
// repeated .google.protobuf.DescriptorProto message_type = 4;
for (int i = 0; i < this->message_type_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
4, this->message_type(i), output);
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
for (int i = 0; i < this->enum_type_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
5, this->enum_type(i), output);
}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
for (int i = 0; i < this->service_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
6, this->service(i), output);
}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
for (int i = 0; i < this->extension_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
7, this->extension(i), output);
}
// optional .google.protobuf.FileOptions options = 8;
if (_has_bit(7)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
8, this->options(), output);
}
@@ -1288,7 +1305,9 @@ int FileDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -1390,7 +1409,7 @@ const int DescriptorProto_ExtensionRange::kEndFieldNumber;
#endif // !_MSC_VER
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -1398,7 +1417,7 @@ void DescriptorProto_ExtensionRange::InitAsDefaultInstance() {
}
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -1419,6 +1438,11 @@ void DescriptorProto_ExtensionRange::SharedDtor() {
}
}
+void DescriptorProto_ExtensionRange::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::descriptor() {
protobuf_AssignDescriptorsOnce();
return DescriptorProto_ExtensionRange_descriptor_;
@@ -1451,27 +1475,31 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional int32 start = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &start_)));
+ _set_bit(0);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
- input, &start_));
- _set_bit(0);
if (input->ExpectTag(16)) goto parse_end;
break;
}
// optional int32 end = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_end:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &end_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_end:
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
- input, &end_));
- _set_bit(1);
if (input->ExpectAtEnd()) return true;
break;
}
@@ -1494,12 +1522,6 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional int32 start = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
@@ -1559,7 +1581,9 @@ int DescriptorProto_ExtensionRange::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -1638,7 +1662,7 @@ const int DescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
DescriptorProto::DescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -1647,7 +1671,7 @@ void DescriptorProto::InitAsDefaultInstance() {
}
DescriptorProto::DescriptorProto(const DescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -1672,6 +1696,11 @@ void DescriptorProto::SharedDtor() {
}
}
+void DescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* DescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return DescriptorProto_descriptor_;
@@ -1715,28 +1744,30 @@ bool DescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(18)) goto parse_field;
break;
}
// repeated .google.protobuf.FieldDescriptorProto field = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_field:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_field()));
+ } else {
goto handle_uninterpreted;
}
- parse_field:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_field()));
if (input->ExpectTag(18)) goto parse_field;
if (input->ExpectTag(26)) goto parse_nested_type;
break;
@@ -1744,13 +1775,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.DescriptorProto nested_type = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_nested_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_nested_type()));
+ } else {
goto handle_uninterpreted;
}
- parse_nested_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_nested_type()));
if (input->ExpectTag(26)) goto parse_nested_type;
if (input->ExpectTag(34)) goto parse_enum_type;
break;
@@ -1758,13 +1790,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_enum_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_enum_type()));
+ } else {
goto handle_uninterpreted;
}
- parse_enum_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_enum_type()));
if (input->ExpectTag(34)) goto parse_enum_type;
if (input->ExpectTag(42)) goto parse_extension_range;
break;
@@ -1772,13 +1805,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_extension_range:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_extension_range()));
+ } else {
goto handle_uninterpreted;
}
- parse_extension_range:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_extension_range()));
if (input->ExpectTag(42)) goto parse_extension_range;
if (input->ExpectTag(50)) goto parse_extension;
break;
@@ -1786,13 +1820,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_extension:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_extension()));
+ } else {
goto handle_uninterpreted;
}
- parse_extension:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_extension()));
if (input->ExpectTag(50)) goto parse_extension;
if (input->ExpectTag(58)) goto parse_options;
break;
@@ -1800,13 +1835,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.MessageOptions options = 7;
case 7: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -1829,12 +1865,6 @@ bool DescriptorProto::MergePartialFromCodedStream(
void DescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- DescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1846,37 +1876,37 @@ void DescriptorProto::SerializeWithCachedSizes(
// repeated .google.protobuf.FieldDescriptorProto field = 2;
for (int i = 0; i < this->field_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->field(i), output);
}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
for (int i = 0; i < this->nested_type_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->nested_type(i), output);
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
for (int i = 0; i < this->enum_type_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
4, this->enum_type(i), output);
}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
for (int i = 0; i < this->extension_range_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
5, this->extension_range(i), output);
}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
for (int i = 0; i < this->extension_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
6, this->extension(i), output);
}
// optional .google.protobuf.MessageOptions options = 7;
if (_has_bit(6)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
7, this->options(), output);
}
@@ -2011,7 +2041,9 @@ int DescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -2154,6 +2186,7 @@ const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT32;
const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT64;
const FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN;
const FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX;
+const int FieldDescriptorProto::Type_ARRAYSIZE;
#endif // _MSC_VER
const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor() {
protobuf_AssignDescriptorsOnce();
@@ -2176,6 +2209,7 @@ const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REQUIRED;
const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REPEATED;
const FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN;
const FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX;
+const int FieldDescriptorProto::Label_ARRAYSIZE;
#endif // _MSC_VER
const ::std::string FieldDescriptorProto::_default_name_;
const ::std::string FieldDescriptorProto::_default_type_name_;
@@ -2193,7 +2227,7 @@ const int FieldDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
FieldDescriptorProto::FieldDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -2202,7 +2236,7 @@ void FieldDescriptorProto::InitAsDefaultInstance() {
}
FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -2242,6 +2276,11 @@ void FieldDescriptorProto::SharedDtor() {
}
}
+void FieldDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FieldDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return FieldDescriptorProto_descriptor_;
@@ -2298,62 +2337,69 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(18)) goto parse_extendee;
break;
}
// optional string extendee = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_extendee:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_extendee()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->extendee().data(), this->extendee().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_extendee:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_extendee()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->extendee().data(), this->extendee().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(24)) goto parse_number;
break;
}
// optional int32 number = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_number:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &number_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_number:
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
- input, &number_));
- _set_bit(1);
if (input->ExpectTag(32)) goto parse_label;
break;
}
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- goto handle_uninterpreted;
- }
- parse_label:
- int value;
- DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));
- if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) {
- set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value));
+ parse_label:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) {
+ set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(4, value);
+ }
} else {
- mutable_unknown_fields()->AddVarint(4, value);
+ goto handle_uninterpreted;
}
if (input->ExpectTag(40)) goto parse_type;
break;
@@ -2361,17 +2407,20 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- goto handle_uninterpreted;
- }
- parse_type:
- int value;
- DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));
- if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) {
- set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value));
+ parse_type:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) {
+ set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(5, value);
+ }
} else {
- mutable_unknown_fields()->AddVarint(5, value);
+ goto handle_uninterpreted;
}
if (input->ExpectTag(50)) goto parse_type_name;
break;
@@ -2379,45 +2428,48 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// optional string type_name = 6;
case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_type_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_type_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->type_name().data(), this->type_name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_type_name:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_type_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->type_name().data(), this->type_name().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(58)) goto parse_default_value;
break;
}
// optional string default_value = 7;
case 7: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_default_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_default_value()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->default_value().data(), this->default_value().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_default_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_default_value()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->default_value().data(), this->default_value().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(66)) goto parse_options;
break;
}
// optional .google.protobuf.FieldOptions options = 8;
case 8: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -2440,12 +2492,6 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FieldDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2501,7 +2547,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
// optional .google.protobuf.FieldOptions options = 8;
if (_has_bit(7)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
8, this->options(), output);
}
@@ -2648,7 +2694,9 @@ int FieldDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -2750,7 +2798,7 @@ const int EnumDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumDescriptorProto::EnumDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -2759,7 +2807,7 @@ void EnumDescriptorProto::InitAsDefaultInstance() {
}
EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -2784,6 +2832,11 @@ void EnumDescriptorProto::SharedDtor() {
}
}
+void EnumDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* EnumDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return EnumDescriptorProto_descriptor_;
@@ -2823,28 +2876,30 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(18)) goto parse_value;
break;
}
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_value()));
+ } else {
goto handle_uninterpreted;
}
- parse_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_value()));
if (input->ExpectTag(18)) goto parse_value;
if (input->ExpectTag(26)) goto parse_options;
break;
@@ -2852,13 +2907,14 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.EnumOptions options = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -2881,12 +2937,6 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
void EnumDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- EnumDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2898,13 +2948,13 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
for (int i = 0; i < this->value_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->value(i), output);
}
// optional .google.protobuf.EnumOptions options = 3;
if (_has_bit(2)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->options(), output);
}
@@ -2979,7 +3029,9 @@ int EnumDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -3062,7 +3114,7 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumValueDescriptorProto::EnumValueDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -3071,7 +3123,7 @@ void EnumValueDescriptorProto::InitAsDefaultInstance() {
}
EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -3097,6 +3149,11 @@ void EnumValueDescriptorProto::SharedDtor() {
}
}
+void EnumValueDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* EnumValueDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return EnumValueDescriptorProto_descriptor_;
@@ -3136,42 +3193,46 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(16)) goto parse_number;
break;
}
// optional int32 number = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_number:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &number_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_number:
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
- input, &number_));
- _set_bit(1);
if (input->ExpectTag(26)) goto parse_options;
break;
}
// optional .google.protobuf.EnumValueOptions options = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -3194,12 +3255,6 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream(
void EnumValueDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- EnumValueDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -3216,7 +3271,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
// optional .google.protobuf.EnumValueOptions options = 3;
if (_has_bit(2)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->options(), output);
}
@@ -3288,7 +3343,9 @@ int EnumValueDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -3370,7 +3427,7 @@ const int ServiceDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
ServiceDescriptorProto::ServiceDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -3379,7 +3436,7 @@ void ServiceDescriptorProto::InitAsDefaultInstance() {
}
ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -3404,6 +3461,11 @@ void ServiceDescriptorProto::SharedDtor() {
}
}
+void ServiceDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* ServiceDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return ServiceDescriptorProto_descriptor_;
@@ -3443,28 +3505,30 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(18)) goto parse_method;
break;
}
// repeated .google.protobuf.MethodDescriptorProto method = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_method:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_method()));
+ } else {
goto handle_uninterpreted;
}
- parse_method:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_method()));
if (input->ExpectTag(18)) goto parse_method;
if (input->ExpectTag(26)) goto parse_options;
break;
@@ -3472,13 +3536,14 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.ServiceOptions options = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -3501,12 +3566,6 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
void ServiceDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- ServiceDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -3518,13 +3577,13 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
// repeated .google.protobuf.MethodDescriptorProto method = 2;
for (int i = 0; i < this->method_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->method(i), output);
}
// optional .google.protobuf.ServiceOptions options = 3;
if (_has_bit(2)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->options(), output);
}
@@ -3599,7 +3658,9 @@ int ServiceDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -3685,7 +3746,7 @@ const int MethodDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
MethodDescriptorProto::MethodDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -3694,7 +3755,7 @@ void MethodDescriptorProto::InitAsDefaultInstance() {
}
MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -3727,6 +3788,11 @@ void MethodDescriptorProto::SharedDtor() {
}
}
+void MethodDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* MethodDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return MethodDescriptorProto_descriptor_;
@@ -3775,60 +3841,64 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_name()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->name().data(), this->name().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(18)) goto parse_input_type;
break;
}
// optional string input_type = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_input_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_input_type()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->input_type().data(), this->input_type().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_input_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_input_type()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->input_type().data(), this->input_type().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(26)) goto parse_output_type;
break;
}
// optional string output_type = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_output_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_output_type()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->output_type().data(), this->output_type().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_output_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_output_type()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->output_type().data(), this->output_type().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(34)) goto parse_options;
break;
}
// optional .google.protobuf.MethodOptions options = 4;
case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -3851,12 +3921,6 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
void MethodDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- MethodDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -3886,7 +3950,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
// optional .google.protobuf.MethodOptions options = 4;
if (_has_bit(3)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
4, this->options(), output);
}
@@ -3980,7 +4044,9 @@ int MethodDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -4079,6 +4145,7 @@ const FileOptions_OptimizeMode FileOptions::CODE_SIZE;
const FileOptions_OptimizeMode FileOptions::LITE_RUNTIME;
const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN;
const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX;
+const int FileOptions::OptimizeMode_ARRAYSIZE;
#endif // _MSC_VER
const ::std::string FileOptions::_default_java_package_;
const ::std::string FileOptions::_default_java_outer_classname_;
@@ -4087,11 +4154,14 @@ const int FileOptions::kJavaPackageFieldNumber;
const int FileOptions::kJavaOuterClassnameFieldNumber;
const int FileOptions::kJavaMultipleFilesFieldNumber;
const int FileOptions::kOptimizeForFieldNumber;
+const int FileOptions::kCcGenericServicesFieldNumber;
+const int FileOptions::kJavaGenericServicesFieldNumber;
+const int FileOptions::kPyGenericServicesFieldNumber;
const int FileOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FileOptions::FileOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -4099,7 +4169,7 @@ void FileOptions::InitAsDefaultInstance() {
}
FileOptions::FileOptions(const FileOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -4110,6 +4180,9 @@ void FileOptions::SharedCtor() {
java_outer_classname_ = const_cast< ::std::string*>(&_default_java_outer_classname_);
java_multiple_files_ = false;
optimize_for_ = 1;
+ cc_generic_services_ = true;
+ java_generic_services_ = true;
+ py_generic_services_ = true;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -4128,6 +4201,11 @@ void FileOptions::SharedDtor() {
}
}
+void FileOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FileOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return FileOptions_descriptor_;
@@ -4158,6 +4236,9 @@ void FileOptions::Clear() {
}
java_multiple_files_ = false;
optimize_for_ = 1;
+ cc_generic_services_ = true;
+ java_generic_services_ = true;
+ py_generic_services_ = true;
}
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -4172,48 +4253,53 @@ bool FileOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string java_package = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_java_package()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->java_package().data(), this->java_package().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_java_package()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->java_package().data(), this->java_package().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(66)) goto parse_java_outer_classname;
break;
}
// optional string java_outer_classname = 8;
case 8: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_java_outer_classname:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_java_outer_classname()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->java_outer_classname().data(), this->java_outer_classname().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_java_outer_classname:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_java_outer_classname()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->java_outer_classname().data(), this->java_outer_classname().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(72)) goto parse_optimize_for;
break;
}
// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
case 9: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- goto handle_uninterpreted;
- }
- parse_optimize_for:
- int value;
- DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));
- if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) {
- set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value));
+ parse_optimize_for:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) {
+ set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(9, value);
+ }
} else {
- mutable_unknown_fields()->AddVarint(9, value);
+ goto handle_uninterpreted;
}
if (input->ExpectTag(80)) goto parse_java_multiple_files;
break;
@@ -4221,27 +4307,78 @@ bool FileOptions::MergePartialFromCodedStream(
// optional bool java_multiple_files = 10 [default = false];
case 10: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_java_multiple_files:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &java_multiple_files_)));
+ _set_bit(2);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(128)) goto parse_cc_generic_services;
+ break;
+ }
+
+ // optional bool cc_generic_services = 16 [default = true];
+ case 16: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_cc_generic_services:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &cc_generic_services_)));
+ _set_bit(4);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(136)) goto parse_java_generic_services;
+ break;
+ }
+
+ // optional bool java_generic_services = 17 [default = true];
+ case 17: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_java_generic_services:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &java_generic_services_)));
+ _set_bit(5);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(144)) goto parse_py_generic_services;
+ break;
+ }
+
+ // optional bool py_generic_services = 18 [default = true];
+ case 18: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_py_generic_services:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &py_generic_services_)));
+ _set_bit(6);
+ } else {
goto handle_uninterpreted;
}
- parse_java_multiple_files:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &java_multiple_files_));
- _set_bit(2);
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_uninterpreted_option()));
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
if (input->ExpectAtEnd()) return true;
break;
@@ -4270,12 +4407,6 @@ bool FileOptions::MergePartialFromCodedStream(
void FileOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FileOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string java_package = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4305,9 +4436,24 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output);
}
+ // optional bool cc_generic_services = 16 [default = true];
+ if (_has_bit(4)) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output);
+ }
+
+ // optional bool java_generic_services = 17 [default = true];
+ if (_has_bit(5)) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output);
+ }
+
+ // optional bool py_generic_services = 18 [default = true];
+ if (_has_bit(6)) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -4354,6 +4500,21 @@ void FileOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target);
}
+ // optional bool cc_generic_services = 16 [default = true];
+ if (_has_bit(4)) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target);
+ }
+
+ // optional bool java_generic_services = 17 [default = true];
+ if (_has_bit(5)) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target);
+ }
+
+ // optional bool py_generic_services = 18 [default = true];
+ if (_has_bit(6)) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
@@ -4401,6 +4562,21 @@ int FileOptions::ByteSize() const {
::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for());
}
+ // optional bool cc_generic_services = 16 [default = true];
+ if (has_cc_generic_services()) {
+ total_size += 2 + 1;
+ }
+
+ // optional bool java_generic_services = 17 [default = true];
+ if (has_java_generic_services()) {
+ total_size += 2 + 1;
+ }
+
+ // optional bool py_generic_services = 18 [default = true];
+ if (has_py_generic_services()) {
+ total_size += 2 + 1;
+ }
+
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
@@ -4417,7 +4593,9 @@ int FileOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -4449,6 +4627,15 @@ void FileOptions::MergeFrom(const FileOptions& from) {
if (from._has_bit(3)) {
set_optimize_for(from.optimize_for());
}
+ if (from._has_bit(4)) {
+ set_cc_generic_services(from.cc_generic_services());
+ }
+ if (from._has_bit(5)) {
+ set_java_generic_services(from.java_generic_services());
+ }
+ if (from._has_bit(6)) {
+ set_py_generic_services(from.py_generic_services());
+ }
}
_extensions_.MergeFrom(from._extensions_);
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
@@ -4481,6 +4668,9 @@ void FileOptions::Swap(FileOptions* other) {
std::swap(java_outer_classname_, other->java_outer_classname_);
std::swap(java_multiple_files_, other->java_multiple_files_);
std::swap(optimize_for_, other->optimize_for_);
+ std::swap(cc_generic_services_, other->cc_generic_services_);
+ std::swap(java_generic_services_, other->java_generic_services_);
+ std::swap(py_generic_services_, other->py_generic_services_);
uninterpreted_option_.Swap(&other->uninterpreted_option_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.Swap(&other->_unknown_fields_);
@@ -4507,7 +4697,7 @@ const int MessageOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MessageOptions::MessageOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -4515,7 +4705,7 @@ void MessageOptions::InitAsDefaultInstance() {
}
MessageOptions::MessageOptions(const MessageOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -4536,6 +4726,11 @@ void MessageOptions::SharedDtor() {
}
}
+void MessageOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* MessageOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return MessageOptions_descriptor_;
@@ -4570,40 +4765,45 @@ bool MessageOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional bool message_set_wire_format = 1 [default = false];
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &message_set_wire_format_)));
+ _set_bit(0);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &message_set_wire_format_));
- _set_bit(0);
if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor;
break;
}
// optional bool no_standard_descriptor_accessor = 2 [default = false];
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_no_standard_descriptor_accessor:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &no_standard_descriptor_accessor_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_no_standard_descriptor_accessor:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &no_standard_descriptor_accessor_));
- _set_bit(1);
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_uninterpreted_option()));
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
if (input->ExpectAtEnd()) return true;
break;
@@ -4632,12 +4832,6 @@ bool MessageOptions::MergePartialFromCodedStream(
void MessageOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- MessageOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional bool message_set_wire_format = 1 [default = false];
if (_has_bit(0)) {
::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output);
@@ -4650,7 +4844,7 @@ void MessageOptions::SerializeWithCachedSizes(
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -4724,7 +4918,9 @@ int MessageOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -4805,6 +5001,7 @@ const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor() {
}
bool FieldOptions_CType_IsValid(int value) {
switch(value) {
+ case 0:
case 1:
case 2:
return true;
@@ -4814,10 +5011,12 @@ bool FieldOptions_CType_IsValid(int value) {
}
#ifndef _MSC_VER
+const FieldOptions_CType FieldOptions::STRING;
const FieldOptions_CType FieldOptions::CORD;
const FieldOptions_CType FieldOptions::STRING_PIECE;
const FieldOptions_CType FieldOptions::CType_MIN;
const FieldOptions_CType FieldOptions::CType_MAX;
+const int FieldOptions::CType_ARRAYSIZE;
#endif // _MSC_VER
const ::std::string FieldOptions::_default_experimental_map_key_;
#ifndef _MSC_VER
@@ -4829,7 +5028,7 @@ const int FieldOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FieldOptions::FieldOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -4837,14 +5036,14 @@ void FieldOptions::InitAsDefaultInstance() {
}
FieldOptions::FieldOptions(const FieldOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
void FieldOptions::SharedCtor() {
_cached_size_ = 0;
- ctype_ = 1;
+ ctype_ = 0;
packed_ = false;
deprecated_ = false;
experimental_map_key_ = const_cast< ::std::string*>(&_default_experimental_map_key_);
@@ -4863,6 +5062,11 @@ void FieldOptions::SharedDtor() {
}
}
+void FieldOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FieldOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return FieldOptions_descriptor_;
@@ -4881,7 +5085,7 @@ FieldOptions* FieldOptions::New() const {
void FieldOptions::Clear() {
_extensions_.Clear();
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- ctype_ = 1;
+ ctype_ = 0;
packed_ = false;
deprecated_ = false;
if (_has_bit(3)) {
@@ -4901,18 +5105,21 @@ bool FieldOptions::MergePartialFromCodedStream(
::google::protobuf::uint32 tag;
while ((tag = input->ReadTag()) != 0) {
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- goto handle_uninterpreted;
- }
- int value;
- DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));
- if (::google::protobuf::FieldOptions_CType_IsValid(value)) {
- set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value));
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FieldOptions_CType_IsValid(value)) {
+ set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(1, value);
+ }
} else {
- mutable_unknown_fields()->AddVarint(1, value);
+ goto handle_uninterpreted;
}
if (input->ExpectTag(16)) goto parse_packed;
break;
@@ -4920,57 +5127,63 @@ bool FieldOptions::MergePartialFromCodedStream(
// optional bool packed = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_packed:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &packed_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_packed:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &packed_));
- _set_bit(1);
if (input->ExpectTag(24)) goto parse_deprecated;
break;
}
// optional bool deprecated = 3 [default = false];
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_deprecated:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &deprecated_)));
+ _set_bit(2);
+ } else {
goto handle_uninterpreted;
}
- parse_deprecated:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &deprecated_));
- _set_bit(2);
if (input->ExpectTag(74)) goto parse_experimental_map_key;
break;
}
// optional string experimental_map_key = 9;
case 9: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_experimental_map_key:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_experimental_map_key()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->experimental_map_key().data(), this->experimental_map_key().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_experimental_map_key:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_experimental_map_key()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->experimental_map_key().data(), this->experimental_map_key().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_uninterpreted_option()));
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
if (input->ExpectAtEnd()) return true;
break;
@@ -4999,13 +5212,7 @@ bool FieldOptions::MergePartialFromCodedStream(
void FieldOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FieldOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (_has_bit(0)) {
::google::protobuf::internal::WireFormatLite::WriteEnum(
1, this->ctype(), output);
@@ -5032,7 +5239,7 @@ void FieldOptions::SerializeWithCachedSizes(
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -5048,7 +5255,7 @@ void FieldOptions::SerializeWithCachedSizes(
::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray(
::google::protobuf::uint8* target) const {
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (_has_bit(0)) {
target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
1, this->ctype(), target);
@@ -5096,7 +5303,7 @@ int FieldOptions::ByteSize() const {
int total_size = 0;
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (has_ctype()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype());
@@ -5135,7 +5342,9 @@ int FieldOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -5223,7 +5432,7 @@ const int EnumOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumOptions::EnumOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -5231,7 +5440,7 @@ void EnumOptions::InitAsDefaultInstance() {
}
EnumOptions::EnumOptions(const EnumOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -5250,6 +5459,11 @@ void EnumOptions::SharedDtor() {
}
}
+void EnumOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* EnumOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return EnumOptions_descriptor_;
@@ -5280,13 +5494,14 @@ bool EnumOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_uninterpreted_option()));
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
if (input->ExpectAtEnd()) return true;
break;
@@ -5315,15 +5530,9 @@ bool EnumOptions::MergePartialFromCodedStream(
void EnumOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- EnumOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -5375,7 +5584,9 @@ int EnumOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -5445,7 +5656,7 @@ const int EnumValueOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumValueOptions::EnumValueOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -5453,7 +5664,7 @@ void EnumValueOptions::InitAsDefaultInstance() {
}
EnumValueOptions::EnumValueOptions(const EnumValueOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -5472,6 +5683,11 @@ void EnumValueOptions::SharedDtor() {
}
}
+void EnumValueOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* EnumValueOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return EnumValueOptions_descriptor_;
@@ -5502,13 +5718,14 @@ bool EnumValueOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_uninterpreted_option()));
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
if (input->ExpectAtEnd()) return true;
break;
@@ -5537,15 +5754,9 @@ bool EnumValueOptions::MergePartialFromCodedStream(
void EnumValueOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- EnumValueOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -5597,7 +5808,9 @@ int EnumValueOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -5667,7 +5880,7 @@ const int ServiceOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
ServiceOptions::ServiceOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -5675,7 +5888,7 @@ void ServiceOptions::InitAsDefaultInstance() {
}
ServiceOptions::ServiceOptions(const ServiceOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -5694,6 +5907,11 @@ void ServiceOptions::SharedDtor() {
}
}
+void ServiceOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* ServiceOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return ServiceOptions_descriptor_;
@@ -5724,13 +5942,14 @@ bool ServiceOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_uninterpreted_option()));
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
if (input->ExpectAtEnd()) return true;
break;
@@ -5759,15 +5978,9 @@ bool ServiceOptions::MergePartialFromCodedStream(
void ServiceOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- ServiceOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -5819,7 +6032,9 @@ int ServiceOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -5889,7 +6104,7 @@ const int MethodOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MethodOptions::MethodOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -5897,7 +6112,7 @@ void MethodOptions::InitAsDefaultInstance() {
}
MethodOptions::MethodOptions(const MethodOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -5916,6 +6131,11 @@ void MethodOptions::SharedDtor() {
}
}
+void MethodOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* MethodOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return MethodOptions_descriptor_;
@@ -5946,13 +6166,14 @@ bool MethodOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_uninterpreted_option()));
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
if (input->ExpectAtEnd()) return true;
break;
@@ -5981,15 +6202,9 @@ bool MethodOptions::MergePartialFromCodedStream(
void MethodOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- MethodOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -6041,7 +6256,9 @@ int MethodOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -6113,7 +6330,7 @@ const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
#endif // !_MSC_VER
UninterpretedOption_NamePart::UninterpretedOption_NamePart()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -6121,7 +6338,7 @@ void UninterpretedOption_NamePart::InitAsDefaultInstance() {
}
UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -6145,6 +6362,11 @@ void UninterpretedOption_NamePart::SharedDtor() {
}
}
+void UninterpretedOption_NamePart::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::descriptor() {
protobuf_AssignDescriptorsOnce();
return UninterpretedOption_NamePart_descriptor_;
@@ -6181,29 +6403,32 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// required string name_part = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_name_part()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name_part().data(), this->name_part().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_name_part()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->name_part().data(), this->name_part().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(16)) goto parse_is_extension;
break;
}
// required bool is_extension = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_is_extension:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &is_extension_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_is_extension:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &is_extension_));
- _set_bit(1);
if (input->ExpectAtEnd()) return true;
break;
}
@@ -6226,12 +6451,6 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
void UninterpretedOption_NamePart::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- UninterpretedOption_NamePart::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// required string name_part = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -6298,7 +6517,9 @@ int UninterpretedOption_NamePart::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -6378,7 +6599,7 @@ const int UninterpretedOption::kStringValueFieldNumber;
#endif // !_MSC_VER
UninterpretedOption::UninterpretedOption()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -6386,7 +6607,7 @@ void UninterpretedOption::InitAsDefaultInstance() {
}
UninterpretedOption::UninterpretedOption(const UninterpretedOption& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -6416,6 +6637,11 @@ void UninterpretedOption::SharedDtor() {
}
}
+void UninterpretedOption::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* UninterpretedOption::descriptor() {
protobuf_AssignDescriptorsOnce();
return UninterpretedOption_descriptor_;
@@ -6460,13 +6686,14 @@ bool UninterpretedOption::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_name()));
+ } else {
goto handle_uninterpreted;
}
- parse_name:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_name()));
if (input->ExpectTag(18)) goto parse_name;
if (input->ExpectTag(26)) goto parse_identifier_value;
break;
@@ -6474,71 +6701,79 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// optional string identifier_value = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_identifier_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_identifier_value()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->identifier_value().data(), this->identifier_value().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
goto handle_uninterpreted;
}
- parse_identifier_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_identifier_value()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
- this->identifier_value().data(), this->identifier_value().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(32)) goto parse_positive_int_value;
break;
}
// optional uint64 positive_int_value = 4;
case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_positive_int_value:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+ input, &positive_int_value_)));
+ _set_bit(2);
+ } else {
goto handle_uninterpreted;
}
- parse_positive_int_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadUInt64(
- input, &positive_int_value_));
- _set_bit(2);
if (input->ExpectTag(40)) goto parse_negative_int_value;
break;
}
// optional int64 negative_int_value = 5;
case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_negative_int_value:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+ input, &negative_int_value_)));
+ _set_bit(3);
+ } else {
goto handle_uninterpreted;
}
- parse_negative_int_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt64(
- input, &negative_int_value_));
- _set_bit(3);
if (input->ExpectTag(49)) goto parse_double_value;
break;
}
// optional double double_value = 6;
case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
+ parse_double_value:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+ input, &double_value_)));
+ _set_bit(4);
+ } else {
goto handle_uninterpreted;
}
- parse_double_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadDouble(
- input, &double_value_));
- _set_bit(4);
if (input->ExpectTag(58)) goto parse_string_value;
break;
}
// optional bytes string_value = 7;
case 7: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_string_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+ input, this->mutable_string_value()));
+ } else {
goto handle_uninterpreted;
}
- parse_string_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
- input, this->mutable_string_value()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -6561,15 +6796,9 @@ bool UninterpretedOption::MergePartialFromCodedStream(
void UninterpretedOption::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- UninterpretedOption::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
for (int i = 0; i < this->name_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->name(i), output);
}
@@ -6708,7 +6937,9 @@ int UninterpretedOption::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -6790,5 +7021,9 @@ void UninterpretedOption::Swap(UninterpretedOption* other) {
}
+// @@protoc_insertion_point(namespace_scope)
+
} // namespace protobuf
} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 4bf7369f..7df3ae16 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -1,4 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/descriptor.proto
#ifndef PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
#define PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
@@ -22,6 +23,7 @@
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/generated_message_reflection.h>
+// @@protoc_insertion_point(includes)
namespace google {
namespace protobuf {
@@ -73,6 +75,7 @@ enum FieldDescriptorProto_Type {
LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value);
const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE;
const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64;
+const int FieldDescriptorProto_Type_Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_MAX + 1;
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor();
inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) {
@@ -92,6 +95,7 @@ enum FieldDescriptorProto_Label {
LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value);
const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL;
const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED;
+const int FieldDescriptorProto_Label_Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_MAX + 1;
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor();
inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) {
@@ -111,6 +115,7 @@ enum FileOptions_OptimizeMode {
LIBPROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value);
const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED;
const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME;
+const int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_MAX + 1;
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor();
inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) {
@@ -123,12 +128,14 @@ inline bool FileOptions_OptimizeMode_Parse(
FileOptions_OptimizeMode_descriptor(), name, value);
}
enum FieldOptions_CType {
+ FieldOptions_CType_STRING = 0,
FieldOptions_CType_CORD = 1,
FieldOptions_CType_STRING_PIECE = 2
};
LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
-const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_CORD;
+const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_STRING;
const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE;
+const int FieldOptions_CType_CType_ARRAYSIZE = FieldOptions_CType_CType_MAX + 1;
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor();
inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) {
@@ -164,6 +171,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
static const ::google::protobuf::Descriptor* descriptor();
static const FileDescriptorSet& default_instance();
+
void Swap(FileDescriptorSet* other);
// implements Message ----------------------------------------------
@@ -186,7 +194,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -199,12 +207,15 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
inline int file_size() const;
inline void clear_file();
static const int kFileFieldNumber = 1;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& file() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_file();
inline const ::google::protobuf::FileDescriptorProto& file(int index) const;
inline ::google::protobuf::FileDescriptorProto* mutable_file(int index);
inline ::google::protobuf::FileDescriptorProto* add_file();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ file() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+ mutable_file();
+ // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -254,6 +265,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
static const ::google::protobuf::Descriptor* descriptor();
static const FileDescriptorProto& default_instance();
+
void Swap(FileDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -276,7 +288,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -309,8 +321,6 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline int dependency_size() const;
inline void clear_dependency();
static const int kDependencyFieldNumber = 3;
- inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
- inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
inline const ::std::string& dependency(int index) const;
inline ::std::string* mutable_dependency(int index);
inline void set_dependency(int index, const ::std::string& value);
@@ -320,46 +330,56 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline void add_dependency(const ::std::string& value);
inline void add_dependency(const char* value);
inline void add_dependency(const char* value, size_t size);
+ inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
+ inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
// repeated .google.protobuf.DescriptorProto message_type = 4;
inline int message_type_size() const;
inline void clear_message_type();
static const int kMessageTypeFieldNumber = 4;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& message_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_message_type();
inline const ::google::protobuf::DescriptorProto& message_type(int index) const;
inline ::google::protobuf::DescriptorProto* mutable_message_type(int index);
inline ::google::protobuf::DescriptorProto* add_message_type();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ message_type() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+ mutable_message_type();
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
inline int enum_type_size() const;
inline void clear_enum_type();
static const int kEnumTypeFieldNumber = 5;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& enum_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type();
inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ enum_type() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+ mutable_enum_type();
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
inline int service_size() const;
inline void clear_service();
static const int kServiceFieldNumber = 6;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& service() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* mutable_service();
inline const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
inline ::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
inline ::google::protobuf::ServiceDescriptorProto* add_service();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+ service() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+ mutable_service();
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
inline int extension_size() const;
inline void clear_extension();
static const int kExtensionFieldNumber = 7;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& extension() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension();
inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
inline ::google::protobuf::FieldDescriptorProto* add_extension();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ extension() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ mutable_extension();
// optional .google.protobuf.FileOptions options = 8;
inline bool has_options() const;
@@ -368,6 +388,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline const ::google::protobuf::FileOptions& options() const;
inline ::google::protobuf::FileOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -426,6 +447,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
static const ::google::protobuf::Descriptor* descriptor();
static const DescriptorProto_ExtensionRange& default_instance();
+
void Swap(DescriptorProto_ExtensionRange* other);
// implements Message ----------------------------------------------
@@ -448,7 +470,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -471,6 +493,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
inline ::google::protobuf::int32 end() const;
inline void set_end(::google::protobuf::int32 value);
+ // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -521,6 +544,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const DescriptorProto& default_instance();
+
void Swap(DescriptorProto* other);
// implements Message ----------------------------------------------
@@ -543,7 +567,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -568,51 +592,61 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
inline int field_size() const;
inline void clear_field();
static const int kFieldFieldNumber = 2;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& field() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_field();
inline const ::google::protobuf::FieldDescriptorProto& field(int index) const;
inline ::google::protobuf::FieldDescriptorProto* mutable_field(int index);
inline ::google::protobuf::FieldDescriptorProto* add_field();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ field() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ mutable_field();
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
inline int extension_size() const;
inline void clear_extension();
static const int kExtensionFieldNumber = 6;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& extension() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension();
inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
inline ::google::protobuf::FieldDescriptorProto* add_extension();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ extension() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ mutable_extension();
// repeated .google.protobuf.DescriptorProto nested_type = 3;
inline int nested_type_size() const;
inline void clear_nested_type();
static const int kNestedTypeFieldNumber = 3;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& nested_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_nested_type();
inline const ::google::protobuf::DescriptorProto& nested_type(int index) const;
inline ::google::protobuf::DescriptorProto* mutable_nested_type(int index);
inline ::google::protobuf::DescriptorProto* add_nested_type();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ nested_type() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+ mutable_nested_type();
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
inline int enum_type_size() const;
inline void clear_enum_type();
static const int kEnumTypeFieldNumber = 4;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& enum_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type();
inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ enum_type() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+ mutable_enum_type();
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
inline int extension_range_size() const;
inline void clear_extension_range();
static const int kExtensionRangeFieldNumber = 5;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& extension_range() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* mutable_extension_range();
inline const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
inline ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
inline ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+ extension_range() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+ mutable_extension_range();
// optional .google.protobuf.MessageOptions options = 7;
inline bool has_options() const;
@@ -621,6 +655,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
inline const ::google::protobuf::MessageOptions& options() const;
inline ::google::protobuf::MessageOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -677,6 +712,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
static const ::google::protobuf::Descriptor* descriptor();
static const FieldDescriptorProto& default_instance();
+
void Swap(FieldDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -699,7 +735,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -732,6 +768,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
FieldDescriptorProto_Type_Type_MIN;
static const Type Type_MAX =
FieldDescriptorProto_Type_Type_MAX;
+ static const int Type_ARRAYSIZE =
+ FieldDescriptorProto_Type_Type_ARRAYSIZE;
static inline const ::google::protobuf::EnumDescriptor*
Type_descriptor() {
return FieldDescriptorProto_Type_descriptor();
@@ -755,6 +793,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
FieldDescriptorProto_Label_Label_MIN;
static const Label Label_MAX =
FieldDescriptorProto_Label_Label_MAX;
+ static const int Label_ARRAYSIZE =
+ FieldDescriptorProto_Label_Label_ARRAYSIZE;
static inline const ::google::protobuf::EnumDescriptor*
Label_descriptor() {
return FieldDescriptorProto_Label_descriptor();
@@ -837,6 +877,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline const ::google::protobuf::FieldOptions& options() const;
inline ::google::protobuf::FieldOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -897,6 +938,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
static const ::google::protobuf::Descriptor* descriptor();
static const EnumDescriptorProto& default_instance();
+
void Swap(EnumDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -919,7 +961,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -942,11 +984,13 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
inline int value_size() const;
inline void clear_value();
static const int kValueFieldNumber = 2;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& value() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* mutable_value();
inline const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
inline ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
inline ::google::protobuf::EnumValueDescriptorProto* add_value();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+ value() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+ mutable_value();
// optional .google.protobuf.EnumOptions options = 3;
inline bool has_options() const;
@@ -955,6 +999,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
inline const ::google::protobuf::EnumOptions& options() const;
inline ::google::protobuf::EnumOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -1007,6 +1052,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
static const ::google::protobuf::Descriptor* descriptor();
static const EnumValueDescriptorProto& default_instance();
+
void Swap(EnumValueDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -1029,7 +1075,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1062,6 +1108,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
inline const ::google::protobuf::EnumValueOptions& options() const;
inline ::google::protobuf::EnumValueOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -1114,6 +1161,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
static const ::google::protobuf::Descriptor* descriptor();
static const ServiceDescriptorProto& default_instance();
+
void Swap(ServiceDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -1136,7 +1184,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1159,11 +1207,13 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
inline int method_size() const;
inline void clear_method();
static const int kMethodFieldNumber = 2;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& method() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* mutable_method();
inline const ::google::protobuf::MethodDescriptorProto& method(int index) const;
inline ::google::protobuf::MethodDescriptorProto* mutable_method(int index);
inline ::google::protobuf::MethodDescriptorProto* add_method();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ method() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ mutable_method();
// optional .google.protobuf.ServiceOptions options = 3;
inline bool has_options() const;
@@ -1172,6 +1222,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
inline const ::google::protobuf::ServiceOptions& options() const;
inline ::google::protobuf::ServiceOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -1224,6 +1275,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
static const ::google::protobuf::Descriptor* descriptor();
static const MethodDescriptorProto& default_instance();
+
void Swap(MethodDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -1246,7 +1298,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1292,6 +1344,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline const ::google::protobuf::MethodOptions& options() const;
inline ::google::protobuf::MethodOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -1347,6 +1400,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const FileOptions& default_instance();
+
void Swap(FileOptions* other);
// implements Message ----------------------------------------------
@@ -1369,7 +1423,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1387,6 +1441,8 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
FileOptions_OptimizeMode_OptimizeMode_MIN;
static const OptimizeMode OptimizeMode_MAX =
FileOptions_OptimizeMode_OptimizeMode_MAX;
+ static const int OptimizeMode_ARRAYSIZE =
+ FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE;
static inline const ::google::protobuf::EnumDescriptor*
OptimizeMode_descriptor() {
return FileOptions_OptimizeMode_descriptor();
@@ -1435,17 +1491,41 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
+ // optional bool cc_generic_services = 16 [default = true];
+ inline bool has_cc_generic_services() const;
+ inline void clear_cc_generic_services();
+ static const int kCcGenericServicesFieldNumber = 16;
+ inline bool cc_generic_services() const;
+ inline void set_cc_generic_services(bool value);
+
+ // optional bool java_generic_services = 17 [default = true];
+ inline bool has_java_generic_services() const;
+ inline void clear_java_generic_services();
+ static const int kJavaGenericServicesFieldNumber = 17;
+ inline bool java_generic_services() const;
+ inline void set_java_generic_services(bool value);
+
+ // optional bool py_generic_services = 18 [default = true];
+ inline bool has_py_generic_services() const;
+ inline void clear_py_generic_services();
+ static const int kPyGenericServicesFieldNumber = 18;
+ inline bool py_generic_services() const;
+ inline void set_py_generic_services(bool value);
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1457,12 +1537,15 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
static const ::std::string _default_java_outer_classname_;
bool java_multiple_files_;
int optimize_for_;
+ bool cc_generic_services_;
+ bool java_generic_services_;
+ bool py_generic_services_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
- ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
+ ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
inline bool _has_bit(int index) const {
@@ -1502,6 +1585,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const MessageOptions& default_instance();
+
void Swap(MessageOptions* other);
// implements Message ----------------------------------------------
@@ -1524,7 +1608,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1551,13 +1635,16 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1610,6 +1697,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const FieldOptions& default_instance();
+
void Swap(FieldOptions* other);
// implements Message ----------------------------------------------
@@ -1632,7 +1720,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1640,6 +1728,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
// nested types ----------------------------------------------------
typedef FieldOptions_CType CType;
+ static const CType STRING = FieldOptions_CType_STRING;
static const CType CORD = FieldOptions_CType_CORD;
static const CType STRING_PIECE = FieldOptions_CType_STRING_PIECE;
static inline bool CType_IsValid(int value) {
@@ -1649,6 +1738,8 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
FieldOptions_CType_CType_MIN;
static const CType CType_MAX =
FieldOptions_CType_CType_MAX;
+ static const int CType_ARRAYSIZE =
+ FieldOptions_CType_CType_ARRAYSIZE;
static inline const ::google::protobuf::EnumDescriptor*
CType_descriptor() {
return FieldOptions_CType_descriptor();
@@ -1663,7 +1754,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
inline bool has_ctype() const;
inline void clear_ctype();
static const int kCtypeFieldNumber = 1;
@@ -1698,13 +1789,16 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1760,6 +1854,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const EnumOptions& default_instance();
+
void Swap(EnumOptions* other);
// implements Message ----------------------------------------------
@@ -1782,7 +1877,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1795,13 +1890,16 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1852,6 +1950,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const EnumValueOptions& default_instance();
+
void Swap(EnumValueOptions* other);
// implements Message ----------------------------------------------
@@ -1874,7 +1973,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1887,13 +1986,16 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1944,6 +2046,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const ServiceOptions& default_instance();
+
void Swap(ServiceOptions* other);
// implements Message ----------------------------------------------
@@ -1966,7 +2069,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1979,13 +2082,16 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -2036,6 +2142,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const MethodOptions& default_instance();
+
void Swap(MethodOptions* other);
// implements Message ----------------------------------------------
@@ -2058,7 +2165,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -2071,13 +2178,16 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -2128,6 +2238,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
static const ::google::protobuf::Descriptor* descriptor();
static const UninterpretedOption_NamePart& default_instance();
+
void Swap(UninterpretedOption_NamePart* other);
// implements Message ----------------------------------------------
@@ -2150,7 +2261,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -2176,6 +2287,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
inline bool is_extension() const;
inline void set_is_extension(bool value);
+ // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -2227,6 +2339,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
static const ::google::protobuf::Descriptor* descriptor();
static const UninterpretedOption& default_instance();
+
void Swap(UninterpretedOption* other);
// implements Message ----------------------------------------------
@@ -2249,7 +2362,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -2264,11 +2377,13 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
inline int name_size() const;
inline void clear_name();
static const int kNameFieldNumber = 2;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& name() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* mutable_name();
inline const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
inline ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
inline ::google::protobuf::UninterpretedOption_NamePart* add_name();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+ name() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+ mutable_name();
// optional string identifier_value = 3;
inline bool has_identifier_value() const;
@@ -2311,6 +2426,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
inline void set_string_value(const void* value, size_t size);
inline ::std::string* mutable_string_value();
+ // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -2348,9 +2464,6 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
// ===================================================================
-
-// ===================================================================
-
// FileDescriptorSet
// repeated .google.protobuf.FileDescriptorProto file = 1;
@@ -2360,14 +2473,6 @@ inline int FileDescriptorSet::file_size() const {
inline void FileDescriptorSet::clear_file() {
file_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-FileDescriptorSet::file() const {
- return file_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
-FileDescriptorSet::mutable_file() {
- return &file_;
-}
inline const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
return file_.Get(index);
}
@@ -2377,6 +2482,14 @@ inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(
inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
return file_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+ return file_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+FileDescriptorSet::mutable_file() {
+ return &file_;
+}
// -------------------------------------------------------------------
@@ -2473,14 +2586,6 @@ inline int FileDescriptorProto::dependency_size() const {
inline void FileDescriptorProto::clear_dependency() {
dependency_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
-FileDescriptorProto::dependency() const {
- return dependency_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::std::string>*
-FileDescriptorProto::mutable_dependency() {
- return &dependency_;
-}
inline const ::std::string& FileDescriptorProto::dependency(int index) const {
return dependency_.Get(index);
}
@@ -2509,6 +2614,14 @@ inline void FileDescriptorProto::add_dependency(const char* value) {
inline void FileDescriptorProto::add_dependency(const char* value, size_t size) {
dependency_.Add()->assign(reinterpret_cast<const char*>(value), size);
}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FileDescriptorProto::dependency() const {
+ return dependency_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+FileDescriptorProto::mutable_dependency() {
+ return &dependency_;
+}
// repeated .google.protobuf.DescriptorProto message_type = 4;
inline int FileDescriptorProto::message_type_size() const {
@@ -2517,14 +2630,6 @@ inline int FileDescriptorProto::message_type_size() const {
inline void FileDescriptorProto::clear_message_type() {
message_type_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-FileDescriptorProto::message_type() const {
- return message_type_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
-FileDescriptorProto::mutable_message_type() {
- return &message_type_;
-}
inline const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
return message_type_.Get(index);
}
@@ -2534,6 +2639,14 @@ inline ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message
inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() {
return message_type_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+ return message_type_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+FileDescriptorProto::mutable_message_type() {
+ return &message_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
inline int FileDescriptorProto::enum_type_size() const {
@@ -2542,14 +2655,6 @@ inline int FileDescriptorProto::enum_type_size() const {
inline void FileDescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-FileDescriptorProto::enum_type() const {
- return enum_type_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
-FileDescriptorProto::mutable_enum_type() {
- return &enum_type_;
-}
inline const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
return enum_type_.Get(index);
}
@@ -2559,6 +2664,14 @@ inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enu
inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
return enum_type_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+ return enum_type_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+FileDescriptorProto::mutable_enum_type() {
+ return &enum_type_;
+}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
inline int FileDescriptorProto::service_size() const {
@@ -2567,14 +2680,6 @@ inline int FileDescriptorProto::service_size() const {
inline void FileDescriptorProto::clear_service() {
service_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
-FileDescriptorProto::service() const {
- return service_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
-FileDescriptorProto::mutable_service() {
- return &service_;
-}
inline const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
return service_.Get(index);
}
@@ -2584,6 +2689,14 @@ inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_
inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() {
return service_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+ return service_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+FileDescriptorProto::mutable_service() {
+ return &service_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
inline int FileDescriptorProto::extension_size() const {
@@ -2592,14 +2705,6 @@ inline int FileDescriptorProto::extension_size() const {
inline void FileDescriptorProto::clear_extension() {
extension_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-FileDescriptorProto::extension() const {
- return extension_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
-FileDescriptorProto::mutable_extension() {
- return &extension_;
-}
inline const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
return extension_.Get(index);
}
@@ -2609,6 +2714,14 @@ inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_ex
inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() {
return extension_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+ return extension_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+FileDescriptorProto::mutable_extension() {
+ return &extension_;
+}
// optional .google.protobuf.FileOptions options = 8;
inline bool FileDescriptorProto::has_options() const {
@@ -2716,14 +2829,6 @@ inline int DescriptorProto::field_size() const {
inline void DescriptorProto::clear_field() {
field_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::field() const {
- return field_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
-DescriptorProto::mutable_field() {
- return &field_;
-}
inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
return field_.Get(index);
}
@@ -2733,6 +2838,14 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(
inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
return field_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+ return field_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_field() {
+ return &field_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
inline int DescriptorProto::extension_size() const {
@@ -2741,14 +2854,6 @@ inline int DescriptorProto::extension_size() const {
inline void DescriptorProto::clear_extension() {
extension_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::extension() const {
- return extension_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
-DescriptorProto::mutable_extension() {
- return &extension_;
-}
inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
return extension_.Get(index);
}
@@ -2758,6 +2863,14 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extens
inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() {
return extension_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+ return extension_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_extension() {
+ return &extension_;
+}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
inline int DescriptorProto::nested_type_size() const {
@@ -2766,14 +2879,6 @@ inline int DescriptorProto::nested_type_size() const {
inline void DescriptorProto::clear_nested_type() {
nested_type_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-DescriptorProto::nested_type() const {
- return nested_type_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
-DescriptorProto::mutable_nested_type() {
- return &nested_type_;
-}
inline const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
return nested_type_.Get(index);
}
@@ -2783,6 +2888,14 @@ inline ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type
inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
return nested_type_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+ return nested_type_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+DescriptorProto::mutable_nested_type() {
+ return &nested_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
inline int DescriptorProto::enum_type_size() const {
@@ -2791,14 +2904,6 @@ inline int DescriptorProto::enum_type_size() const {
inline void DescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-DescriptorProto::enum_type() const {
- return enum_type_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
-DescriptorProto::mutable_enum_type() {
- return &enum_type_;
-}
inline const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
return enum_type_.Get(index);
}
@@ -2808,6 +2913,14 @@ inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_ty
inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() {
return enum_type_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+ return enum_type_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+DescriptorProto::mutable_enum_type() {
+ return &enum_type_;
+}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
inline int DescriptorProto::extension_range_size() const {
@@ -2816,14 +2929,6 @@ inline int DescriptorProto::extension_range_size() const {
inline void DescriptorProto::clear_extension_range() {
extension_range_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
-DescriptorProto::extension_range() const {
- return extension_range_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
-DescriptorProto::mutable_extension_range() {
- return &extension_range_;
-}
inline const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
return extension_range_.Get(index);
}
@@ -2833,6 +2938,14 @@ inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::muta
inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
return extension_range_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+ return extension_range_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+DescriptorProto::mutable_extension_range() {
+ return &extension_range_;
+}
// optional .google.protobuf.MessageOptions options = 7;
inline bool DescriptorProto::has_options() const {
@@ -3143,14 +3256,6 @@ inline int EnumDescriptorProto::value_size() const {
inline void EnumDescriptorProto::clear_value() {
value_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
-EnumDescriptorProto::value() const {
- return value_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
-EnumDescriptorProto::mutable_value() {
- return &value_;
-}
inline const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
return value_.Get(index);
}
@@ -3160,6 +3265,14 @@ inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutabl
inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
return value_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+ return value_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+EnumDescriptorProto::mutable_value() {
+ return &value_;
+}
// optional .google.protobuf.EnumOptions options = 3;
inline bool EnumDescriptorProto::has_options() const {
@@ -3310,14 +3423,6 @@ inline int ServiceDescriptorProto::method_size() const {
inline void ServiceDescriptorProto::clear_method() {
method_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
-ServiceDescriptorProto::method() const {
- return method_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
-ServiceDescriptorProto::mutable_method() {
- return &method_;
-}
inline const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
return method_.Get(index);
}
@@ -3327,6 +3432,14 @@ inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutabl
inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
return method_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+ return method_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ServiceDescriptorProto::mutable_method() {
+ return &method_;
+}
// optional .google.protobuf.ServiceOptions options = 3;
inline bool ServiceDescriptorProto::has_options() const {
@@ -3613,6 +3726,54 @@ inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_Optimi
optimize_for_ = value;
}
+// optional bool cc_generic_services = 16 [default = true];
+inline bool FileOptions::has_cc_generic_services() const {
+ return _has_bit(4);
+}
+inline void FileOptions::clear_cc_generic_services() {
+ cc_generic_services_ = true;
+ _clear_bit(4);
+}
+inline bool FileOptions::cc_generic_services() const {
+ return cc_generic_services_;
+}
+inline void FileOptions::set_cc_generic_services(bool value) {
+ _set_bit(4);
+ cc_generic_services_ = value;
+}
+
+// optional bool java_generic_services = 17 [default = true];
+inline bool FileOptions::has_java_generic_services() const {
+ return _has_bit(5);
+}
+inline void FileOptions::clear_java_generic_services() {
+ java_generic_services_ = true;
+ _clear_bit(5);
+}
+inline bool FileOptions::java_generic_services() const {
+ return java_generic_services_;
+}
+inline void FileOptions::set_java_generic_services(bool value) {
+ _set_bit(5);
+ java_generic_services_ = value;
+}
+
+// optional bool py_generic_services = 18 [default = true];
+inline bool FileOptions::has_py_generic_services() const {
+ return _has_bit(6);
+}
+inline void FileOptions::clear_py_generic_services() {
+ py_generic_services_ = true;
+ _clear_bit(6);
+}
+inline bool FileOptions::py_generic_services() const {
+ return py_generic_services_;
+}
+inline void FileOptions::set_py_generic_services(bool value) {
+ _set_bit(6);
+ py_generic_services_ = value;
+}
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int FileOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
@@ -3620,14 +3781,6 @@ inline int FileOptions::uninterpreted_option_size() const {
inline void FileOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FileOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-FileOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3637,6 +3790,14 @@ inline ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpret
inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FileOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3681,14 +3842,6 @@ inline int MessageOptions::uninterpreted_option_size() const {
inline void MessageOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MessageOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-MessageOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3698,17 +3851,25 @@ inline ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterp
inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MessageOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
// FieldOptions
-// optional .google.protobuf.FieldOptions.CType ctype = 1;
+// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
inline bool FieldOptions::has_ctype() const {
return _has_bit(0);
}
inline void FieldOptions::clear_ctype() {
- ctype_ = 1;
+ ctype_ = 0;
_clear_bit(0);
}
inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const {
@@ -3801,14 +3962,6 @@ inline int FieldOptions::uninterpreted_option_size() const {
inline void FieldOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FieldOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-FieldOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3818,6 +3971,14 @@ inline ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpre
inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FieldOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3830,14 +3991,6 @@ inline int EnumOptions::uninterpreted_option_size() const {
inline void EnumOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-EnumOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3847,6 +4000,14 @@ inline ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpret
inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3859,14 +4020,6 @@ inline int EnumValueOptions::uninterpreted_option_size() const {
inline void EnumValueOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumValueOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-EnumValueOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3876,6 +4029,14 @@ inline ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninte
inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumValueOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3888,14 +4049,6 @@ inline int ServiceOptions::uninterpreted_option_size() const {
inline void ServiceOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-ServiceOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-ServiceOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3905,6 +4058,14 @@ inline ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterp
inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ServiceOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3917,14 +4078,6 @@ inline int MethodOptions::uninterpreted_option_size() const {
inline void MethodOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MethodOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-MethodOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3934,6 +4087,14 @@ inline ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpr
inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MethodOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -4008,14 +4169,6 @@ inline int UninterpretedOption::name_size() const {
inline void UninterpretedOption::clear_name() {
name_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
-UninterpretedOption::name() const {
- return name_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
-UninterpretedOption::mutable_name() {
- return &name_;
-}
inline const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
return name_.Get(index);
}
@@ -4025,6 +4178,14 @@ inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mu
inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
return name_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+ return name_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+UninterpretedOption::mutable_name() {
+ return &name_;
+}
// optional string identifier_value = 3;
inline bool UninterpretedOption::has_identifier_value() const {
@@ -4159,6 +4320,8 @@ inline ::std::string* UninterpretedOption::mutable_string_value() {
}
+// @@protoc_insertion_point(namespace_scope)
+
} // namespace protobuf
} // namespace google
@@ -4187,4 +4350,6 @@ inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions
} // namespace protobuf
#endif // SWIG
+// @@protoc_insertion_point(global_scope)
+
#endif // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 4db88a82..cc04aa8e 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -256,6 +256,22 @@ message FileOptions {
+
+ // Should generic services be generated in each language? "Generic" services
+ // are not specific to any particular RPC system. They are generated by the
+ // main code generators in each language (without additional plugins).
+ // Generic services were the only kind of service generation supported by
+ // early versions of proto2.
+ //
+ // Generic services are now considered deprecated in favor of using plugins
+ // that generate code specific to your particular RPC system. If you are
+ // using such a plugin, set these to false. In the future, we may change
+ // the default to false, so if you explicitly want generic services, you
+ // should explicitly set these to true.
+ optional bool cc_generic_services = 16 [default=true];
+ optional bool java_generic_services = 17 [default=true];
+ optional bool py_generic_services = 18 [default=true];
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -301,8 +317,11 @@ message FieldOptions {
// representation of the field than it normally would. See the specific
// options below. This option is not yet implemented in the open source
// release -- sorry, we'll try to include it in a future version!
- optional CType ctype = 1;
+ optional CType ctype = 1 [default = STRING];
enum CType {
+ // Default mode.
+ STRING = 0;
+
CORD = 1;
STRING_PIECE = 2;
@@ -313,6 +332,7 @@ message FieldOptions {
// a single length-delimited blob.
optional bool packed = 2;
+
// Is this field deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for accessors, or it will be completely ignored; in the very least, this
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index 6ea674d1..95708d94 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -37,6 +37,7 @@
#include <set>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/stl_util-inl.h>
#include <google/protobuf/stubs/map-util.h>
@@ -336,6 +337,35 @@ bool EncodedDescriptorDatabase::FindFileContainingSymbol(
return MaybeParse(index_.FindSymbol(symbol_name), output);
}
+bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol(
+ const string& symbol_name,
+ string* output) {
+ pair<const void*, int> encoded_file = index_.FindSymbol(symbol_name);
+ if (encoded_file.first == NULL) return false;
+
+ // Optimization: The name should be the first field in the encoded message.
+ // Try to just read it directly.
+ io::CodedInputStream input(reinterpret_cast<const uint8*>(encoded_file.first),
+ encoded_file.second);
+
+ const uint32 kNameTag = internal::WireFormatLite::MakeTag(
+ FileDescriptorProto::kNameFieldNumber,
+ internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+
+ if (input.ReadTag() == kNameTag) {
+ // Success!
+ return internal::WireFormatLite::ReadString(&input, output);
+ } else {
+ // Slow path. Parse whole message.
+ FileDescriptorProto file_proto;
+ if (!file_proto.ParseFromArray(encoded_file.first, encoded_file.second)) {
+ return false;
+ }
+ *output = file_proto.name();
+ return true;
+ }
+}
+
bool EncodedDescriptorDatabase::FindFileContainingExtension(
const string& containing_type,
int field_number,
diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h
index c23ab75f..f32b1db9 100644
--- a/src/google/protobuf/descriptor_database.h
+++ b/src/google/protobuf/descriptor_database.h
@@ -280,6 +280,10 @@ class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
// need to keep it around.
bool AddCopy(const void* encoded_file_descriptor, int size);
+ // Like FindFileContainingSymbol but returns only the name of the file.
+ bool FindNameOfFileContainingSymbol(const string& symbol_name,
+ string* output);
+
// implements DescriptorDatabase -----------------------------------
bool FindFileByName(const string& filename,
FileDescriptorProto* output);
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index 33de1348..ac72ddcd 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -480,6 +480,40 @@ INSTANTIATE_TEST_CASE_P(Pool, DescriptorDatabaseTest,
#endif // GTEST_HAS_PARAM_TEST
+TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) {
+ // Create two files, one of which is in two parts.
+ FileDescriptorProto file1, file2a, file2b;
+ file1.set_name("foo.proto");
+ file1.set_package("foo");
+ file1.add_message_type()->set_name("Foo");
+ file2a.set_name("bar.proto");
+ file2b.set_package("bar");
+ file2b.add_message_type()->set_name("Bar");
+
+ // Normal serialization allows our optimization to kick in.
+ string data1 = file1.SerializeAsString();
+
+ // Force out-of-order serialization to test slow path.
+ string data2 = file2b.SerializeAsString() + file2a.SerializeAsString();
+
+ // Create EncodedDescriptorDatabase containing both files.
+ EncodedDescriptorDatabase db;
+ db.Add(data1.data(), data1.size());
+ db.Add(data2.data(), data2.size());
+
+ // Test!
+ string filename;
+ EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo", &filename));
+ EXPECT_EQ("foo.proto", filename);
+ EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo.Blah", &filename));
+ EXPECT_EQ("foo.proto", filename);
+ EXPECT_TRUE(db.FindNameOfFileContainingSymbol("bar.Bar", &filename));
+ EXPECT_EQ("bar.proto", filename);
+ EXPECT_FALSE(db.FindNameOfFileContainingSymbol("foo", &filename));
+ EXPECT_FALSE(db.FindNameOfFileContainingSymbol("bar", &filename));
+ EXPECT_FALSE(db.FindNameOfFileContainingSymbol("baz.Baz", &filename));
+}
+
// ===================================================================
class MergedDescriptorDatabaseTest : public testing::Test {
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 8fcfba3e..ec2c8152 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -3948,6 +3948,9 @@ TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
EXPECT_EQ(0, call_counter.call_count_);
}
+// ===================================================================
+
+
} // namespace descriptor_unittest
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index f8b5b4ea..c711a2da 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -106,7 +106,11 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
case FD::CPPTYPE_MESSAGE: return sizeof(RepeatedPtrField<Message>);
case FD::CPPTYPE_STRING:
- return sizeof(RepeatedPtrField<string>);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return sizeof(RepeatedPtrField<string>);
+ }
break;
}
} else {
@@ -122,7 +126,11 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
case FD::CPPTYPE_MESSAGE: return sizeof(Message*);
case FD::CPPTYPE_STRING:
- return sizeof(string*);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return sizeof(string*);
+ }
break;
}
}
@@ -262,19 +270,24 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
break;
case FieldDescriptor::CPPTYPE_STRING:
- if (!field->is_repeated()) {
- if (is_prototype()) {
- new(field_ptr) const string*(&field->default_value_string());
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ if (!field->is_repeated()) {
+ if (is_prototype()) {
+ new(field_ptr) const string*(&field->default_value_string());
+ } else {
+ string* default_value =
+ *reinterpret_cast<string* const*>(
+ type_info_->prototype->OffsetToPointer(
+ type_info_->offsets[i]));
+ new(field_ptr) string*(default_value);
+ }
} else {
- string* default_value =
- *reinterpret_cast<string* const*>(
- type_info_->prototype->OffsetToPointer(
- type_info_->offsets[i]));
- new(field_ptr) string*(default_value);
+ new(field_ptr) RepeatedPtrField<string>();
}
- } else {
- new(field_ptr) RepeatedPtrField<string>();
- }
+ break;
+ }
break;
case FieldDescriptor::CPPTYPE_MESSAGE: {
@@ -329,8 +342,13 @@ DynamicMessage::~DynamicMessage() {
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
- reinterpret_cast<RepeatedPtrField<string>*>(field_ptr)
- ->~RepeatedPtrField<string>();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ reinterpret_cast<RepeatedPtrField<string>*>(field_ptr)
+ ->~RepeatedPtrField<string>();
+ break;
+ }
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -340,10 +358,16 @@ DynamicMessage::~DynamicMessage() {
}
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
- string* ptr = *reinterpret_cast<string**>(field_ptr);
- if (ptr != &field->default_value_string()) {
- delete ptr;
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING: {
+ string* ptr = *reinterpret_cast<string**>(field_ptr);
+ if (ptr != &field->default_value_string()) {
+ delete ptr;
+ }
+ break;
}
+ }
} else if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) &&
!is_prototype()) {
Message* message = *reinterpret_cast<Message**>(field_ptr);
@@ -373,7 +397,7 @@ void DynamicMessage::CrossLinkPrototypes() {
// For singular fields, the field is just a pointer which should
// point to the prototype.
*reinterpret_cast<const Message**>(field_ptr) =
- factory->GetPrototype(field->message_type());
+ factory->GetPrototypeNoLock(field->message_type());
}
}
}
@@ -410,11 +434,13 @@ struct DynamicMessageFactory::PrototypeMap {
};
DynamicMessageFactory::DynamicMessageFactory()
- : pool_(NULL), prototypes_(new PrototypeMap) {
+ : pool_(NULL), delegate_to_generated_factory_(false),
+ prototypes_(new PrototypeMap) {
}
DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
- : pool_(pool), prototypes_(new PrototypeMap) {
+ : pool_(pool), delegate_to_generated_factory_(false),
+ prototypes_(new PrototypeMap) {
}
DynamicMessageFactory::~DynamicMessageFactory() {
@@ -424,8 +450,18 @@ DynamicMessageFactory::~DynamicMessageFactory() {
}
}
-
const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
+ MutexLock lock(&prototypes_mutex_);
+ return GetPrototypeNoLock(type);
+}
+
+const Message* DynamicMessageFactory::GetPrototypeNoLock(
+ const Descriptor* type) {
+ if (delegate_to_generated_factory_ &&
+ type->file()->pool() == DescriptorPool::generated_pool()) {
+ return MessageFactory::generated_factory()->GetPrototype(type);
+ }
+
const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
if (*target != NULL) {
// Already exists.
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index f38d3b09..81dd2c63 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -73,9 +73,25 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
// Construct a DynamicMessageFactory that will search for extensions in
// the given DescriptorPool.
+ //
+ // DEPRECATED: Use CodedInputStream::SetExtensionRegistry() to tell the
+ // parser to look for extensions in an alternate pool. However, note that
+ // this is almost never what you want to do. Almost all users should use
+ // the zero-arg constructor.
DynamicMessageFactory(const DescriptorPool* pool);
+
~DynamicMessageFactory();
+ // Call this to tell the DynamicMessageFactory that if it is given a
+ // Descriptor d for which:
+ // d->file()->pool() == DescriptorPool::generated_pool(),
+ // then it should delegate to MessageFactory::generated_factory() instead
+ // of constructing a dynamic implementation of the message. In theory there
+ // is no down side to doing this, so it may become the default in the future.
+ void SetDelegateToGeneratedFactory(bool enable) {
+ delegate_to_generated_factory_ = enable;
+ }
+
// implements MessageFactory ---------------------------------------
// Given a Descriptor, constructs the default (prototype) Message of that
@@ -92,14 +108,12 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
// The given descriptor must outlive the returned message, and hence must
// outlive the DynamicMessageFactory.
//
- // Note that while GetPrototype() is idempotent, it is not const. This
- // implies that it is not thread-safe to call GetPrototype() on the same
- // DynamicMessageFactory in two different threads simultaneously. However,
- // the returned objects are just as thread-safe as any other Message.
+ // The method is thread-safe.
const Message* GetPrototype(const Descriptor* type);
private:
const DescriptorPool* pool_;
+ bool delegate_to_generated_factory_;
// This struct just contains a hash_map. We can't #include <google/protobuf/stubs/hash.h> from
// this header due to hacks needed for hash_map portability in the open source
@@ -108,6 +122,10 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
// headers may only #include other public headers.
struct PrototypeMap;
scoped_ptr<PrototypeMap> prototypes_;
+ mutable Mutex prototypes_mutex_;
+
+ friend class DynamicMessage;
+ const Message* GetPrototypeNoLock(const Descriptor* type);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
};
@@ -116,4 +134,3 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
} // namespace google
#endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
-
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 4d5eb6cc..b1ffb0f5 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -59,24 +59,10 @@ inline WireFormatLite::CppType cpp_type(FieldType type) {
}
// Registry stuff.
-struct ExtensionInfo {
- inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
- : type(type), is_repeated(is_repeated), is_packed(is_packed) {}
-
- FieldType type;
- bool is_repeated;
- bool is_packed;
-
- union {
- ExtensionSet::EnumValidityFunc* enum_is_valid;
- const MessageLite* message_prototype;
- };
-};
-
typedef hash_map<pair<const MessageLite*, int>,
ExtensionInfo> ExtensionRegistry;
ExtensionRegistry* registry_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_);
+GoogleOnceType registry_init_;
void DeleteRegistry() {
delete registry_;
@@ -110,6 +96,19 @@ const ExtensionInfo* FindRegisteredExtension(
} // namespace
+ExtensionFinder::~ExtensionFinder() {}
+
+bool GeneratedExtensionFinder::Find(int number, ExtensionInfo* output) {
+ const ExtensionInfo* extension =
+ FindRegisteredExtension(containing_type_, number);
+ if (extension == NULL) {
+ return false;
+ } else {
+ *output = *extension;
+ return true;
+ }
+}
+
void ExtensionSet::RegisterExtension(const MessageLite* containing_type,
int number, FieldType type,
bool is_repeated, bool is_packed) {
@@ -120,13 +119,18 @@ void ExtensionSet::RegisterExtension(const MessageLite* containing_type,
Register(containing_type, number, info);
}
+static bool CallNoArgValidityFunc(const void* arg, int number) {
+ return reinterpret_cast<const EnumValidityFunc*>(arg)(number);
+}
+
void ExtensionSet::RegisterEnumExtension(const MessageLite* containing_type,
int number, FieldType type,
bool is_repeated, bool is_packed,
EnumValidityFunc* is_valid) {
GOOGLE_CHECK_EQ(type, WireFormatLite::TYPE_ENUM);
ExtensionInfo info(type, is_repeated, is_packed);
- info.enum_is_valid = is_valid;
+ info.enum_is_valid = CallNoArgValidityFunc;
+ info.enum_is_valid_arg = reinterpret_cast<void*>(is_valid);
Register(containing_type, number, info);
}
@@ -211,9 +215,10 @@ LOWERCASE ExtensionSet::Get##CAMELCASE(int number, \
} \
\
void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \
- LOWERCASE value) { \
+ LOWERCASE value, \
+ const FieldDescriptor* descriptor) { \
Extension* extension; \
- if (MaybeNewExtension(number, &extension)) { \
+ if (MaybeNewExtension(number, descriptor, &extension)) { \
extension->type = type; \
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \
extension->is_repeated = false; \
@@ -240,9 +245,10 @@ void ExtensionSet::SetRepeated##CAMELCASE( \
} \
\
void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \
- bool packed, LOWERCASE value) { \
+ bool packed, LOWERCASE value, \
+ const FieldDescriptor* descriptor) { \
Extension* extension; \
- if (MaybeNewExtension(number, &extension)) { \
+ if (MaybeNewExtension(number, descriptor, &extension)) { \
extension->type = type; \
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \
extension->is_repeated = true; \
@@ -279,9 +285,10 @@ int ExtensionSet::GetEnum(int number, int default_value) const {
}
}
-void ExtensionSet::SetEnum(int number, FieldType type, int value) {
+void ExtensionSet::SetEnum(int number, FieldType type, int value,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
extension->is_repeated = false;
@@ -307,9 +314,10 @@ void ExtensionSet::SetRepeatedEnum(int number, int index, int value) {
}
void ExtensionSet::AddEnum(int number, FieldType type,
- bool packed, int value) {
+ bool packed, int value,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
extension->is_repeated = true;
@@ -337,9 +345,10 @@ const string& ExtensionSet::GetString(int number,
}
}
-string* ExtensionSet::MutableString(int number, FieldType type) {
+string* ExtensionSet::MutableString(int number, FieldType type,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
extension->is_repeated = false;
@@ -365,9 +374,10 @@ string* ExtensionSet::MutableRepeatedString(int number, int index) {
return iter->second.repeated_string_value->Mutable(index);
}
-string* ExtensionSet::AddString(int number, FieldType type) {
+string* ExtensionSet::AddString(int number, FieldType type,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
extension->is_repeated = true;
@@ -400,9 +410,10 @@ const MessageLite& ExtensionSet::GetMessage(
// MessageFactory* factory) const
MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
- const MessageLite& prototype) {
+ const MessageLite& prototype,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = false;
@@ -435,9 +446,10 @@ MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) {
}
MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
- const MessageLite& prototype) {
+ const MessageLite& prototype,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = true;
@@ -563,7 +575,8 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
if (other_extension.is_repeated) {
Extension* extension;
- bool is_new = MaybeNewExtension(iter->first, &extension);
+ bool is_new = MaybeNewExtension(iter->first, other_extension.descriptor,
+ &extension);
if (is_new) {
// Extension did not already exist in set.
extension->type = other_extension.type;
@@ -622,7 +635,8 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \
case WireFormatLite::CPPTYPE_##UPPERCASE: \
Set##CAMELCASE(iter->first, other_extension.type, \
- other_extension.LOWERCASE##_value); \
+ other_extension.LOWERCASE##_value, \
+ other_extension.descriptor); \
break;
HANDLE_TYPE( INT32, int32, Int32);
@@ -636,11 +650,13 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
#undef HANDLE_TYPE
case WireFormatLite::CPPTYPE_STRING:
SetString(iter->first, other_extension.type,
- *other_extension.string_value);
+ *other_extension.string_value,
+ other_extension.descriptor);
break;
case WireFormatLite::CPPTYPE_MESSAGE:
MutableMessage(iter->first, other_extension.type,
- *other_extension.message_value)
+ *other_extension.message_value,
+ other_extension.descriptor)
->CheckTypeAndMergeFrom(*other_extension.message_value);
break;
}
@@ -678,64 +694,66 @@ bool ExtensionSet::IsInitialized() const {
}
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
- const MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper) {
int number = WireFormatLite::GetTagFieldNumber(tag);
WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
- const ExtensionInfo* extension =
- FindRegisteredExtension(containing_type, number);
-
+ ExtensionInfo extension;
bool is_unknown;
- if (extension == NULL) {
+ if (!extension_finder->Find(number, &extension)) {
is_unknown = true;
- } else if (extension->is_packed) {
+ } else if (extension.is_packed) {
is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
} else {
WireFormatLite::WireType expected_wire_type =
- WireFormatLite::WireTypeForFieldType(real_type(extension->type));
+ WireFormatLite::WireTypeForFieldType(real_type(extension.type));
is_unknown = (wire_type != expected_wire_type);
}
if (is_unknown) {
field_skipper->SkipField(input, tag);
- } else if (extension->is_packed) {
+ } else if (extension.is_packed) {
uint32 size;
if (!input->ReadVarint32(&size)) return false;
io::CodedInputStream::Limit limit = input->PushLimit(size);
- switch (extension->type) {
-#define HANDLE_TYPE(UPPERCASE, CAMELCASE, CPP_CAMELCASE, CPP_LOWERCASE) \
+ switch (extension.type) {
+#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \
case WireFormatLite::TYPE_##UPPERCASE: \
while (input->BytesUntilLimit() > 0) { \
CPP_LOWERCASE value; \
- if (!WireFormatLite::Read##CAMELCASE(input, &value)) return false; \
+ if (!WireFormatLite::ReadPrimitive< \
+ CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \
+ input, &value)) return false; \
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
- true, value); \
+ true, value, extension.descriptor); \
} \
break
- HANDLE_TYPE( INT32, Int32, Int32, int32);
- HANDLE_TYPE( INT64, Int64, Int64, int64);
- HANDLE_TYPE( UINT32, UInt32, UInt32, uint32);
- HANDLE_TYPE( UINT64, UInt64, UInt64, uint64);
- HANDLE_TYPE( SINT32, SInt32, Int32, int32);
- HANDLE_TYPE( SINT64, SInt64, Int64, int64);
- HANDLE_TYPE( FIXED32, Fixed32, UInt32, uint32);
- HANDLE_TYPE( FIXED64, Fixed64, UInt64, uint64);
- HANDLE_TYPE(SFIXED32, SFixed32, Int32, int32);
- HANDLE_TYPE(SFIXED64, SFixed64, Int64, int64);
- HANDLE_TYPE( FLOAT, Float, Float, float);
- HANDLE_TYPE( DOUBLE, Double, Double, double);
- HANDLE_TYPE( BOOL, Bool, Bool, bool);
+ HANDLE_TYPE( INT32, Int32, int32);
+ HANDLE_TYPE( INT64, Int64, int64);
+ HANDLE_TYPE( UINT32, UInt32, uint32);
+ HANDLE_TYPE( UINT64, UInt64, uint64);
+ HANDLE_TYPE( SINT32, Int32, int32);
+ HANDLE_TYPE( SINT64, Int64, int64);
+ HANDLE_TYPE( FIXED32, UInt32, uint32);
+ HANDLE_TYPE( FIXED64, UInt64, uint64);
+ HANDLE_TYPE(SFIXED32, Int32, int32);
+ HANDLE_TYPE(SFIXED64, Int64, int64);
+ HANDLE_TYPE( FLOAT, Float, float);
+ HANDLE_TYPE( DOUBLE, Double, double);
+ HANDLE_TYPE( BOOL, Bool, bool);
#undef HANDLE_TYPE
case WireFormatLite::TYPE_ENUM:
while (input->BytesUntilLimit() > 0) {
int value;
- if (!WireFormatLite::ReadEnum(input, &value)) return false;
- if (extension->enum_is_valid(value)) {
- AddEnum(number, WireFormatLite::TYPE_ENUM, true, value);
+ if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ input, &value)) return false;
+ if (extension.enum_is_valid(extension.enum_is_valid_arg, value)) {
+ AddEnum(number, WireFormatLite::TYPE_ENUM, true, value,
+ extension.descriptor);
}
}
break;
@@ -750,81 +768,89 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
input->PopLimit(limit);
} else {
- switch (extension->type) {
-#define HANDLE_TYPE(UPPERCASE, CAMELCASE, CPP_CAMELCASE, CPP_LOWERCASE) \
+ switch (extension.type) {
+#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \
case WireFormatLite::TYPE_##UPPERCASE: { \
CPP_LOWERCASE value; \
- if (!WireFormatLite::Read##CAMELCASE(input, &value)) return false; \
- if (extension->is_repeated) { \
+ if (!WireFormatLite::ReadPrimitive< \
+ CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \
+ input, &value)) return false; \
+ if (extension.is_repeated) { \
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
- false, value); \
+ false, value, extension.descriptor); \
} else { \
- Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value); \
+ Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
+ extension.descriptor); \
} \
} break
- HANDLE_TYPE( INT32, Int32, Int32, int32);
- HANDLE_TYPE( INT64, Int64, Int64, int64);
- HANDLE_TYPE( UINT32, UInt32, UInt32, uint32);
- HANDLE_TYPE( UINT64, UInt64, UInt64, uint64);
- HANDLE_TYPE( SINT32, SInt32, Int32, int32);
- HANDLE_TYPE( SINT64, SInt64, Int64, int64);
- HANDLE_TYPE( FIXED32, Fixed32, UInt32, uint32);
- HANDLE_TYPE( FIXED64, Fixed64, UInt64, uint64);
- HANDLE_TYPE(SFIXED32, SFixed32, Int32, int32);
- HANDLE_TYPE(SFIXED64, SFixed64, Int64, int64);
- HANDLE_TYPE( FLOAT, Float, Float, float);
- HANDLE_TYPE( DOUBLE, Double, Double, double);
- HANDLE_TYPE( BOOL, Bool, Bool, bool);
+ HANDLE_TYPE( INT32, Int32, int32);
+ HANDLE_TYPE( INT64, Int64, int64);
+ HANDLE_TYPE( UINT32, UInt32, uint32);
+ HANDLE_TYPE( UINT64, UInt64, uint64);
+ HANDLE_TYPE( SINT32, Int32, int32);
+ HANDLE_TYPE( SINT64, Int64, int64);
+ HANDLE_TYPE( FIXED32, UInt32, uint32);
+ HANDLE_TYPE( FIXED64, UInt64, uint64);
+ HANDLE_TYPE(SFIXED32, Int32, int32);
+ HANDLE_TYPE(SFIXED64, Int64, int64);
+ HANDLE_TYPE( FLOAT, Float, float);
+ HANDLE_TYPE( DOUBLE, Double, double);
+ HANDLE_TYPE( BOOL, Bool, bool);
#undef HANDLE_TYPE
case WireFormatLite::TYPE_ENUM: {
int value;
- if (!WireFormatLite::ReadEnum(input, &value)) return false;
+ if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ input, &value)) return false;
- if (!extension->enum_is_valid(value)) {
+ if (!extension.enum_is_valid(extension.enum_is_valid_arg, value)) {
// Invalid value. Treat as unknown.
field_skipper->SkipUnknownEnum(number, value);
- } else if (extension->is_repeated) {
- AddEnum(number, WireFormatLite::TYPE_ENUM, false, value);
+ } else if (extension.is_repeated) {
+ AddEnum(number, WireFormatLite::TYPE_ENUM, false, value,
+ extension.descriptor);
} else {
- SetEnum(number, WireFormatLite::TYPE_ENUM, value);
+ SetEnum(number, WireFormatLite::TYPE_ENUM, value,
+ extension.descriptor);
}
break;
}
case WireFormatLite::TYPE_STRING: {
- string* value = extension->is_repeated ?
- AddString(number, WireFormatLite::TYPE_STRING) :
- MutableString(number, WireFormatLite::TYPE_STRING);
+ string* value = extension.is_repeated ?
+ AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) :
+ MutableString(number, WireFormatLite::TYPE_STRING,
+ extension.descriptor);
if (!WireFormatLite::ReadString(input, value)) return false;
break;
}
case WireFormatLite::TYPE_BYTES: {
- string* value = extension->is_repeated ?
- AddString(number, WireFormatLite::TYPE_STRING) :
- MutableString(number, WireFormatLite::TYPE_STRING);
+ string* value = extension.is_repeated ?
+ AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) :
+ MutableString(number, WireFormatLite::TYPE_STRING,
+ extension.descriptor);
if (!WireFormatLite::ReadBytes(input, value)) return false;
break;
}
case WireFormatLite::TYPE_GROUP: {
- MessageLite* value = extension->is_repeated ?
+ MessageLite* value = extension.is_repeated ?
AddMessage(number, WireFormatLite::TYPE_GROUP,
- *extension->message_prototype) :
+ *extension.message_prototype, extension.descriptor) :
MutableMessage(number, WireFormatLite::TYPE_GROUP,
- *extension->message_prototype);
+ *extension.message_prototype, extension.descriptor);
if (!WireFormatLite::ReadGroup(number, input, value)) return false;
break;
}
case WireFormatLite::TYPE_MESSAGE: {
- MessageLite* value = extension->is_repeated ?
+ MessageLite* value = extension.is_repeated ?
AddMessage(number, WireFormatLite::TYPE_MESSAGE,
- *extension->message_prototype) :
+ *extension.message_prototype, extension.descriptor) :
MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
- *extension->message_prototype);
+ *extension.message_prototype, extension.descriptor);
if (!WireFormatLite::ReadMessage(input, value)) return false;
break;
}
@@ -837,7 +863,8 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
const MessageLite* containing_type) {
FieldSkipper skipper;
- return ParseField(tag, input, containing_type, &skipper);
+ GeneratedExtensionFinder finder(containing_type);
+ return ParseField(tag, input, &finder, &skipper);
}
// Defined in extension_set_heavy.cc.
@@ -846,7 +873,7 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
// UnknownFieldSet* unknown_fields)
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper) {
while (true) {
uint32 tag = input->ReadTag();
@@ -854,12 +881,12 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
case 0:
return true;
case WireFormatLite::kMessageSetItemStartTag:
- if (!ParseMessageSetItem(input, containing_type, field_skipper)) {
+ if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
return false;
}
break;
default:
- if (!ParseField(tag, input, containing_type, field_skipper)) {
+ if (!ParseField(tag, input, extension_finder, field_skipper)) {
return false;
}
break;
@@ -870,7 +897,8 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
const MessageLite* containing_type) {
FieldSkipper skipper;
- return ParseMessageSet(input, containing_type, &skipper);
+ GeneratedExtensionFinder finder(containing_type);
+ return ParseMessageSet(input, &finder, &skipper);
}
// Defined in extension_set_heavy.cc.
@@ -879,7 +907,7 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
// UnknownFieldSet* unknown_fields);
bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper) {
// TODO(kenton): It would be nice to share code between this and
// WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
@@ -919,7 +947,7 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
reinterpret_cast<const uint8*>(message_data.data()),
message_data.size());
if (!ParseField(fake_tag, &sub_input,
- containing_type, field_skipper)) {
+ extension_finder, field_skipper)) {
return false;
}
message_data.clear();
@@ -939,7 +967,7 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
} else {
// Already saw type_id, so we can parse this directly.
if (!ParseField(fake_tag, input,
- containing_type, field_skipper)) {
+ extension_finder, field_skipper)) {
return false;
}
}
@@ -969,26 +997,6 @@ void ExtensionSet::SerializeWithCachedSizes(
}
}
-uint8* ExtensionSet::SerializeWithCachedSizesToArray(
- int start_field_number, int end_field_number,
- uint8* target) const {
- // For now, just create an array output stream around the target and dispatch
- // to SerializeWithCachedSizes(). Give the array output stream kint32max
- // bytes; we will certainly write less than that. It is up to the caller to
- // ensure that the buffer has sufficient space.
- int written_bytes;
- {
- io::ArrayOutputStream array_stream(target, kint32max);
- io::CodedOutputStream output_stream(&array_stream);
- SerializeWithCachedSizes(start_field_number,
- end_field_number,
- &output_stream);
- written_bytes = output_stream.ByteCount();
- GOOGLE_DCHECK(!output_stream.HadError());
- }
- return target + written_bytes;
-}
-
void ExtensionSet::SerializeMessageSetWithCachedSizes(
io::CodedOutputStream* output) const {
map<int, Extension>::const_iterator iter;
@@ -997,23 +1005,6 @@ void ExtensionSet::SerializeMessageSetWithCachedSizes(
}
}
-uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
- uint8* target) const {
- // For now, just create an array output stream around the target and dispatch
- // to SerializeWithCachedSizes(). Give the array output stream kint32max
- // bytes; we will certainly write less than that. It is up to the caller to
- // ensure that the buffer has sufficient space.
- int written_bytes;
- {
- io::ArrayOutputStream array_stream(target, kint32max);
- io::CodedOutputStream output_stream(&array_stream);
- SerializeMessageSetWithCachedSizes(&output_stream);
- written_bytes = output_stream.ByteCount();
- GOOGLE_DCHECK(!output_stream.HadError());
- }
- return target + written_bytes;
-}
-
int ExtensionSet::ByteSize() const {
int total_size = 0;
@@ -1039,10 +1030,13 @@ int ExtensionSet::MessageSetByteSize() const {
// Defined in extension_set_heavy.cc.
// int ExtensionSet::SpaceUsedExcludingSelf() const
-bool ExtensionSet::MaybeNewExtension(int number, Extension** result) {
+bool ExtensionSet::MaybeNewExtension(int number,
+ const FieldDescriptor* descriptor,
+ Extension** result) {
pair<map<int, Extension>::iterator, bool> insert_result =
extensions_.insert(make_pair(number, Extension()));
*result = &insert_result.first->second;
+ (*result)->descriptor = descriptor;
return insert_result.second;
}
@@ -1206,20 +1200,20 @@ void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
if (is_cleared) return;
// Start group.
- output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
+ output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
// Write type ID.
- output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
- output->WriteVarint32(number);
-
+ WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
+ number,
+ output);
// Write message.
- output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
-
- output->WriteVarint32(message_value->GetCachedSize());
- message_value->SerializeWithCachedSizes(output);
+ WireFormatLite::WriteMessageMaybeToArray(
+ WireFormatLite::kMessageSetMessageNumber,
+ *message_value,
+ output);
// End group.
- output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
+ output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
}
int ExtensionSet::Extension::ByteSize(int number) const {
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index e5ac277e..b1a55338 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -53,6 +53,7 @@ namespace protobuf {
class FieldDescriptor; // descriptor.h
class DescriptorPool; // descriptor.h
class MessageLite; // message_lite.h
+ class Message; // message.h
class MessageFactory; // message.h
class UnknownFieldSet; // unknown_field_set.h
namespace io {
@@ -76,6 +77,84 @@ namespace internal {
// ExtensionSet::Extension small.
typedef uint8 FieldType;
+// A function which, given an integer value, returns true if the number
+// matches one of the defined values for the corresponding enum type. This
+// is used with RegisterEnumExtension, below.
+typedef bool EnumValidityFunc(int number);
+
+// Version of the above which takes an argument. This is needed to deal with
+// extensions that are not compiled in.
+typedef bool EnumValidityFuncWithArg(const void* arg, int number);
+
+// Information about a registered extension.
+struct ExtensionInfo {
+ inline ExtensionInfo() {}
+ inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
+ : type(type), is_repeated(is_repeated), is_packed(is_packed),
+ descriptor(NULL) {}
+
+ FieldType type;
+ bool is_repeated;
+ bool is_packed;
+
+ union {
+ struct {
+ EnumValidityFuncWithArg* enum_is_valid;
+ const void* enum_is_valid_arg;
+ };
+ const MessageLite* message_prototype;
+ };
+
+ // The descriptor for this extension, if one exists and is known. May be
+ // NULL. Must not be NULL if the descriptor for the extension does not
+ // live in the same pool as the descriptor for the containing type.
+ const FieldDescriptor* descriptor;
+};
+
+// Abstract interface for an object which looks up extension definitions. Used
+// when parsing.
+class LIBPROTOBUF_EXPORT ExtensionFinder {
+ public:
+ virtual ~ExtensionFinder();
+
+ // Find the extension with the given containing type and number.
+ virtual bool Find(int number, ExtensionInfo* output) = 0;
+};
+
+// Implementation of ExtensionFinder which finds extensions defined in .proto
+// files which have been compiled into the binary.
+class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder {
+ public:
+ GeneratedExtensionFinder(const MessageLite* containing_type)
+ : containing_type_(containing_type) {}
+ virtual ~GeneratedExtensionFinder() {}
+
+ // Returns true and fills in *output if found, otherwise returns false.
+ virtual bool Find(int number, ExtensionInfo* output);
+
+ private:
+ const MessageLite* containing_type_;
+};
+
+// Implementation of ExtensionFinder which finds extensions in a given
+// DescriptorPool, using the given MessageFactory to construct sub-objects.
+// This class is implemented in extension_set_heavy.cc.
+class LIBPROTOBUF_EXPORT DescriptorPoolExtensionFinder : public ExtensionFinder {
+ public:
+ DescriptorPoolExtensionFinder(const DescriptorPool* pool,
+ MessageFactory* factory,
+ const Descriptor* containing_type)
+ : pool_(pool), factory_(factory), containing_type_(containing_type) {}
+ virtual ~DescriptorPoolExtensionFinder() {}
+
+ virtual bool Find(int number, ExtensionInfo* output);
+
+ private:
+ const DescriptorPool* pool_;
+ MessageFactory* factory_;
+ const Descriptor* containing_type_;
+};
+
// This is an internal helper class intended for use within the protocol buffer
// library and generated classes. Clients should not use it directly. Instead,
// use the generated accessors such as GetExtension() of the class being
@@ -92,11 +171,6 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
ExtensionSet();
~ExtensionSet();
- // A function which, given an integer value, returns true if the number
- // matches one of the defined values for the corresponding enum type. This
- // is used with RegisterEnumExtension, below.
- typedef bool EnumValidityFunc(int number);
-
// These are called at startup by protocol-compiler-generated code to
// register known extensions. The registrations are used by ParseField()
// to look up extensions for parsed field numbers. Note that dynamic parsing
@@ -117,11 +191,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// =================================================================
// Add all fields which are currently present to the given vector. This
- // is useful to implement Reflection::ListFields(). The FieldDescriptors
- // are looked up by number from the given pool.
- //
- // TODO(kenton): Looking up each field by number is somewhat unfortunate.
- // Is there a better way?
+ // is useful to implement Reflection::ListFields().
void AppendToList(const Descriptor* containing_type,
const DescriptorPool* pool,
vector<const FieldDescriptor*>* output) const;
@@ -176,21 +246,25 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
const MessageLite& GetMessage(int number, const Descriptor* message_type,
MessageFactory* factory) const;
- void SetInt32 (int number, FieldType type, int32 value);
- void SetInt64 (int number, FieldType type, int64 value);
- void SetUInt32(int number, FieldType type, uint32 value);
- void SetUInt64(int number, FieldType type, uint64 value);
- void SetFloat (int number, FieldType type, float value);
- void SetDouble(int number, FieldType type, double value);
- void SetBool (int number, FieldType type, bool value);
- void SetEnum (int number, FieldType type, int value);
- void SetString(int number, FieldType type, const string& value);
- string * MutableString (int number, FieldType type);
- MessageLite* MutableMessage(int number, FieldType type,
- const MessageLite& prototype);
+ // |descriptor| may be NULL so long as it is known that the descriptor for
+ // the extension lives in the same pool as the descriptor for the containing
+ // type.
+#define desc const FieldDescriptor* descriptor // avoid line wrapping
+ void SetInt32 (int number, FieldType type, int32 value, desc);
+ void SetInt64 (int number, FieldType type, int64 value, desc);
+ void SetUInt32(int number, FieldType type, uint32 value, desc);
+ void SetUInt64(int number, FieldType type, uint64 value, desc);
+ void SetFloat (int number, FieldType type, float value, desc);
+ void SetDouble(int number, FieldType type, double value, desc);
+ void SetBool (int number, FieldType type, bool value, desc);
+ void SetEnum (int number, FieldType type, int value, desc);
+ void SetString(int number, FieldType type, const string& value, desc);
+ string * MutableString (int number, FieldType type, desc);
MessageLite* MutableMessage(int number, FieldType type,
- const Descriptor* message_type,
+ const MessageLite& prototype, desc);
+ MessageLite* MutableMessage(const FieldDescriptor* decsriptor,
MessageFactory* factory);
+#undef desc
// repeated fields -------------------------------------------------
@@ -217,21 +291,22 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
string * MutableRepeatedString (int number, int index);
MessageLite* MutableRepeatedMessage(int number, int index);
- void AddInt32 (int number, FieldType type, bool packed, int32 value);
- void AddInt64 (int number, FieldType type, bool packed, int64 value);
- void AddUInt32(int number, FieldType type, bool packed, uint32 value);
- void AddUInt64(int number, FieldType type, bool packed, uint64 value);
- void AddFloat (int number, FieldType type, bool packed, float value);
- void AddDouble(int number, FieldType type, bool packed, double value);
- void AddBool (int number, FieldType type, bool packed, bool value);
- void AddEnum (int number, FieldType type, bool packed, int value);
- void AddString(int number, FieldType type, const string& value);
- string * AddString (int number, FieldType type);
+#define desc const FieldDescriptor* descriptor // avoid line wrapping
+ void AddInt32 (int number, FieldType type, bool packed, int32 value, desc);
+ void AddInt64 (int number, FieldType type, bool packed, int64 value, desc);
+ void AddUInt32(int number, FieldType type, bool packed, uint32 value, desc);
+ void AddUInt64(int number, FieldType type, bool packed, uint64 value, desc);
+ void AddFloat (int number, FieldType type, bool packed, float value, desc);
+ void AddDouble(int number, FieldType type, bool packed, double value, desc);
+ void AddBool (int number, FieldType type, bool packed, bool value, desc);
+ void AddEnum (int number, FieldType type, bool packed, int value, desc);
+ void AddString(int number, FieldType type, const string& value, desc);
+ string * AddString (int number, FieldType type, desc);
MessageLite* AddMessage(int number, FieldType type,
- const MessageLite& prototype);
- MessageLite* AddMessage(int number, FieldType type,
- const Descriptor* message_type,
+ const MessageLite& prototype, desc);
+ MessageLite* AddMessage(const FieldDescriptor* descriptor,
MessageFactory* factory);
+#undef desc
void RemoveLast(int number);
void SwapElements(int number, int index1, int index2);
@@ -257,7 +332,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// methods of ExtensionSet, this only works for generated message types --
// it looks up extensions registered using RegisterExtension().
bool ParseField(uint32 tag, io::CodedInputStream* input,
- const MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper);
// Specific versions for lite or full messages (constructs the appropriate
@@ -265,13 +340,13 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
bool ParseField(uint32 tag, io::CodedInputStream* input,
const MessageLite* containing_type);
bool ParseField(uint32 tag, io::CodedInputStream* input,
- const MessageLite* containing_type,
+ const Message* containing_type,
UnknownFieldSet* unknown_fields);
// Parse an entire message in MessageSet format. Such messages have no
// fields, only extensions.
bool ParseMessageSet(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper);
// Specific versions for lite or full messages (constructs the appropriate
@@ -279,7 +354,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
bool ParseMessageSet(io::CodedInputStream* input,
const MessageLite* containing_type);
bool ParseMessageSet(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ const Message* containing_type,
UnknownFieldSet* unknown_fields);
// Write all extension fields with field numbers in the range
@@ -359,6 +434,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// For repeated types, this indicates if the [packed=true] option is set.
bool is_packed;
+ // The descriptor for this extension, if one exists and is known. May be
+ // NULL. Must not be NULL if the descriptor for the extension does not
+ // live in the same pool as the descriptor for the containing type.
+ const FieldDescriptor* descriptor;
+
// For packed fields, the size of the packed data is recorded here when
// ByteSize() is called then used during serialization.
// TODO(kenton): Use atomic<int> when C++ supports it.
@@ -368,9 +448,15 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
void SerializeFieldWithCachedSizes(
int number,
io::CodedOutputStream* output) const;
+ uint8* SerializeFieldWithCachedSizesToArray(
+ int number,
+ uint8* target) const;
void SerializeMessageSetItemWithCachedSizes(
int number,
io::CodedOutputStream* output) const;
+ uint8* SerializeMessageSetItemWithCachedSizesToArray(
+ int number,
+ uint8* target) const;
int ByteSize(int number) const;
int MessageSetItemByteSize(int number) const;
void Clear();
@@ -381,14 +467,16 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// Gets the extension with the given number, creating it if it does not
// already exist. Returns true if the extension did not already exist.
- bool MaybeNewExtension(int number, Extension** result);
+ bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
+ Extension** result);
// Parse a single MessageSet item -- called just after the item group start
// tag has been read.
bool ParseMessageSetItem(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper);
+
// Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This
// friendship should automatically extend to ExtensionSet::Extension, but
// unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this
@@ -412,16 +500,18 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// These are just for convenience...
inline void ExtensionSet::SetString(int number, FieldType type,
- const string& value) {
- MutableString(number, type)->assign(value);
+ const string& value,
+ const FieldDescriptor* descriptor) {
+ MutableString(number, type, descriptor)->assign(value);
}
inline void ExtensionSet::SetRepeatedString(int number, int index,
const string& value) {
MutableRepeatedString(number, index)->assign(value);
}
inline void ExtensionSet::AddString(int number, FieldType type,
- const string& value) {
- AddString(number, type)->assign(value);
+ const string& value,
+ const FieldDescriptor* descriptor) {
+ AddString(number, type, descriptor)->assign(value);
}
// ===================================================================
@@ -502,7 +592,7 @@ template<> inline TYPE PrimitiveTypeTraits<TYPE>::Get( \
} \
template<> inline void PrimitiveTypeTraits<TYPE>::Set( \
int number, FieldType field_type, TYPE value, ExtensionSet* set) { \
- set->Set##METHOD(number, field_type, value); \
+ set->Set##METHOD(number, field_type, value, NULL); \
} \
\
template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get( \
@@ -516,7 +606,7 @@ template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Set( \
template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
int number, FieldType field_type, bool is_packed, \
TYPE value, ExtensionSet* set) { \
- set->Add##METHOD(number, field_type, is_packed, value); \
+ set->Add##METHOD(number, field_type, is_packed, value, NULL); \
}
PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32)
@@ -544,11 +634,11 @@ class LIBPROTOBUF_EXPORT StringTypeTraits {
}
static inline void Set(int number, FieldType field_type,
const string& value, ExtensionSet* set) {
- set->SetString(number, field_type, value);
+ set->SetString(number, field_type, value, NULL);
}
static inline string* Mutable(int number, FieldType field_type,
ExtensionSet* set) {
- return set->MutableString(number, field_type);
+ return set->MutableString(number, field_type, NULL);
}
};
@@ -571,11 +661,11 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
static inline void Add(int number, FieldType field_type,
bool /*is_packed*/, const string& value,
ExtensionSet* set) {
- set->AddString(number, field_type, value);
+ set->AddString(number, field_type, value, NULL);
}
static inline string* Add(int number, FieldType field_type,
ExtensionSet* set) {
- return set->AddString(number, field_type);
+ return set->AddString(number, field_type, NULL);
}
};
@@ -596,7 +686,7 @@ class EnumTypeTraits {
static inline void Set(int number, FieldType field_type,
ConstType value, ExtensionSet* set) {
GOOGLE_DCHECK(IsValid(value));
- set->SetEnum(number, field_type, value);
+ set->SetEnum(number, field_type, value, NULL);
}
};
@@ -616,7 +706,7 @@ class RepeatedEnumTypeTraits {
static inline void Add(int number, FieldType field_type,
bool is_packed, ConstType value, ExtensionSet* set) {
GOOGLE_DCHECK(IsValid(value));
- set->AddEnum(number, field_type, is_packed, value);
+ set->AddEnum(number, field_type, is_packed, value, NULL);
}
};
@@ -640,7 +730,7 @@ class MessageTypeTraits {
static inline MutableType Mutable(int number, FieldType field_type,
ExtensionSet* set) {
return static_cast<Type*>(
- set->MutableMessage(number, field_type, Type::default_instance()));
+ set->MutableMessage(number, field_type, Type::default_instance(), NULL));
}
};
@@ -659,7 +749,7 @@ class RepeatedMessageTypeTraits {
static inline MutableType Add(int number, FieldType field_type,
ExtensionSet* set) {
return static_cast<Type*>(
- set->AddMessage(number, field_type, Type::default_instance()));
+ set->AddMessage(number, field_type, Type::default_instance(), NULL));
}
};
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 8555f6f8..426ec5f4 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -40,6 +40,7 @@
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
namespace google {
namespace protobuf {
@@ -58,12 +59,26 @@ void ExtensionSet::AppendToList(const Descriptor* containing_type,
}
if (has) {
- output->push_back(
- pool->FindExtensionByNumber(containing_type, iter->first));
+ // TODO(kenton): Looking up each field by number is somewhat unfortunate.
+ // Is there a better way? The problem is that descriptors are lazily-
+ // initialized, so they might not even be constructed until
+ // AppendToList() is called.
+
+ if (iter->second.descriptor == NULL) {
+ output->push_back(pool->FindExtensionByNumber(
+ containing_type, iter->first));
+ } else {
+ output->push_back(iter->second.descriptor);
+ }
}
}
}
+inline FieldDescriptor::Type real_type(FieldType type) {
+ GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
+ return static_cast<FieldDescriptor::Type>(type);
+}
+
inline FieldDescriptor::CppType cpp_type(FieldType type) {
return FieldDescriptor::TypeToCppType(
static_cast<FieldDescriptor::Type>(type));
@@ -88,16 +103,16 @@ const MessageLite& ExtensionSet::GetMessage(int number,
}
}
-MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
- const Descriptor* message_type,
+MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
MessageFactory* factory) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
- extension->type = type;
+ if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
+ extension->type = descriptor->type();
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
extension->is_repeated = false;
extension->is_packed = false;
- const MessageLite* prototype = factory->GetPrototype(message_type);
+ const MessageLite* prototype =
+ factory->GetPrototype(descriptor->message_type());
GOOGLE_CHECK(prototype != NULL);
extension->message_value = prototype->New();
} else {
@@ -107,12 +122,11 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
return extension->message_value;
}
-MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
- const Descriptor* message_type,
+MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
MessageFactory* factory) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
- extension->type = type;
+ if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
+ extension->type = descriptor->type();
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
extension->is_repeated = true;
extension->repeated_message_value =
@@ -128,7 +142,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
if (result == NULL) {
const MessageLite* prototype;
if (extension->repeated_message_value->size() == 0) {
- prototype = factory->GetPrototype(message_type);
+ prototype = factory->GetPrototype(descriptor->message_type());
GOOGLE_CHECK(prototype != NULL);
} else {
prototype = &extension->repeated_message_value->Get(0);
@@ -139,18 +153,64 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
return result;
}
+static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
+ return reinterpret_cast<const EnumDescriptor*>(arg)
+ ->FindValueByNumber(number) != NULL;
+}
+
+bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
+ const FieldDescriptor* extension =
+ pool_->FindExtensionByNumber(containing_type_, number);
+ if (extension == NULL) {
+ return false;
+ } else {
+ output->type = extension->type();
+ output->is_repeated = extension->is_repeated();
+ output->is_packed = extension->options().packed();
+ output->descriptor = extension;
+ if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ output->message_prototype =
+ factory_->GetPrototype(extension->message_type());
+ GOOGLE_CHECK(output->message_prototype != NULL)
+ << "Extension factory's GetPrototype() returned NULL for extension: "
+ << extension->full_name();
+ } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ output->enum_is_valid = ValidateEnumUsingDescriptor;
+ output->enum_is_valid_arg = extension->enum_type();
+ }
+
+ return true;
+ }
+}
+
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
- const MessageLite* containing_type,
+ const Message* containing_type,
UnknownFieldSet* unknown_fields) {
UnknownFieldSetFieldSkipper skipper(unknown_fields);
- return ParseField(tag, input, containing_type, &skipper);
+ if (input->GetExtensionPool() == NULL) {
+ GeneratedExtensionFinder finder(containing_type);
+ return ParseField(tag, input, &finder, &skipper);
+ } else {
+ DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
+ input->GetExtensionFactory(),
+ containing_type->GetDescriptor());
+ return ParseField(tag, input, &finder, &skipper);
+ }
}
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ const Message* containing_type,
UnknownFieldSet* unknown_fields) {
UnknownFieldSetFieldSkipper skipper(unknown_fields);
- return ParseMessageSet(input, containing_type, &skipper);
+ if (input->GetExtensionPool() == NULL) {
+ GeneratedExtensionFinder finder(containing_type);
+ return ParseMessageSet(input, &finder, &skipper);
+ } else {
+ DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
+ input->GetExtensionFactory(),
+ containing_type->GetDescriptor());
+ return ParseMessageSet(input, &finder, &skipper);
+ }
}
int ExtensionSet::SpaceUsedExcludingSelf() const {
@@ -175,7 +235,7 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
if (is_repeated) {
switch (cpp_type(type)) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
- case WireFormatLite::CPPTYPE_##UPPERCASE: \
+ case FieldDescriptor::CPPTYPE_##UPPERCASE: \
total_size += sizeof(*repeated_##LOWERCASE##_value) + \
repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
break
@@ -189,8 +249,9 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, enum);
HANDLE_TYPE( STRING, string);
+#undef HANDLE_TYPE
- case WireFormatLite::CPPTYPE_MESSAGE:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
// repeated_message_value is actually a RepeatedPtrField<MessageLite>,
// but MessageLite has no SpaceUsed(), so we must directly call
// RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
@@ -201,11 +262,11 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
}
} else {
switch (cpp_type(type)) {
- case WireFormatLite::CPPTYPE_STRING:
+ case FieldDescriptor::CPPTYPE_STRING:
total_size += sizeof(*string_value) +
StringSpaceUsedExcludingSelf(*string_value);
break;
- case WireFormatLite::CPPTYPE_MESSAGE:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
total_size += down_cast<Message*>(message_value)->SpaceUsed();
break;
default:
@@ -216,6 +277,162 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
return total_size;
}
+// The Serialize*ToArray methods are only needed in the heavy library, as
+// the lite library only generates SerializeWithCachedSizes.
+uint8* ExtensionSet::SerializeWithCachedSizesToArray(
+ int start_field_number, int end_field_number,
+ uint8* target) const {
+ map<int, Extension>::const_iterator iter;
+ for (iter = extensions_.lower_bound(start_field_number);
+ iter != extensions_.end() && iter->first < end_field_number;
+ ++iter) {
+ target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first,
+ target);
+ }
+ return target;
+}
+
+uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
+ uint8* target) const {
+ map<int, Extension>::const_iterator iter;
+ for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
+ target = iter->second.SerializeMessageSetItemWithCachedSizesToArray(
+ iter->first, target);
+ }
+ return target;
+}
+
+uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray(
+ int number, uint8* target) const {
+ if (is_repeated) {
+ if (is_packed) {
+ if (cached_size == 0) return target;
+
+ target = WireFormatLite::WriteTagToArray(number,
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
+ target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
+
+ switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
+ target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \
+ repeated_##LOWERCASE##_value->Get(i), target); \
+ } \
+ break
+
+ HANDLE_TYPE( INT32, Int32, int32);
+ HANDLE_TYPE( INT64, Int64, int64);
+ HANDLE_TYPE( UINT32, UInt32, uint32);
+ HANDLE_TYPE( UINT64, UInt64, uint64);
+ HANDLE_TYPE( SINT32, SInt32, int32);
+ HANDLE_TYPE( SINT64, SInt64, int64);
+ HANDLE_TYPE( FIXED32, Fixed32, uint32);
+ HANDLE_TYPE( FIXED64, Fixed64, uint64);
+ HANDLE_TYPE(SFIXED32, SFixed32, int32);
+ HANDLE_TYPE(SFIXED64, SFixed64, int64);
+ HANDLE_TYPE( FLOAT, Float, float);
+ HANDLE_TYPE( DOUBLE, Double, double);
+ HANDLE_TYPE( BOOL, Bool, bool);
+ HANDLE_TYPE( ENUM, Enum, enum);
+#undef HANDLE_TYPE
+
+ case WireFormatLite::TYPE_STRING:
+ case WireFormatLite::TYPE_BYTES:
+ case WireFormatLite::TYPE_GROUP:
+ case WireFormatLite::TYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
+ break;
+ }
+ } else {
+ switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
+ target = WireFormatLite::Write##CAMELCASE##ToArray(number, \
+ repeated_##LOWERCASE##_value->Get(i), target); \
+ } \
+ break
+
+ HANDLE_TYPE( INT32, Int32, int32);
+ HANDLE_TYPE( INT64, Int64, int64);
+ HANDLE_TYPE( UINT32, UInt32, uint32);
+ HANDLE_TYPE( UINT64, UInt64, uint64);
+ HANDLE_TYPE( SINT32, SInt32, int32);
+ HANDLE_TYPE( SINT64, SInt64, int64);
+ HANDLE_TYPE( FIXED32, Fixed32, uint32);
+ HANDLE_TYPE( FIXED64, Fixed64, uint64);
+ HANDLE_TYPE(SFIXED32, SFixed32, int32);
+ HANDLE_TYPE(SFIXED64, SFixed64, int64);
+ HANDLE_TYPE( FLOAT, Float, float);
+ HANDLE_TYPE( DOUBLE, Double, double);
+ HANDLE_TYPE( BOOL, Bool, bool);
+ HANDLE_TYPE( STRING, String, string);
+ HANDLE_TYPE( BYTES, Bytes, string);
+ HANDLE_TYPE( ENUM, Enum, enum);
+ HANDLE_TYPE( GROUP, Group, message);
+ HANDLE_TYPE( MESSAGE, Message, message);
+#undef HANDLE_TYPE
+ }
+ }
+ } else if (!is_cleared) {
+ switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ target = WireFormatLite::Write##CAMELCASE##ToArray( \
+ number, VALUE, target); \
+ break
+
+ HANDLE_TYPE( INT32, Int32, int32_value);
+ HANDLE_TYPE( INT64, Int64, int64_value);
+ HANDLE_TYPE( UINT32, UInt32, uint32_value);
+ HANDLE_TYPE( UINT64, UInt64, uint64_value);
+ HANDLE_TYPE( SINT32, SInt32, int32_value);
+ HANDLE_TYPE( SINT64, SInt64, int64_value);
+ HANDLE_TYPE( FIXED32, Fixed32, uint32_value);
+ HANDLE_TYPE( FIXED64, Fixed64, uint64_value);
+ HANDLE_TYPE(SFIXED32, SFixed32, int32_value);
+ HANDLE_TYPE(SFIXED64, SFixed64, int64_value);
+ HANDLE_TYPE( FLOAT, Float, float_value);
+ HANDLE_TYPE( DOUBLE, Double, double_value);
+ HANDLE_TYPE( BOOL, Bool, bool_value);
+ HANDLE_TYPE( STRING, String, *string_value);
+ HANDLE_TYPE( BYTES, Bytes, *string_value);
+ HANDLE_TYPE( ENUM, Enum, enum_value);
+ HANDLE_TYPE( GROUP, Group, *message_value);
+ HANDLE_TYPE( MESSAGE, Message, *message_value);
+#undef HANDLE_TYPE
+ }
+ }
+ return target;
+}
+
+uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray(
+ int number,
+ uint8* target) const {
+ if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+ // Not a valid MessageSet extension, but serialize it the normal way.
+ GOOGLE_LOG(WARNING) << "Invalid message set extension.";
+ return SerializeFieldWithCachedSizesToArray(number, target);
+ }
+
+ if (is_cleared) return target;
+
+ // Start group.
+ target = io::CodedOutputStream::WriteTagToArray(
+ WireFormatLite::kMessageSetItemStartTag, target);
+ // Write type ID.
+ target = WireFormatLite::WriteUInt32ToArray(
+ WireFormatLite::kMessageSetTypeIdNumber, number, target);
+ // Write message.
+ target = WireFormatLite::WriteMessageToArray(
+ WireFormatLite::kMessageSetMessageNumber, *message_value, target);
+ // End group.
+ target = io::CodedOutputStream::WriteTagToArray(
+ WireFormatLite::kMessageSetItemEndTag, target);
+ return target;
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 327aee02..000f846c 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -35,10 +35,15 @@
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/wire_format.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/stubs/stl_util-inl.h>
@@ -477,6 +482,160 @@ TEST(ExtensionSetTest, InvalidEnumDeath) {
#endif // GTEST_HAS_DEATH_TEST
+TEST(ExtensionSetTest, DynamicExtensions) {
+ // Test adding a dynamic extension to a compiled-in message object.
+
+ FileDescriptorProto dynamic_proto;
+ dynamic_proto.set_name("dynamic_extensions_test.proto");
+ dynamic_proto.add_dependency(
+ unittest::TestAllExtensions::descriptor()->file()->name());
+ dynamic_proto.set_package("dynamic_extensions");
+
+ // Copy the fields and nested types from TestDynamicExtensions into our new
+ // proto, converting the fields into extensions.
+ const Descriptor* template_descriptor =
+ unittest::TestDynamicExtensions::descriptor();
+ DescriptorProto template_descriptor_proto;
+ template_descriptor->CopyTo(&template_descriptor_proto);
+ dynamic_proto.mutable_message_type()->MergeFrom(
+ template_descriptor_proto.nested_type());
+ dynamic_proto.mutable_enum_type()->MergeFrom(
+ template_descriptor_proto.enum_type());
+ dynamic_proto.mutable_extension()->MergeFrom(
+ template_descriptor_proto.field());
+
+ // For each extension that we added...
+ for (int i = 0; i < dynamic_proto.extension_size(); i++) {
+ // Set its extendee to TestAllExtensions.
+ FieldDescriptorProto* extension = dynamic_proto.mutable_extension(i);
+ extension->set_extendee(
+ unittest::TestAllExtensions::descriptor()->full_name());
+
+ // If the field refers to one of the types nested in TestDynamicExtensions,
+ // make it refer to the type in our dynamic proto instead.
+ string prefix = "." + template_descriptor->full_name() + ".";
+ if (extension->has_type_name()) {
+ string* type_name = extension->mutable_type_name();
+ if (HasPrefixString(*type_name, prefix)) {
+ type_name->replace(0, prefix.size(), ".dynamic_extensions.");
+ }
+ }
+ }
+
+ // Now build the file, using the generated pool as an underlay.
+ DescriptorPool dynamic_pool(DescriptorPool::generated_pool());
+ const FileDescriptor* file = dynamic_pool.BuildFile(dynamic_proto);
+ ASSERT_TRUE(file != NULL);
+ DynamicMessageFactory dynamic_factory(&dynamic_pool);
+ dynamic_factory.SetDelegateToGeneratedFactory(true);
+
+ // Construct a message that we can parse with the extensions we defined.
+ // Since the extensions were based off of the fields of TestDynamicExtensions,
+ // we can use that message to create this test message.
+ string data;
+ {
+ unittest::TestDynamicExtensions message;
+ message.set_scalar_extension(123);
+ message.set_enum_extension(unittest::FOREIGN_BAR);
+ message.set_dynamic_enum_extension(
+ unittest::TestDynamicExtensions::DYNAMIC_BAZ);
+ message.mutable_message_extension()->set_c(456);
+ message.mutable_dynamic_message_extension()->set_dynamic_field(789);
+ message.add_repeated_extension("foo");
+ message.add_repeated_extension("bar");
+ message.add_packed_extension(12);
+ message.add_packed_extension(-34);
+ message.add_packed_extension(56);
+ message.add_packed_extension(-78);
+
+ // Also add some unknown fields.
+
+ // An unknown enum value (for a known field).
+ message.mutable_unknown_fields()->AddVarint(
+ unittest::TestDynamicExtensions::kDynamicEnumExtensionFieldNumber,
+ 12345);
+ // A regular unknown field.
+ message.mutable_unknown_fields()->AddLengthDelimited(54321, "unknown");
+
+ message.SerializeToString(&data);
+ }
+
+ // Now we can parse this using our dynamic extension definitions...
+ unittest::TestAllExtensions message;
+ {
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory);
+ ASSERT_TRUE(message.ParseFromCodedStream(&input));
+ ASSERT_TRUE(input.ConsumedEntireMessage());
+ }
+
+ // Can we print it?
+ EXPECT_EQ(
+ "[dynamic_extensions.scalar_extension]: 123\n"
+ "[dynamic_extensions.enum_extension]: FOREIGN_BAR\n"
+ "[dynamic_extensions.dynamic_enum_extension]: DYNAMIC_BAZ\n"
+ "[dynamic_extensions.message_extension] {\n"
+ " c: 456\n"
+ "}\n"
+ "[dynamic_extensions.dynamic_message_extension] {\n"
+ " dynamic_field: 789\n"
+ "}\n"
+ "[dynamic_extensions.repeated_extension]: \"foo\"\n"
+ "[dynamic_extensions.repeated_extension]: \"bar\"\n"
+ "[dynamic_extensions.packed_extension]: 12\n"
+ "[dynamic_extensions.packed_extension]: -34\n"
+ "[dynamic_extensions.packed_extension]: 56\n"
+ "[dynamic_extensions.packed_extension]: -78\n"
+ "2002: 12345\n"
+ "54321: \"unknown\"\n",
+ message.DebugString());
+
+ // Can we serialize it?
+ // (Don't use EXPECT_EQ because we don't want to dump raw binary data to the
+ // terminal on failure.)
+ EXPECT_TRUE(message.SerializeAsString() == data);
+
+ // What if we parse using the reflection-based parser?
+ {
+ unittest::TestAllExtensions message2;
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory);
+ ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message2));
+ ASSERT_TRUE(input.ConsumedEntireMessage());
+ EXPECT_EQ(message.DebugString(), message2.DebugString());
+ }
+
+ // Are the embedded generated types actually using the generated objects?
+ {
+ const FieldDescriptor* message_extension =
+ file->FindExtensionByName("message_extension");
+ ASSERT_TRUE(message_extension != NULL);
+ const Message& sub_message =
+ message.GetReflection()->GetMessage(message, message_extension);
+ const unittest::ForeignMessage* typed_sub_message =
+ dynamic_cast<const unittest::ForeignMessage*>(&sub_message);
+ ASSERT_TRUE(typed_sub_message != NULL);
+ EXPECT_EQ(456, typed_sub_message->c());
+ }
+
+ // What does GetMessage() return for the embedded dynamic type if it isn't
+ // present?
+ {
+ const FieldDescriptor* dynamic_message_extension =
+ file->FindExtensionByName("dynamic_message_extension");
+ ASSERT_TRUE(dynamic_message_extension != NULL);
+ const Message& parent = unittest::TestAllExtensions::default_instance();
+ const Message& sub_message =
+ parent.GetReflection()->GetMessage(parent, dynamic_message_extension,
+ &dynamic_factory);
+ const Message* prototype =
+ dynamic_factory.GetPrototype(dynamic_message_extension->message_type());
+ EXPECT_EQ(prototype, &sub_message);
+ }
+}
+
} // namespace
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index e04b93cc..0f065ff2 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -239,8 +239,13 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
- total_size += GetRaw<RepeatedPtrField<string> >(message, field)
- .SpaceUsedExcludingSelf();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ total_size += GetRaw<RepeatedPtrField<string> >(message, field)
+ .SpaceUsedExcludingSelf();
+ break;
+ }
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -265,18 +270,24 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
break;
case FieldDescriptor::CPPTYPE_STRING: {
- const string* ptr = GetField<const string*>(message, field);
-
- // Initially, the string points to the default value stored in
- // the prototype. Only count the string if it has been changed
- // from the default value.
- const string* default_ptr = DefaultRaw<const string*>(field);
-
- if (ptr != default_ptr) {
- // string fields are represented by just a pointer, so also
- // include sizeof(string) as well.
- total_size += sizeof(*ptr) + StringSpaceUsedExcludingSelf(*ptr);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING: {
+ const string* ptr = GetField<const string*>(message, field);
+
+ // Initially, the string points to the default value stored in
+ // the prototype. Only count the string if it has been changed
+ // from the default value.
+ const string* default_ptr = DefaultRaw<const string*>(field);
+
+ if (ptr != default_ptr) {
+ // string fields are represented by just a pointer, so also
+ // include sizeof(string) as well.
+ total_size += sizeof(*ptr) + StringSpaceUsedExcludingSelf(*ptr);
+ }
+ break;
}
+ }
break;
}
@@ -376,8 +387,13 @@ void GeneratedMessageReflection::Swap(
#undef SWAP_VALUES
case FieldDescriptor::CPPTYPE_STRING:
- std::swap(*MutableRaw<string*>(message1, field),
- *MutableRaw<string*>(message2, field));
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ std::swap(*MutableRaw<string*>(message1, field),
+ *MutableRaw<string*>(message2, field));
+ break;
+ }
break;
default:
@@ -473,15 +489,20 @@ void GeneratedMessageReflection::ClearField(
break;
case FieldDescriptor::CPPTYPE_STRING: {
- const string* default_ptr = DefaultRaw<const string*>(field);
- string** value = MutableRaw<string*>(message, field);
- if (*value != default_ptr) {
- if (field->has_default_value()) {
- (*value)->assign(field->default_value_string());
- } else {
- (*value)->clear();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ const string* default_ptr = DefaultRaw<const string*>(field);
+ string** value = MutableRaw<string*>(message, field);
+ if (*value != default_ptr) {
+ if (field->has_default_value()) {
+ (*value)->assign(field->default_value_string());
+ } else {
+ (*value)->clear();
+ }
}
- }
+ break;
+ }
break;
}
@@ -508,7 +529,12 @@ void GeneratedMessageReflection::ClearField(
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING: {
- MutableRaw<RepeatedPtrField<string> >(message, field)->Clear();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ MutableRaw<RepeatedPtrField<string> >(message, field)->Clear();
+ break;
+ }
break;
}
@@ -549,7 +575,12 @@ void GeneratedMessageReflection::RemoveLast(
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
- MutableRaw<RepeatedPtrField<string> >(message, field)->RemoveLast();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ MutableRaw<RepeatedPtrField<string> >(message, field)->RemoveLast();
+ break;
+ }
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -658,7 +689,7 @@ void GeneratedMessageReflection::ListFields(
USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \
if (field->is_extension()) { \
return MutableExtensionSet(message)->Set##TYPENAME( \
- field->number(), field->type(), value); \
+ field->number(), field->type(), value, field); \
} else { \
SetField<TYPE>(message, field, value); \
} \
@@ -694,7 +725,8 @@ void GeneratedMessageReflection::ListFields(
USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \
if (field->is_extension()) { \
MutableExtensionSet(message)->Add##TYPENAME( \
- field->number(), field->type(), field->options().packed(), value); \
+ field->number(), field->type(), field->options().packed(), value, \
+ field); \
} else { \
AddField<TYPE>(message, field, value); \
} \
@@ -718,7 +750,14 @@ string GeneratedMessageReflection::GetString(
return GetExtensionSet(message).GetString(field->number(),
field->default_value_string());
} else {
- return *GetField<const string*>(message, field);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return *GetField<const string*>(message, field);
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return kEmptyString; // Make compiler happy.
}
}
@@ -730,7 +769,14 @@ const string& GeneratedMessageReflection::GetStringReference(
return GetExtensionSet(message).GetString(field->number(),
field->default_value_string());
} else {
- return *GetField<const string*>(message, field);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return *GetField<const string*>(message, field);
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return kEmptyString; // Make compiler happy.
}
}
@@ -741,13 +787,19 @@ void GeneratedMessageReflection::SetString(
USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
if (field->is_extension()) {
return MutableExtensionSet(message)->SetString(field->number(),
- field->type(), value);
+ field->type(), value, field);
} else {
- string** ptr = MutableField<string*>(message, field);
- if (*ptr == DefaultRaw<const string*>(field)) {
- *ptr = new string(value);
- } else {
- (*ptr)->assign(value);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING: {
+ string** ptr = MutableField<string*>(message, field);
+ if (*ptr == DefaultRaw<const string*>(field)) {
+ *ptr = new string(value);
+ } else {
+ (*ptr)->assign(value);
+ }
+ break;
+ }
}
}
}
@@ -759,7 +811,14 @@ string GeneratedMessageReflection::GetRepeatedString(
if (field->is_extension()) {
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
} else {
- return GetRepeatedPtrField<string>(message, field, index);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return GetRepeatedPtrField<string>(message, field, index);
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return kEmptyString; // Make compiler happy.
}
}
@@ -770,7 +829,14 @@ const string& GeneratedMessageReflection::GetRepeatedStringReference(
if (field->is_extension()) {
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
} else {
- return GetRepeatedPtrField<string>(message, field, index);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return GetRepeatedPtrField<string>(message, field, index);
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return kEmptyString; // Make compiler happy.
}
}
@@ -783,7 +849,12 @@ void GeneratedMessageReflection::SetRepeatedString(
MutableExtensionSet(message)->SetRepeatedString(
field->number(), index, value);
} else {
- *MutableRepeatedField<string>(message, field, index) = value;
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ *MutableRepeatedField<string>(message, field, index) = value;
+ break;
+ }
}
}
@@ -794,9 +865,14 @@ void GeneratedMessageReflection::AddString(
USAGE_CHECK_ALL(AddString, REPEATED, STRING);
if (field->is_extension()) {
MutableExtensionSet(message)->AddString(field->number(),
- field->type(), value);
+ field->type(), value, field);
} else {
- *AddField<string>(message, field) = value;
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ *AddField<string>(message, field) = value;
+ break;
+ }
}
}
@@ -828,7 +904,7 @@ void GeneratedMessageReflection::SetEnum(
if (field->is_extension()) {
MutableExtensionSet(message)->SetEnum(field->number(), field->type(),
- value->number());
+ value->number(), field);
} else {
SetField<int>(message, field, value->number());
}
@@ -874,7 +950,7 @@ void GeneratedMessageReflection::AddEnum(
if (field->is_extension()) {
MutableExtensionSet(message)->AddEnum(field->number(), field->type(),
field->options().packed(),
- value->number());
+ value->number(), field);
} else {
AddField<int>(message, field, value->number());
}
@@ -883,14 +959,15 @@ void GeneratedMessageReflection::AddEnum(
// -------------------------------------------------------------------
const Message& GeneratedMessageReflection::GetMessage(
- const Message& message, const FieldDescriptor* field) const {
+ const Message& message, const FieldDescriptor* field,
+ MessageFactory* factory) const {
USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
if (field->is_extension()) {
return static_cast<const Message&>(
- GetExtensionSet(message).GetMessage(field->number(),
- field->message_type(),
- message_factory_));
+ GetExtensionSet(message).GetMessage(
+ field->number(), field->message_type(),
+ factory == NULL ? message_factory_ : factory));
} else {
const Message* result = GetRaw<const Message*>(message, field);
if (result == NULL) {
@@ -901,15 +978,14 @@ const Message& GeneratedMessageReflection::GetMessage(
}
Message* GeneratedMessageReflection::MutableMessage(
- Message* message, const FieldDescriptor* field) const {
+ Message* message, const FieldDescriptor* field,
+ MessageFactory* factory) const {
USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
if (field->is_extension()) {
return static_cast<Message*>(
- MutableExtensionSet(message)->MutableMessage(field->number(),
- field->type(),
- field->message_type(),
- message_factory_));
+ MutableExtensionSet(message)->MutableMessage(field,
+ factory == NULL ? message_factory_ : factory));
} else {
Message** result = MutableField<Message*>(message, field);
if (*result == NULL) {
@@ -948,15 +1024,15 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage(
}
Message* GeneratedMessageReflection::AddMessage(
- Message* message, const FieldDescriptor* field) const {
+ Message* message, const FieldDescriptor* field,
+ MessageFactory* factory) const {
USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
+ if (factory == NULL) factory = message_factory_;
+
if (field->is_extension()) {
return static_cast<Message*>(
- MutableExtensionSet(message)->AddMessage(field->number(),
- field->type(),
- field->message_type(),
- message_factory_));
+ MutableExtensionSet(message)->AddMessage(field, factory));
} else {
// We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
// know how to allocate one.
@@ -967,7 +1043,7 @@ Message* GeneratedMessageReflection::AddMessage(
// We must allocate a new object.
const Message* prototype;
if (repeated->size() == 0) {
- prototype = message_factory_->GetPrototype(field->message_type());
+ prototype = factory->GetPrototype(field->message_type());
} else {
prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
}
@@ -1110,7 +1186,7 @@ inline Type* GeneratedMessageReflection::MutableField(
}
template <typename Type>
-inline Type GeneratedMessageReflection::GetRepeatedField(
+inline const Type& GeneratedMessageReflection::GetRepeatedField(
const Message& message, const FieldDescriptor* field, int index) const {
return GetRaw<RepeatedField<Type> >(message, field).Get(index);
}
@@ -1138,7 +1214,7 @@ inline Type* GeneratedMessageReflection::MutableRepeatedField(
template <typename Type>
inline void GeneratedMessageReflection::AddField(
- Message* message, const FieldDescriptor* field, Type value) const {
+ Message* message, const FieldDescriptor* field, const Type& value) const {
MutableRaw<RepeatedField<Type> >(message, field)->Add(value);
}
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index d0b5b43b..b545fa1a 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -169,7 +169,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const EnumValueDescriptor* GetEnum(const Message& message,
const FieldDescriptor* field) const;
const Message& GetMessage(const Message& message,
- const FieldDescriptor* field) const;
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const;
void SetInt32 (Message* message,
const FieldDescriptor* field, int32 value) const;
@@ -190,7 +191,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const string& value) const;
void SetEnum (Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const;
- Message* MutableMessage(Message* message, const FieldDescriptor* field) const;
+ Message* MutableMessage(Message* message, const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const;
int32 GetRepeatedInt32 (const Message& message,
const FieldDescriptor* field, int index) const;
@@ -262,7 +264,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
void AddEnum(Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const;
- Message* AddMessage(Message* message, const FieldDescriptor* field) const;
+ Message* AddMessage(Message* message, const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const;
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
@@ -314,9 +317,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
inline Type* MutableField(Message* message,
const FieldDescriptor* field) const;
template <typename Type>
- inline Type GetRepeatedField(const Message& message,
- const FieldDescriptor* field,
- int index) const;
+ inline const Type& GetRepeatedField(const Message& message,
+ const FieldDescriptor* field,
+ int index) const;
template <typename Type>
inline const Type& GetRepeatedPtrField(const Message& message,
const FieldDescriptor* field,
@@ -331,7 +334,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int index) const;
template <typename Type>
inline void AddField(Message* message,
- const FieldDescriptor* field, Type value) const;
+ const FieldDescriptor* field, const Type& value) const;
template <typename Type>
inline Type* AddField(Message* message,
const FieldDescriptor* field) const;
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 9470bb08..7ac015d0 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -34,10 +34,19 @@
#include <google/protobuf/generated_message_util.h>
+#include <limits>
+
namespace google {
namespace protobuf {
namespace internal {
+double Infinity() {
+ return std::numeric_limits<double>::infinity();
+}
+double NaN() {
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 80dd028e..f306a2f1 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -43,21 +43,33 @@
namespace google {
namespace protobuf {
+ namespace io {
+ class CodedInputStream; // coded_stream.h
+ }
+}
+
+namespace protobuf {
namespace internal {
// Annotation for the compiler to emit a deprecation message if a field marked
-// with option 'deprecated=true' is used in the code.
+// with option 'deprecated=true' is used in the code, or for other things in
+// generated code which are deprecated.
//
// For internal use in the pb.cc files, deprecation warnings are suppressed
// there.
#undef DEPRECATED_PROTOBUF_FIELD
#if !defined(INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION)
-# define DEPRECATED_PROTOBUF_FIELD GOOGLE_ATTRIBUTE_DEPRECATED
+# define PROTOBUF_DEPRECATED GOOGLE_ATTRIBUTE_DEPRECATED
#else
-# define DEPRECATED_PROTOBUF_FIELD
+# define PROTOBUF_DEPRECATED
#endif
+// Constants for special floating point values.
+double Infinity();
+double NaN();
+
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index e17a4775..6a91a13d 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -38,9 +38,9 @@
// will not cross the end of the buffer, since we can avoid a lot
// of branching in this case.
-#include <stack>
+#include <google/protobuf/io/coded_stream_inl.h>
+#include <algorithm>
#include <limits.h>
-#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stl_util-inl.h>
@@ -52,11 +52,6 @@ namespace io {
namespace {
-static const int kDefaultTotalBytesLimit = 64 << 20; // 64MB
-
-static const int kDefaultTotalBytesWarningThreshold = 32 << 20; // 32MB
-static const int kDefaultRecursionLimit = 64;
-
static const int kMaxVarintBytes = 10;
static const int kMaxVarint32Bytes = 5;
@@ -65,72 +60,28 @@ static const int kMaxVarint32Bytes = 5;
// CodedInputStream ==================================================
-CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
- : input_(input),
- buffer_(NULL),
- buffer_size_(0),
- total_bytes_read_(0),
- overflow_bytes_(0),
- last_tag_(0),
- legitimate_message_end_(false),
- aliasing_enabled_(false),
- current_limit_(INT_MAX),
- buffer_size_after_limit_(0),
- total_bytes_limit_(kDefaultTotalBytesLimit),
- total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
- recursion_depth_(0),
- recursion_limit_(kDefaultRecursionLimit) {
- // Eagerly Refresh() so buffer space is immediately available.
- Refresh();
-}
-
-CodedInputStream::CodedInputStream(const uint8* buffer, int size)
- : input_(NULL),
- buffer_(buffer),
- buffer_size_(size),
- total_bytes_read_(size),
- overflow_bytes_(0),
- last_tag_(0),
- legitimate_message_end_(false),
- aliasing_enabled_(false),
- current_limit_(size),
- buffer_size_after_limit_(0),
- total_bytes_limit_(kDefaultTotalBytesLimit),
- total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
- recursion_depth_(0),
- recursion_limit_(kDefaultRecursionLimit) {
- // Note that setting current_limit_ == size is important to prevent some
- // code paths from trying to access input_ and segfaulting.
-}
-
-CodedInputStream::~CodedInputStream() {
- if (input_ != NULL) {
- BackUpInputToCurrentPosition();
- }
-}
-
void CodedInputStream::BackUpInputToCurrentPosition() {
- int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_;
+ int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
if (backup_bytes > 0) {
input_->BackUp(backup_bytes);
// total_bytes_read_ doesn't include overflow_bytes_.
- total_bytes_read_ -= buffer_size_ + buffer_size_after_limit_;
- buffer_size_ = 0;
+ total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
+ buffer_end_ = buffer_;
buffer_size_after_limit_ = 0;
overflow_bytes_ = 0;
}
}
inline void CodedInputStream::RecomputeBufferLimits() {
- buffer_size_ += buffer_size_after_limit_;
+ buffer_end_ += buffer_size_after_limit_;
int closest_limit = min(current_limit_, total_bytes_limit_);
if (closest_limit < total_bytes_read_) {
// The limit position is in the current buffer. We must adjust
// the buffer size accordingly.
buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
- buffer_size_ -= buffer_size_after_limit_;
+ buffer_end_ -= buffer_size_after_limit_;
} else {
buffer_size_after_limit_ = 0;
}
@@ -139,7 +90,7 @@ inline void CodedInputStream::RecomputeBufferLimits() {
CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
// Current position relative to the beginning of the stream.
int current_position = total_bytes_read_ -
- (buffer_size_ + buffer_size_after_limit_);
+ (BufferSize() + buffer_size_after_limit_);
Limit old_limit = current_limit_;
@@ -176,7 +127,7 @@ void CodedInputStream::PopLimit(Limit limit) {
int CodedInputStream::BytesUntilLimit() {
if (current_limit_ == INT_MAX) return -1;
int current_position = total_bytes_read_ -
- (buffer_size_ + buffer_size_after_limit_);
+ (BufferSize() + buffer_size_after_limit_);
return current_limit_ - current_position;
}
@@ -186,7 +137,7 @@ void CodedInputStream::SetTotalBytesLimit(
// Make sure the limit isn't already past, since this could confuse other
// code.
int current_position = total_bytes_read_ -
- (buffer_size_ + buffer_size_after_limit_);
+ (BufferSize() + buffer_size_after_limit_);
total_bytes_limit_ = max(current_position, total_bytes_limit);
total_bytes_warning_threshold_ = warning_threshold;
RecomputeBufferLimits();
@@ -203,7 +154,9 @@ void CodedInputStream::PrintTotalBytesLimitError() {
bool CodedInputStream::Skip(int count) {
if (count < 0) return false; // security: count is often user-supplied
- if (count <= buffer_size_) {
+ const int original_buffer_size = BufferSize();
+
+ if (count <= original_buffer_size) {
// Just skipping within the current buffer. Easy.
Advance(count);
return true;
@@ -211,13 +164,13 @@ bool CodedInputStream::Skip(int count) {
if (buffer_size_after_limit_ > 0) {
// We hit a limit inside this buffer. Advance to the limit and fail.
- Advance(buffer_size_);
+ Advance(original_buffer_size);
return false;
}
- count -= buffer_size_;
+ count -= original_buffer_size;
buffer_ = NULL;
- buffer_size_ = 0;
+ buffer_end_ = buffer_;
// Make sure this skip doesn't try to skip past the current limit.
int closest_limit = min(current_limit_, total_bytes_limit_);
@@ -236,20 +189,21 @@ bool CodedInputStream::Skip(int count) {
}
bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
- if (buffer_size_ == 0 && !Refresh()) return false;
+ if (BufferSize() == 0 && !Refresh()) return false;
*data = buffer_;
- *size = buffer_size_;
+ *size = BufferSize();
return true;
}
bool CodedInputStream::ReadRaw(void* buffer, int size) {
- while (buffer_size_ < size) {
+ int current_buffer_size;
+ while ((current_buffer_size = BufferSize()) < size) {
// Reading past end of buffer. Copy what we have, then refresh.
- memcpy(buffer, buffer_, buffer_size_);
- buffer = reinterpret_cast<uint8*>(buffer) + buffer_size_;
- size -= buffer_size_;
- Advance(buffer_size_);
+ memcpy(buffer, buffer_, current_buffer_size);
+ buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
+ size -= current_buffer_size;
+ Advance(current_buffer_size);
if (!Refresh()) return false;
}
@@ -261,27 +215,25 @@ bool CodedInputStream::ReadRaw(void* buffer, int size) {
bool CodedInputStream::ReadString(string* buffer, int size) {
if (size < 0) return false; // security: size is often user-supplied
+ return InternalReadStringInline(buffer, size);
+}
+bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
if (!buffer->empty()) {
buffer->clear();
}
- if (size < buffer_size_) {
- STLStringResizeUninitialized(buffer, size);
- memcpy((uint8*)buffer->data(), buffer_, size);
- Advance(size);
- return true;
- }
-
- while (buffer_size_ < size) {
+ int current_buffer_size;
+ while ((current_buffer_size = BufferSize()) < size) {
// Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
- if (buffer_size_ != 0) {
+ if (current_buffer_size != 0) {
// Note: string1.append(string2) is O(string2.size()) (as opposed to
// O(string1.size() + string2.size()), which would be bad).
- buffer->append(reinterpret_cast<const char*>(buffer_), buffer_size_);
+ buffer->append(reinterpret_cast<const char*>(buffer_),
+ current_buffer_size);
}
- size -= buffer_size_;
- Advance(buffer_size_);
+ size -= current_buffer_size;
+ Advance(current_buffer_size);
if (!Refresh()) return false;
}
@@ -292,11 +244,11 @@ bool CodedInputStream::ReadString(string* buffer, int size) {
}
-bool CodedInputStream::ReadLittleEndian32(uint32* value) {
+bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
uint8 bytes[sizeof(*value)];
const uint8* ptr;
- if (buffer_size_ >= sizeof(*value)) {
+ if (BufferSize() >= sizeof(*value)) {
// Fast path: Enough bytes in the buffer to read directly.
ptr = buffer_;
Advance(sizeof(*value));
@@ -305,19 +257,15 @@ bool CodedInputStream::ReadLittleEndian32(uint32* value) {
if (!ReadRaw(bytes, sizeof(*value))) return false;
ptr = bytes;
}
-
- *value = (static_cast<uint32>(ptr[0]) ) |
- (static_cast<uint32>(ptr[1]) << 8) |
- (static_cast<uint32>(ptr[2]) << 16) |
- (static_cast<uint32>(ptr[3]) << 24);
+ ReadLittleEndian32FromArray(ptr, value);
return true;
}
-bool CodedInputStream::ReadLittleEndian64(uint64* value) {
+bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
uint8 bytes[sizeof(*value)];
const uint8* ptr;
- if (buffer_size_ >= sizeof(*value)) {
+ if (BufferSize() >= sizeof(*value)) {
// Fast path: Enough bytes in the buffer to read directly.
ptr = buffer_;
Advance(sizeof(*value));
@@ -326,99 +274,152 @@ bool CodedInputStream::ReadLittleEndian64(uint64* value) {
if (!ReadRaw(bytes, sizeof(*value))) return false;
ptr = bytes;
}
+ ReadLittleEndian64FromArray(ptr, value);
+ return true;
+}
+
+namespace {
+
+inline const uint8* ReadVarint32FromArray(
+ const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
+ // Fast path: We have enough bytes left in the buffer to guarantee that
+ // this read won't cross the end, so we can skip the checks.
+ const uint8* ptr = buffer;
+ uint32 b;
+ uint32 result;
+
+ b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done;
+
+ // If the input is larger than 32 bits, we still need to read it all
+ // and discard the high-order bits.
+ for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
+ b = *(ptr++); if (!(b & 0x80)) goto done;
+ }
+
+ // We have overrun the maximum size of a varint (10 bytes). Assume
+ // the data is corrupt.
+ return NULL;
+
+ done:
+ *value = result;
+ return ptr;
+}
+
+} // namespace
- uint32 part0 = (static_cast<uint32>(ptr[0]) ) |
- (static_cast<uint32>(ptr[1]) << 8) |
- (static_cast<uint32>(ptr[2]) << 16) |
- (static_cast<uint32>(ptr[3]) << 24);
- uint32 part1 = (static_cast<uint32>(ptr[4]) ) |
- (static_cast<uint32>(ptr[5]) << 8) |
- (static_cast<uint32>(ptr[6]) << 16) |
- (static_cast<uint32>(ptr[7]) << 24);
- *value = static_cast<uint64>(part0) |
- (static_cast<uint64>(part1) << 32);
+bool CodedInputStream::ReadVarint32Slow(uint32* value) {
+ uint64 result;
+ // Directly invoke ReadVarint64Fallback, since we already tried to optimize
+ // for one-byte varints.
+ if (!ReadVarint64Fallback(&result)) return false;
+ *value = (uint32)result;
return true;
}
bool CodedInputStream::ReadVarint32Fallback(uint32* value) {
- if (buffer_size_ >= kMaxVarintBytes ||
+ if (BufferSize() >= kMaxVarintBytes ||
// Optimization: If the varint ends at exactly the end of the buffer,
// we can detect that and still use the fast path.
- (buffer_size_ != 0 && !(buffer_[buffer_size_-1] & 0x80))) {
- // Fast path: We have enough bytes left in the buffer to guarantee that
- // this read won't cross the end, so we can skip the checks.
- const uint8* ptr = buffer_;
- uint32 b;
- uint32 result;
-
- b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done;
- b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
- b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
- b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
- b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done;
-
- // If the input is larger than 32 bits, we still need to read it all
- // and discard the high-order bits.
- for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
- b = *(ptr++); if (!(b & 0x80)) goto done;
- }
-
- // We have overrun the maximum size of a varint (10 bytes). Assume
- // the data is corrupt.
- return false;
-
- done:
- Advance(ptr - buffer_);
- *value = result;
+ (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
+ const uint8* end = ReadVarint32FromArray(buffer_, value);
+ if (end == NULL) return false;
+ buffer_ = end;
return true;
-
} else {
- // Optimization: If we're at a limit, detect that quickly. (This is
- // common when reading tags.)
- while (buffer_size_ == 0) {
- // Detect cases where we definitely hit a byte limit without calling
- // Refresh().
- if (// If we hit a limit, buffer_size_after_limit_ will be non-zero.
- buffer_size_after_limit_ > 0 &&
- // Make sure that the limit we hit is not total_bytes_limit_, since
- // in that case we still need to call Refresh() so that it prints an
- // error.
- total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
- // We hit a byte limit.
- legitimate_message_end_ = true;
- return false;
- }
+ // Really slow case: we will incur the cost of an extra function call here,
+ // but moving this out of line reduces the size of this function, which
+ // improves the common case. In micro benchmarks, this is worth about 10-15%
+ return ReadVarint32Slow(value);
+ }
+}
- // Call refresh.
- if (!Refresh()) {
- // Refresh failed. Make sure that it failed due to EOF, not because
- // we hit total_bytes_limit_, which, unlike normal limits, is not a
- // valid place to end a message.
- int current_position = total_bytes_read_ - buffer_size_after_limit_;
- if (current_position >= total_bytes_limit_) {
- // Hit total_bytes_limit_. But if we also hit the normal limit,
- // we're still OK.
- legitimate_message_end_ = current_limit_ == total_bytes_limit_;
- } else {
- legitimate_message_end_ = true;
- }
- return false;
+uint32 CodedInputStream::ReadTagSlow() {
+ if (buffer_ == buffer_end_) {
+ // Call refresh.
+ if (!Refresh()) {
+ // Refresh failed. Make sure that it failed due to EOF, not because
+ // we hit total_bytes_limit_, which, unlike normal limits, is not a
+ // valid place to end a message.
+ int current_position = total_bytes_read_ - buffer_size_after_limit_;
+ if (current_position >= total_bytes_limit_) {
+ // Hit total_bytes_limit_. But if we also hit the normal limit,
+ // we're still OK.
+ legitimate_message_end_ = current_limit_ == total_bytes_limit_;
+ } else {
+ legitimate_message_end_ = true;
}
+ return 0;
}
+ }
- // Slow path: Just do a 64-bit read.
- uint64 result;
- if (!ReadVarint64(&result)) return false;
- *value = (uint32)result;
- return true;
+ // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
+ // again, since we have now refreshed the buffer.
+ uint64 result;
+ if (!ReadVarint64(&result)) return 0;
+ return static_cast<uint32>(result);
+}
+
+uint32 CodedInputStream::ReadTagFallback() {
+ if (BufferSize() >= kMaxVarintBytes ||
+ // Optimization: If the varint ends at exactly the end of the buffer,
+ // we can detect that and still use the fast path.
+ (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
+ uint32 tag;
+ const uint8* end = ReadVarint32FromArray(buffer_, &tag);
+ if (end == NULL) {
+ return 0;
+ }
+ buffer_ = end;
+ return tag;
+ } else {
+ // We are commonly at a limit when attempting to read tags. Try to quickly
+ // detect this case without making another function call.
+ if (buffer_ == buffer_end_ && buffer_size_after_limit_ > 0 &&
+ // Make sure that the limit we hit is not total_bytes_limit_, since
+ // in that case we still need to call Refresh() so that it prints an
+ // error.
+ total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
+ // We hit a byte limit.
+ legitimate_message_end_ = true;
+ return 0;
+ }
+ return ReadTagSlow();
}
}
-bool CodedInputStream::ReadVarint64(uint64* value) {
- if (buffer_size_ >= kMaxVarintBytes ||
+bool CodedInputStream::ReadVarint64Slow(uint64* value) {
+ // Slow path: This read might cross the end of the buffer, so we
+ // need to check and refresh the buffer if and when it does.
+
+ uint64 result = 0;
+ int count = 0;
+ uint32 b;
+
+ do {
+ if (count == kMaxVarintBytes) return false;
+ while (buffer_ == buffer_end_) {
+ if (!Refresh()) return false;
+ }
+ b = *buffer_;
+ result |= static_cast<uint64>(b & 0x7F) << (7 * count);
+ Advance(1);
+ ++count;
+ } while (b & 0x80);
+
+ *value = result;
+ return true;
+}
+
+bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
+ if (BufferSize() >= kMaxVarintBytes ||
// Optimization: If the varint ends at exactly the end of the buffer,
// we can detect that and still use the fast path.
- (buffer_size_ != 0 && !(buffer_[buffer_size_-1] & 0x80))) {
+ (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
// Fast path: We have enough bytes left in the buffer to guarantee that
// this read won't cross the end, so we can skip the checks.
@@ -442,7 +443,7 @@ bool CodedInputStream::ReadVarint64(uint64* value) {
// We have overrun the maximum size of a varint (10 bytes). The data
// must be corrupt.
- return false;
+ return NULL;
done:
Advance(ptr - buffer_);
@@ -450,33 +451,13 @@ bool CodedInputStream::ReadVarint64(uint64* value) {
(static_cast<uint64>(part1) << 28) |
(static_cast<uint64>(part2) << 56);
return true;
-
} else {
- // Slow path: This read might cross the end of the buffer, so we
- // need to check and refresh the buffer if and when it does.
-
- uint64 result = 0;
- int count = 0;
- uint32 b;
-
- do {
- if (count == kMaxVarintBytes) return false;
- while (buffer_size_ == 0) {
- if (!Refresh()) return false;
- }
- b = *buffer_;
- result |= static_cast<uint64>(b & 0x7F) << (7 * count);
- Advance(1);
- ++count;
- } while(b & 0x80);
-
- *value = result;
- return true;
+ return ReadVarint64Slow(value);
}
}
bool CodedInputStream::Refresh() {
- GOOGLE_DCHECK_EQ(buffer_size_, 0);
+ GOOGLE_DCHECK_EQ(0, BufferSize());
if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
total_bytes_read_ == current_limit_) {
@@ -507,25 +488,27 @@ bool CodedInputStream::Refresh() {
}
const void* void_buffer;
- if (input_->Next(&void_buffer, &buffer_size_)) {
+ int buffer_size;
+ if (input_->Next(&void_buffer, &buffer_size)) {
buffer_ = reinterpret_cast<const uint8*>(void_buffer);
- GOOGLE_CHECK_GE(buffer_size_, 0);
+ buffer_end_ = buffer_ + buffer_size;
+ GOOGLE_CHECK_GE(buffer_size, 0);
- if (total_bytes_read_ <= INT_MAX - buffer_size_) {
- total_bytes_read_ += buffer_size_;
+ if (total_bytes_read_ <= INT_MAX - buffer_size) {
+ total_bytes_read_ += buffer_size;
} else {
- // Overflow. Reset buffer_size_ to not include the bytes beyond INT_MAX.
+ // Overflow. Reset buffer_end_ to not include the bytes beyond INT_MAX.
// We can't get that far anyway, because total_bytes_limit_ is guaranteed
// to be less than it. We need to keep track of the number of bytes
// we discarded, though, so that we can call input_->BackUp() to back
// up over them on destruction.
// The following line is equivalent to:
- // overflow_bytes_ = total_bytes_read_ + buffer_size_ - INT_MAX;
+ // overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
// except that it avoids overflows. Signed integer overflow has
// undefined results according to the C standard.
- overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size_);
- buffer_size_ -= overflow_bytes_;
+ overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
+ buffer_end_ -= overflow_bytes_;
total_bytes_read_ = INT_MAX;
}
@@ -533,7 +516,7 @@ bool CodedInputStream::Refresh() {
return true;
} else {
buffer_ = NULL;
- buffer_size_ = 0;
+ buffer_end_ = NULL;
return false;
}
}
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index fa023f35..dcbb0d45 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -114,10 +114,15 @@
#include <sys/param.h>
#endif // !_MSC_VER
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/common.h> // for GOOGLE_PREDICT_TRUE macro
namespace google {
namespace protobuf {
+
+class DescriptorPool;
+class MessageFactory;
+
namespace io {
// Defined in this file.
@@ -166,6 +171,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// types of data not covered by the CodedInputStream interface.
bool GetDirectBufferPointer(const void** data, int* size);
+ // Like GetDirectBufferPointer, but this method is inlined, and does not
+ // attempt to Refresh() if the buffer is currently empty.
+ inline void GetDirectBufferPointerInline(const void** data,
+ int* size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
// Read raw bytes, copying them into the given buffer.
bool ReadRaw(void* buffer, int size);
@@ -177,6 +187,10 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// could claim that a string is going to be MAX_INT bytes long in order to
// crash the server because it can't allocate this much space at once.
bool ReadString(string* buffer, int size);
+ // Like the above, with inlined optimizations. This should only be used
+ // by the protobuf implementation.
+ inline bool InternalReadStringInline(string* buffer,
+ int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
// Read a 32-bit little-endian integer.
@@ -184,6 +198,15 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Read a 64-bit little-endian integer.
bool ReadLittleEndian64(uint64* value);
+ // These methods read from an externally provided buffer. The caller is
+ // responsible for ensuring that the buffer has sufficient space.
+ // Read a 32-bit little-endian integer.
+ static const uint8* ReadLittleEndian32FromArray(const uint8* buffer,
+ uint32* value);
+ // Read a 64-bit little-endian integer.
+ static const uint8* ReadLittleEndian64FromArray(const uint8* buffer,
+ uint64* value);
+
// Read an unsigned integer with Varint encoding, truncating to 32 bits.
// Reading a 32-bit value is equivalent to reading a 64-bit one and casting
// it to uint32, but may be more efficient.
@@ -208,6 +231,17 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// when given a constant parameter, but GCC doesn't want to inline by default.
bool ExpectTag(uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ // Like above, except this reads from the specified buffer. The caller is
+ // responsible for ensuring that the buffer is large enough to read a varint
+ // of the expected size. For best performance, use a compile-time constant as
+ // the expected tag parameter.
+ //
+ // Returns a pointer beyond the expected tag if it was found, or NULL if it
+ // was not.
+ static const uint8* ExpectTagFromArray(
+ const uint8* buffer,
+ uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
// Usually returns true if no more bytes can be read. Always returns false
// if more bytes can be read. If ExpectAtEnd() returns true, a subsequent
// call to LastTagWas() will act as if ReadTag() had been called and returned
@@ -318,12 +352,90 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Decrements the recursion depth.
void DecrementRecursionDepth();
+ // Extension Registry ----------------------------------------------
+ // ADVANCED USAGE: 99.9% of people can ignore this section.
+ //
+ // By default, when parsing extensions, the parser looks for extension
+ // definitions in the pool which owns the outer message's Descriptor.
+ // However, you may call SetExtensionRegistry() to provide an alternative
+ // pool instead. This makes it possible, for example, to parse a message
+ // using a generated class, but represent some extensions using
+ // DynamicMessage.
+
+ // Set the pool used to look up extensions. Most users do not need to call
+ // this as the correct pool will be chosen automatically.
+ //
+ // WARNING: It is very easy to misuse this. Carefully read the requirements
+ // below. Do not use this unless you are sure you need it. Almost no one
+ // does.
+ //
+ // Let's say you are parsing a message into message object m, and you want
+ // to take advantage of SetExtensionRegistry(). You must follow these
+ // requirements:
+ //
+ // The given DescriptorPool must contain m->GetDescriptor(). It is not
+ // sufficient for it to simply contain a descriptor that has the same name
+ // and content -- it must be the *exact object*. In other words:
+ // assert(pool->FindMessageTypeByName(m->GetDescriptor()->full_name()) ==
+ // m->GetDescriptor());
+ // There are two ways to satisfy this requirement:
+ // 1) Use m->GetDescriptor()->pool() as the pool. This is generally useless
+ // because this is the pool that would be used anyway if you didn't call
+ // SetExtensionRegistry() at all.
+ // 2) Use a DescriptorPool which has m->GetDescriptor()->pool() as an
+ // "underlay". Read the documentation for DescriptorPool for more
+ // information about underlays.
+ //
+ // You must also provide a MessageFactory. This factory will be used to
+ // construct Message objects representing extensions. The factory's
+ // GetPrototype() MUST return non-NULL for any Descriptor which can be found
+ // through the provided pool.
+ //
+ // If the provided factory might return instances of protocol-compiler-
+ // generated (i.e. compiled-in) types, or if the outer message object m is
+ // a generated type, then the given factory MUST have this property: If
+ // GetPrototype() is given a Descriptor which resides in
+ // DescriptorPool::generated_pool(), the factory MUST return the same
+ // prototype which MessageFactory::generated_factory() would return. That
+ // is, given a descriptor for a generated type, the factory must return an
+ // instance of the generated class (NOT DynamicMessage). However, when
+ // given a descriptor for a type that is NOT in generated_pool, the factory
+ // is free to return any implementation.
+ //
+ // The reason for this requirement is that generated sub-objects may be
+ // accessed via the standard (non-reflection) extension accessor methods,
+ // and these methods will down-cast the object to the generated class type.
+ // If the object is not actually of that type, the results would be undefined.
+ // On the other hand, if an extension is not compiled in, then there is no
+ // way the code could end up accessing it via the standard accessors -- the
+ // only way to access the extension is via reflection. When using reflection,
+ // DynamicMessage and generated messages are indistinguishable, so it's fine
+ // if these objects are represented using DynamicMessage.
+ //
+ // Using DynamicMessageFactory on which you have called
+ // SetDelegateToGeneratedFactory(true) should be sufficient to satisfy the
+ // above requirement.
+ //
+ // If either pool or factory is NULL, both must be NULL.
+ //
+ // Note that this feature is ignored when parsing "lite" messages as they do
+ // not have descriptors.
+ void SetExtensionRegistry(DescriptorPool* pool, MessageFactory* factory);
+
+ // Get the DescriptorPool set via SetExtensionRegistry(), or NULL if no pool
+ // has been provided.
+ const DescriptorPool* GetExtensionPool();
+
+ // Get the MessageFactory set via SetExtensionRegistry(), or NULL if no
+ // factory has been provided.
+ MessageFactory* GetExtensionFactory();
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedInputStream);
ZeroCopyInputStream* input_;
const uint8* buffer_;
- int buffer_size_; // size of current buffer
+ const uint8* buffer_end_; // pointer to the end of the buffer.
int total_bytes_read_; // total bytes read from input_, including
// the current buffer
@@ -334,7 +446,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// LastTagWas() stuff.
uint32 last_tag_; // result of last ReadTag().
- // This is set true by ReadVarint32Fallback() if it is called when exactly
+ // This is set true by ReadTag{Fallback/Slow}() if it is called when exactly
// at EOF, or by ExpectAtEnd() when it returns true. This happens when we
// reach the end of a message and attempt to read another tag.
bool legitimate_message_end_;
@@ -365,6 +477,12 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Recursion depth limit, set by SetRecursionLimit().
int recursion_limit_;
+ // See SetExtensionRegistry().
+ const DescriptorPool* extension_pool_;
+ MessageFactory* extension_factory_;
+
+ // Private member functions.
+
// Advance the buffer by a given number of bytes.
void Advance(int amount);
@@ -379,10 +497,36 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
void PrintTotalBytesLimitError();
// Called when the buffer runs out to request more data. Implies an
- // Advance(buffer_size_).
+ // Advance(BufferSize()).
bool Refresh();
+ // When parsing varints, we optimize for the common case of small values, and
+ // then optimize for the case when the varint fits within the current buffer
+ // piece. The Fallback method is used when we can't use the one-byte
+ // optimization. The Slow method is yet another fallback when the buffer is
+ // not large enough. Making the slow path out-of-line speeds up the common
+ // case by 10-15%. The slow path is fairly uncommon: it only triggers when a
+ // message crosses multiple buffers.
bool ReadVarint32Fallback(uint32* value);
+ bool ReadVarint64Fallback(uint64* value);
+ bool ReadVarint32Slow(uint32* value);
+ bool ReadVarint64Slow(uint64* value);
+ bool ReadLittleEndian32Fallback(uint32* value);
+ bool ReadLittleEndian64Fallback(uint64* value);
+ // Fallback/slow methods for reading tags. These do not update last_tag_,
+ // but will set legitimate_message_end_ if we are at the end of the input
+ // stream.
+ uint32 ReadTagFallback();
+ uint32 ReadTagSlow();
+ bool ReadStringFallback(string* buffer, int size);
+
+ // Return the size of the buffer.
+ int BufferSize() const;
+
+ static const int kDefaultTotalBytesLimit = 64 << 20; // 64MB
+
+ static const int kDefaultTotalBytesWarningThreshold = 32 << 20; // 32MB
+ static const int kDefaultRecursionLimit = 64;
};
// Class which encodes and writes binary data which is composed of varint-
@@ -568,7 +712,7 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// methods optimize for that case.
inline bool CodedInputStream::ReadVarint32(uint32* value) {
- if (buffer_size_ != 0 && *buffer_ < 0x80) {
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) {
*value = *buffer_;
Advance(1);
return true;
@@ -577,20 +721,93 @@ inline bool CodedInputStream::ReadVarint32(uint32* value) {
}
}
+inline bool CodedInputStream::ReadVarint64(uint64* value) {
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) {
+ *value = *buffer_;
+ Advance(1);
+ return true;
+ } else {
+ return ReadVarint64Fallback(value);
+ }
+}
+
+// static
+inline const uint8* CodedInputStream::ReadLittleEndian32FromArray(
+ const uint8* buffer,
+ uint32* value) {
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+ memcpy(value, buffer, sizeof(*value));
+ return buffer + sizeof(*value);
+#else
+ *value = (static_cast<uint32>(buffer[0]) ) |
+ (static_cast<uint32>(buffer[1]) << 8) |
+ (static_cast<uint32>(buffer[2]) << 16) |
+ (static_cast<uint32>(buffer[3]) << 24);
+ return buffer + sizeof(*value);
+#endif
+}
+// static
+inline const uint8* CodedInputStream::ReadLittleEndian64FromArray(
+ const uint8* buffer,
+ uint64* value) {
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+ memcpy(value, buffer, sizeof(*value));
+ return buffer + sizeof(*value);
+#else
+ uint32 part0 = (static_cast<uint32>(buffer[0]) ) |
+ (static_cast<uint32>(buffer[1]) << 8) |
+ (static_cast<uint32>(buffer[2]) << 16) |
+ (static_cast<uint32>(buffer[3]) << 24);
+ uint32 part1 = (static_cast<uint32>(buffer[4]) ) |
+ (static_cast<uint32>(buffer[5]) << 8) |
+ (static_cast<uint32>(buffer[6]) << 16) |
+ (static_cast<uint32>(buffer[7]) << 24);
+ *value = static_cast<uint64>(part0) |
+ (static_cast<uint64>(part1) << 32);
+ return buffer + sizeof(*value);
+#endif
+}
+
+inline bool CodedInputStream::ReadLittleEndian32(uint32* value) {
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+ if (GOOGLE_PREDICT_TRUE(BufferSize() >= sizeof(*value))) {
+ memcpy(value, buffer_, sizeof(*value));
+ Advance(sizeof(*value));
+ return true;
+ } else {
+ return ReadLittleEndian32Fallback(value);
+ }
+#else
+ return ReadLittleEndian32Fallback(value);
+#endif
+}
+
+inline bool CodedInputStream::ReadLittleEndian64(uint64* value) {
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+ if (GOOGLE_PREDICT_TRUE(BufferSize() >= sizeof(*value))) {
+ memcpy(value, buffer_, sizeof(*value));
+ Advance(sizeof(*value));
+ return true;
+ } else {
+ return ReadLittleEndian64Fallback(value);
+ }
+#else
+ return ReadLittleEndian64Fallback(value);
+#endif
+}
+
inline uint32 CodedInputStream::ReadTag() {
- if (buffer_size_ != 0 && buffer_[0] < 0x80) {
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] < 0x80) {
last_tag_ = buffer_[0];
Advance(1);
return last_tag_;
- } else if (buffer_size_ >= 2 && buffer_[1] < 0x80) {
- last_tag_ = (buffer_[0] & 0x7f) + (buffer_[1] << 7);
- Advance(2);
- return last_tag_;
- } else if (ReadVarint32Fallback(&last_tag_)) {
- return last_tag_;
} else {
- last_tag_ = 0;
- return 0;
+ last_tag_ = ReadTagFallback();
+ return last_tag_;
}
}
@@ -604,14 +821,14 @@ inline bool CodedInputStream::ConsumedEntireMessage() {
inline bool CodedInputStream::ExpectTag(uint32 expected) {
if (expected < (1 << 7)) {
- if (buffer_size_ != 0 && buffer_[0] == expected) {
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] == expected) {
Advance(1);
return true;
} else {
return false;
}
} else if (expected < (1 << 14)) {
- if (buffer_size_ >= 2 &&
+ if (GOOGLE_PREDICT_TRUE(BufferSize() >= 2) &&
buffer_[0] == static_cast<uint8>(expected | 0x80) &&
buffer_[1] == static_cast<uint8>(expected >> 7)) {
Advance(2);
@@ -625,11 +842,32 @@ inline bool CodedInputStream::ExpectTag(uint32 expected) {
}
}
+inline const uint8* CodedInputStream::ExpectTagFromArray(
+ const uint8* buffer, uint32 expected) {
+ if (expected < (1 << 7)) {
+ if (buffer[0] == expected) {
+ return buffer + 1;
+ }
+ } else if (expected < (1 << 14)) {
+ if (buffer[0] == static_cast<uint8>(expected | 0x80) &&
+ buffer[1] == static_cast<uint8>(expected >> 7)) {
+ return buffer + 2;
+ }
+ }
+ return NULL;
+}
+
+inline void CodedInputStream::GetDirectBufferPointerInline(const void** data,
+ int* size) {
+ *data = buffer_;
+ *size = buffer_end_ - buffer_;
+}
+
inline bool CodedInputStream::ExpectAtEnd() {
// If we are at a limit we know no more bytes can be read. Otherwise, it's
// hard to say without calling Refresh(), and we'd rather not do that.
- if (buffer_size_ == 0 && buffer_size_after_limit_ != 0) {
+ if (buffer_ == buffer_end_ && buffer_size_after_limit_ != 0) {
last_tag_ = 0; // Pretend we called ReadTag()...
legitimate_message_end_ = true; // ... and it hit EOF.
return true;
@@ -677,11 +915,11 @@ inline uint8* CodedOutputStream::WriteVarint32SignExtendedToArray(
inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value,
uint8* target) {
-#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
memcpy(target, &value, sizeof(value));
#else
- target[0] = static_cast<uint8>(value );
+ target[0] = static_cast<uint8>(value);
target[1] = static_cast<uint8>(value >> 8);
target[2] = static_cast<uint8>(value >> 16);
target[3] = static_cast<uint8>(value >> 24);
@@ -691,18 +929,18 @@ inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value,
inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value,
uint8* target) {
-#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
memcpy(target, &value, sizeof(value));
#else
uint32 part0 = static_cast<uint32>(value);
uint32 part1 = static_cast<uint32>(value >> 32);
- target[0] = static_cast<uint8>(part0 );
+ target[0] = static_cast<uint8>(part0);
target[1] = static_cast<uint8>(part0 >> 8);
target[2] = static_cast<uint8>(part0 >> 16);
target[3] = static_cast<uint8>(part0 >> 24);
- target[4] = static_cast<uint8>(part1 );
+ target[4] = static_cast<uint8>(part1);
target[5] = static_cast<uint8>(part1 >> 8);
target[6] = static_cast<uint8>(part1 >> 16);
target[7] = static_cast<uint8>(part1 >> 24);
@@ -759,7 +997,6 @@ inline int CodedOutputStream::ByteCount() const {
inline void CodedInputStream::Advance(int amount) {
buffer_ += amount;
- buffer_size_ -= amount;
}
inline void CodedOutputStream::Advance(int amount) {
@@ -780,6 +1017,72 @@ inline void CodedInputStream::DecrementRecursionDepth() {
if (recursion_depth_ > 0) --recursion_depth_;
}
+inline void CodedInputStream::SetExtensionRegistry(DescriptorPool* pool,
+ MessageFactory* factory) {
+ extension_pool_ = pool;
+ extension_factory_ = factory;
+}
+
+inline const DescriptorPool* CodedInputStream::GetExtensionPool() {
+ return extension_pool_;
+}
+
+inline MessageFactory* CodedInputStream::GetExtensionFactory() {
+ return extension_factory_;
+}
+
+inline int CodedInputStream::BufferSize() const {
+ return buffer_end_ - buffer_;
+}
+
+inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
+ : input_(input),
+ buffer_(NULL),
+ buffer_end_(NULL),
+ total_bytes_read_(0),
+ overflow_bytes_(0),
+ last_tag_(0),
+ legitimate_message_end_(false),
+ aliasing_enabled_(false),
+ current_limit_(INT_MAX),
+ buffer_size_after_limit_(0),
+ total_bytes_limit_(kDefaultTotalBytesLimit),
+ total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
+ recursion_depth_(0),
+ recursion_limit_(kDefaultRecursionLimit),
+ extension_pool_(NULL),
+ extension_factory_(NULL) {
+ // Eagerly Refresh() so buffer space is immediately available.
+ Refresh();
+}
+
+inline CodedInputStream::CodedInputStream(const uint8* buffer, int size)
+ : input_(NULL),
+ buffer_(buffer),
+ buffer_end_(buffer + size),
+ total_bytes_read_(size),
+ overflow_bytes_(0),
+ last_tag_(0),
+ legitimate_message_end_(false),
+ aliasing_enabled_(false),
+ current_limit_(size),
+ buffer_size_after_limit_(0),
+ total_bytes_limit_(kDefaultTotalBytesLimit),
+ total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
+ recursion_depth_(0),
+ recursion_limit_(kDefaultRecursionLimit),
+ extension_pool_(NULL),
+ extension_factory_(NULL) {
+ // Note that setting current_limit_ == size is important to prevent some
+ // code paths from trying to access input_ and segfaulting.
+}
+
+inline CodedInputStream::~CodedInputStream() {
+ if (input_ != NULL) {
+ BackUpInputToCurrentPosition();
+ }
+}
+
} // namespace io
} // namespace protobuf
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index e165fb93..7d298332 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -242,6 +242,24 @@ TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) {
}
}
+TEST_1D(CodedStreamTest, ExpectTagFromArray, kVarintCases) {
+ memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
+
+ const uint32 expected_value = static_cast<uint32>(kVarintCases_case.value);
+
+ // If the expectation succeeds, it should return a pointer past the tag.
+ if (kVarintCases_case.size <= 2) {
+ EXPECT_TRUE(NULL ==
+ CodedInputStream::ExpectTagFromArray(buffer_,
+ expected_value + 1));
+ EXPECT_TRUE(buffer_ + kVarintCases_case.size ==
+ CodedInputStream::ExpectTagFromArray(buffer_, expected_value));
+ } else {
+ EXPECT_TRUE(NULL ==
+ CodedInputStream::ExpectTagFromArray(buffer_, expected_value));
+ }
+}
+
TEST_2D(CodedStreamTest, ReadVarint64, kVarintCases, kBlockSizes) {
memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
@@ -529,10 +547,32 @@ TEST_2D(CodedStreamTest, WriteLittleEndian64, kFixed64Cases, kBlockSizes) {
EXPECT_EQ(0, memcmp(buffer_, kFixed64Cases_case.bytes, sizeof(uint64)));
}
+// Tests using the static methods to read fixed-size values from raw arrays.
+
+TEST_1D(CodedStreamTest, ReadLittleEndian32FromArray, kFixed32Cases) {
+ memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes));
+
+ uint32 value;
+ const uint8* end = CodedInputStream::ReadLittleEndian32FromArray(
+ buffer_, &value);
+ EXPECT_EQ(kFixed32Cases_case.value, value);
+ EXPECT_TRUE(end == buffer_ + sizeof(value));
+}
+
+TEST_1D(CodedStreamTest, ReadLittleEndian64FromArray, kFixed64Cases) {
+ memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes));
+
+ uint64 value;
+ const uint8* end = CodedInputStream::ReadLittleEndian64FromArray(
+ buffer_, &value);
+ EXPECT_EQ(kFixed64Cases_case.value, value);
+ EXPECT_TRUE(end == buffer_ + sizeof(value));
+}
+
// -------------------------------------------------------------------
// Raw reads and writes
-const char kRawBytes[] = "Some bytes which will be writted and read raw.";
+const char kRawBytes[] = "Some bytes which will be written and read raw.";
TEST_1D(CodedStreamTest, ReadRaw, kBlockSizes) {
memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
@@ -593,6 +633,22 @@ TEST_1D(CodedStreamTest, ReadStringImpossiblyLarge, kBlockSizes) {
}
}
+TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnStack) {
+ // Same test as above, except directly use a buffer. This used to cause
+ // crashes while the above did not.
+ uint8 buffer[8];
+ CodedInputStream coded_input(buffer, 8);
+ string str;
+ EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
+}
+
+TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) {
+ scoped_array<uint8> buffer(new uint8[8]);
+ CodedInputStream coded_input(buffer.get(), 8);
+ string str;
+ EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
+}
+
// -------------------------------------------------------------------
// Skip
@@ -652,6 +708,36 @@ TEST_F(CodedStreamTest, GetDirectBufferPointerInput) {
EXPECT_EQ(8, size);
}
+TEST_F(CodedStreamTest, GetDirectBufferPointerInlineInput) {
+ ArrayInputStream input(buffer_, sizeof(buffer_), 8);
+ CodedInputStream coded_input(&input);
+
+ const void* ptr;
+ int size;
+
+ coded_input.GetDirectBufferPointerInline(&ptr, &size);
+ EXPECT_EQ(buffer_, ptr);
+ EXPECT_EQ(8, size);
+
+ // Peeking again should return the same pointer.
+ coded_input.GetDirectBufferPointerInline(&ptr, &size);
+ EXPECT_EQ(buffer_, ptr);
+ EXPECT_EQ(8, size);
+
+ // Skip forward in the same buffer then peek again.
+ EXPECT_TRUE(coded_input.Skip(3));
+ coded_input.GetDirectBufferPointerInline(&ptr, &size);
+ EXPECT_EQ(buffer_ + 3, ptr);
+ EXPECT_EQ(5, size);
+
+ // Skip to end of buffer and peek -- should return false and provide an empty
+ // buffer. It does not try to Refresh().
+ EXPECT_TRUE(coded_input.Skip(5));
+ coded_input.GetDirectBufferPointerInline(&ptr, &size);
+ EXPECT_EQ(buffer_ + 8, ptr);
+ EXPECT_EQ(0, size);
+}
+
TEST_F(CodedStreamTest, GetDirectBufferPointerOutput) {
ArrayOutputStream output(buffer_, sizeof(buffer_), 8);
CodedOutputStream coded_output(&output);
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index 84d277f4..e1a35ea2 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -315,6 +315,6 @@ bool GzipOutputStream::Close() {
} // namespace io
} // namespace protobuf
-} // namespace google
#endif // HAVE_ZLIB
+} // namespace google
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index 937d777e..c7d3074d 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -65,10 +65,10 @@ void Printer::Print(const map<string, string>& variables, const char* text) {
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);
+ WriteRaw(text + pos, i - pos + 1);
pos = i + 1;
- // Setting this true will cause the next Write() to insert an indent
+ // Setting this true will cause the next WriteRaw() to insert an indent
// first.
at_start_of_line_ = true;
@@ -76,7 +76,7 @@ void Printer::Print(const map<string, string>& variables, const char* text) {
// Saw the start of a variable name.
// Write what we have so far.
- Write(text + pos, i - pos);
+ WriteRaw(text + pos, i - pos);
pos = i + 1;
// Find closing delimiter.
@@ -90,14 +90,14 @@ void Printer::Print(const map<string, string>& variables, const char* text) {
string varname(text + pos, endpos - pos);
if (varname.empty()) {
// Two delimiters in a row reduce to a literal delimiter character.
- Write(&variable_delimiter_, 1);
+ WriteRaw(&variable_delimiter_, 1);
} else {
// Replace with the variable's value.
map<string, string>::const_iterator iter = variables.find(varname);
if (iter == variables.end()) {
GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
} else {
- Write(iter->second.data(), iter->second.size());
+ WriteRaw(iter->second.data(), iter->second.size());
}
}
@@ -108,7 +108,7 @@ void Printer::Print(const map<string, string>& variables, const char* text) {
}
// Write the rest.
- Write(text + pos, size - pos);
+ WriteRaw(text + pos, size - pos);
}
void Printer::Print(const char* text) {
@@ -145,14 +145,23 @@ void Printer::Outdent() {
indent_.resize(indent_.size() - 2);
}
-void Printer::Write(const char* data, int size) {
+void Printer::PrintRaw(const string& data) {
+ WriteRaw(data.data(), data.size());
+}
+
+void Printer::PrintRaw(const char* data) {
+ if (failed_) return;
+ WriteRaw(data, strlen(data));
+}
+
+void Printer::WriteRaw(const char* data, int size) {
if (failed_) return;
if (size == 0) return;
if (at_start_of_line_) {
// Insert an indent.
at_start_of_line_ = false;
- Write(indent_.data(), indent_.size());
+ WriteRaw(indent_.data(), indent_.size());
if (failed_) return;
}
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index b7c4cf39..de085389 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -59,8 +59,8 @@ class ZeroCopyOutputStream; // zero_copy_stream.h
// The above writes "My name is Bob." to the output stream.
//
// Printer aggressively enforces correct usage, crashing (with assert failures)
-// in the case of undefined variables. This helps greatly in debugging code
-// which uses it. This class is not intended to be used by production servers.
+// in the case of undefined variables in debug builds. This helps greatly in
+// debugging code which uses it.
class LIBPROTOBUF_EXPORT Printer {
public:
// Create a printer that writes text to the given output stream. Use the
@@ -94,15 +94,24 @@ class LIBPROTOBUF_EXPORT Printer {
// level is zero.
void Outdent();
+ // Write a string to the output buffer.
+ // This method does not look for newlines to add indentation.
+ void PrintRaw(const string& data);
+
+ // Write a zero-delimited string to output buffer.
+ // This method does not look for newlines to add indentation.
+ void PrintRaw(const char* data);
+
+ // Write some bytes to the output buffer.
+ // This method does not look for newlines to add indentation.
+ void WriteRaw(const char* data, int size);
+
// True if any write to the underlying stream failed. (We don't just
// crash in this case because this is an I/O failure, not a programming
// error.)
bool failed() const { return failed_; }
private:
- // Write some text to the output buffer.
- void Write(const char* data, int size);
-
const char variable_delimiter_;
ZeroCopyOutputStream* const output_;
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index 69c7ee34..580a53da 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -76,10 +76,38 @@ TEST(Printer, BasicPrinting) {
buffer[output.ByteCount()] = '\0';
- EXPECT_STREQ(buffer,
- "Hello World! This is the same line.\n"
- "But this is a new one.\n"
- "And this is another one.");
+ EXPECT_STREQ("Hello World! This is the same line.\n"
+ "But this is a new one.\n"
+ "And this is another one.",
+ buffer);
+ }
+}
+
+TEST(Printer, WriteRaw) {
+ char buffer[8192];
+
+ for (int block_size = 1; block_size < 512; block_size *= 2) {
+ ArrayOutputStream output(buffer, sizeof(buffer), block_size);
+
+ {
+ string string_obj = "From an object\n";
+ Printer printer(&output, '$');
+ printer.WriteRaw("Hello World!", 12);
+ printer.PrintRaw(" This is the same line.\n");
+ printer.PrintRaw("But this is a new one.\nAnd this is another one.");
+ printer.WriteRaw("\n", 1);
+ printer.PrintRaw(string_obj);
+ EXPECT_FALSE(printer.failed());
+ }
+
+ buffer[output.ByteCount()] = '\0';
+
+ EXPECT_STREQ("Hello World! This is the same line.\n"
+ "But this is a new one.\n"
+ "And this is another one."
+ "\n"
+ "From an object\n",
+ buffer);
}
}
@@ -98,6 +126,7 @@ TEST(Printer, VariableSubstitution) {
vars["abcdefg"] = "1234";
printer.Print(vars, "Hello $foo$!\nbar = $bar$\n");
+ printer.PrintRaw("RawBit\n");
printer.Print(vars, "$abcdefg$\nA literal dollar sign: $$");
vars["foo"] = "blah";
@@ -108,12 +137,13 @@ TEST(Printer, VariableSubstitution) {
buffer[output.ByteCount()] = '\0';
- EXPECT_STREQ(buffer,
- "Hello World!\n"
- "bar = $foo$\n"
- "1234\n"
- "A literal dollar sign: $\n"
- "Now foo = blah.");
+ EXPECT_STREQ("Hello World!\n"
+ "bar = $foo$\n"
+ "RawBit\n"
+ "1234\n"
+ "A literal dollar sign: $\n"
+ "Now foo = blah.",
+ buffer);
}
}
@@ -125,15 +155,17 @@ TEST(Printer, InlineVariableSubstitution) {
{
Printer printer(&output, '$');
printer.Print("Hello $foo$!\n", "foo", "World");
+ printer.PrintRaw("RawBit\n");
printer.Print("$foo$ $bar$\n", "foo", "one", "bar", "two");
EXPECT_FALSE(printer.failed());
}
buffer[output.ByteCount()] = '\0';
- EXPECT_STREQ(buffer,
- "Hello World!\n"
- "one two\n");
+ EXPECT_STREQ("Hello World!\n"
+ "RawBit\n"
+ "one two\n",
+ buffer);
}
TEST(Printer, Indenting) {
@@ -156,6 +188,8 @@ TEST(Printer, Indenting) {
printer.Indent();
printer.Print(" And this is still the same line.\n"
"But this is indented.\n");
+ printer.PrintRaw("RawBit has indent at start\n");
+ printer.PrintRaw("but not after a raw newline\n");
printer.Print(vars, "Note that a newline in a variable will break "
"indenting, as we see$newline$here.\n");
printer.Indent();
@@ -169,16 +203,19 @@ TEST(Printer, Indenting) {
buffer[output.ByteCount()] = '\0';
- EXPECT_STREQ(buffer,
+ EXPECT_STREQ(
"This is not indented.\n"
" This is indented\n"
" And so is this\n"
"But this is not. And this is still the same line.\n"
" But this is indented.\n"
- " Note that a newline in a variable will break indenting, as we see\n"
+ " RawBit has indent at start\n"
+ "but not after a raw newline\n"
+ "Note that a newline in a variable will break indenting, as we see\n"
"here.\n"
" And this is double-indented\n"
- "Back to normal.");
+ "Back to normal.",
+ buffer);
}
}
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index 0bda451b..75cbfed5 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -119,7 +119,7 @@ namespace {
CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' ||
c == '\r' || c == '\v');
-CHARACTER_CLASS(Unprintable, c < ' ' && c != '\0');
+CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0');
CHARACTER_CLASS(Digit, '0' <= c && c <= '9');
CHARACTER_CLASS(OctalDigit, '0' <= c && c <= '7');
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index 98386e0b..d115161f 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -63,6 +63,11 @@ class LIBPROTOBUF_EXPORT ErrorCollector {
// 1 to each before printing them.
virtual void AddError(int line, int column, const string& message) = 0;
+ // Indicates that there was a warning in the input at the given line and
+ // column numbers. The numbers are zero-based, so you may want to add
+ // 1 to each before printing them.
+ virtual void AddWarning(int line, int column, const string& message) { }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
};
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index eac1455d..3598e188 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -397,6 +397,12 @@ MultiTokenCase kMultiTokenCases[] = {
{ Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0 },
{ Tokenizer::TYPE_END , "" , 1, 3 },
}},
+
+ // Bytes with the high-order bit set should not be seen as control characters.
+ { "\300", {
+ { Tokenizer::TYPE_SYMBOL, "\300", 0, 0 },
+ { Tokenizer::TYPE_END , "" , 0, 1 },
+ }},
};
TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) {
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h
index 64e96cd4..9fedb005 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl.h
@@ -133,10 +133,11 @@ class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream {
// A ZeroCopyOutputStream which writes to a file descriptor.
//
-// FileInputStream is preferred over using an ofstream with OstreamOutputStream.
-// The latter will introduce an extra layer of buffering, harming performance.
-// Also, it's conceivable that FileInputStream could someday be enhanced
-// to use zero-copy file descriptors on OSs which support them.
+// FileOutputStream is preferred over using an ofstream with
+// OstreamOutputStream. The latter will introduce an extra layer of buffering,
+// harming performance. Also, it's conceivable that FileOutputStream could
+// someday be enhanced to use zero-copy file descriptors on OSs which
+// support them.
class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
public:
// Creates a stream that writes to the given Unix file descriptor.
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index f919b7ac..8229ee6d 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -403,7 +403,8 @@ TEST_F(IoTest, CompressionOptions) {
string golden;
File::ReadFileToStringOrDie(
- TestSourceDir() + "/google/protobuf/testdata/golden_message", &golden);
+ TestSourceDir() + "/google/protobuf/testdata/golden_message",
+ &golden);
GzipOutputStream::Options options;
string gzip_compressed = Compress(golden, options);
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 4e5b662c..d43507cd 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -212,7 +212,7 @@ class GeneratedMessageFactory : public MessageFactory {
};
GeneratedMessageFactory* generated_message_factory_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
+GoogleOnceType generated_message_factory_once_init_;
void ShutdownGeneratedMessageFactory() {
delete generated_message_factory_;
@@ -227,7 +227,7 @@ GeneratedMessageFactory::GeneratedMessageFactory() {}
GeneratedMessageFactory::~GeneratedMessageFactory() {}
GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
- GoogleOnceInit(&generated_message_factory_once_init_,
+ ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_,
&InitGeneratedMessageFactory);
return generated_message_factory_;
}
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 54b596d5..c0062f98 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -148,6 +148,7 @@ namespace protobuf {
// Defined in this file.
class Message;
class Reflection;
+class MessageFactory;
// Defined in other files.
class Descriptor; // descriptor.h
@@ -238,13 +239,15 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
// Reflection object's SpaceUsed() method.
virtual int SpaceUsed() const;
- // Debugging -------------------------------------------------------
+ // Debugging & Testing----------------------------------------------
// Generates a human readable form of this message, useful for debugging
// and other purposes.
string DebugString() const;
// Like DebugString(), but with less whitespace.
string ShortDebugString() const;
+ // Like DebugString(), but do not escape UTF-8 byte sequences.
+ string Utf8DebugString() const;
// Convenience function useful in GDB. Prints DebugString() to stdout.
void PrintDebugString() const;
@@ -327,6 +330,7 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
// GetReflection() wrappers.
virtual Metadata GetMetadata() const = 0;
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
};
@@ -453,8 +457,10 @@ class LIBPROTOBUF_EXPORT Reflection {
const FieldDescriptor* field) const = 0;
virtual const EnumValueDescriptor* GetEnum(
const Message& message, const FieldDescriptor* field) const = 0;
+ // See MutableMessage() for the meaning of the "factory" parameter.
virtual const Message& GetMessage(const Message& message,
- const FieldDescriptor* field) const = 0;
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const = 0;
// Get a string value without copying, if possible.
//
@@ -499,9 +505,19 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual void SetEnum (Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const = 0;
- // Get a mutable pointer to a field with a message type.
+ // Get a mutable pointer to a field with a message type. If a MessageFactory
+ // is provided, it will be used to construct instances of the sub-message;
+ // otherwise, the default factory is used. If the field is an extension that
+ // does not live in the same pool as the containing message's descriptor (e.g.
+ // it lives in an overlay pool), then a MessageFactory must be provided.
+ // If you have no idea what that meant, then you probably don't need to worry
+ // about it (don't provide a MessageFactory). WARNING: If the
+ // FieldDescriptor is for a compiled-in extension, then
+ // factory->GetPrototype(field->message_type() MUST return an instance of the
+ // compiled-in class for this type, NOT DynamicMessage.
virtual Message* MutableMessage(Message* message,
- const FieldDescriptor* field) const = 0;
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const = 0;
// Repeated field getters ------------------------------------------
@@ -603,8 +619,10 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual void AddEnum (Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const = 0;
+ // See MutableMessage() for comments on the "factory" parameter.
virtual Message* AddMessage(Message* message,
- const FieldDescriptor* field) const = 0;
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const = 0;
// Extensions ------------------------------------------------------
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index a53740ad..7c8f37dc 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -33,9 +33,8 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-
#include <google/protobuf/message_lite.h>
-
+#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -52,6 +51,24 @@ string MessageLite::InitializationErrorString() const {
namespace {
+// When serializing, we first compute the byte size, then serialize the message.
+// If serialization produces a different number of bytes than expected, we
+// call this function, which crashes. The problem could be due to a bug in the
+// protobuf implementation but is more likely caused by concurrent modification
+// of the message. This function attempts to distinguish between the two and
+// provide a useful error message.
+void ByteSizeConsistencyError(int byte_size_before_serialization,
+ int byte_size_after_serialization,
+ int bytes_produced_by_serialization) {
+ GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
+ << "Protocol message was modified concurrently during serialization.";
+ GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
+ << "Byte size calculation and serialization were inconsistent. This "
+ "may indicate a bug in protocol buffers or it may be caused by "
+ "concurrent modification of the message.";
+ GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
+}
+
string InitializationErrorMessage(const char* action,
const MessageLite& message) {
// Note: We want to avoid depending on strutil in the lite library, otherwise
@@ -215,9 +232,29 @@ bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
bool MessageLite::SerializePartialToCodedStream(
io::CodedOutputStream* output) const {
- ByteSize(); // Force size to be cached.
- SerializeWithCachedSizes(output);
- return !output->HadError();
+ const int size = ByteSize(); // Force size to be cached.
+ uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
+ if (buffer != NULL) {
+ uint8* end = SerializeWithCachedSizesToArray(buffer);
+ if (end - buffer != size) {
+ ByteSizeConsistencyError(size, ByteSize(), end - buffer);
+ }
+ return true;
+ } else {
+ int original_byte_count = output->ByteCount();
+ SerializeWithCachedSizes(output);
+ if (output->HadError()) {
+ return false;
+ }
+ int final_byte_count = output->ByteCount();
+
+ if (final_byte_count - original_byte_count != size) {
+ ByteSizeConsistencyError(size, ByteSize(),
+ final_byte_count - original_byte_count);
+ }
+
+ return true;
+ }
}
bool MessageLite::SerializeToZeroCopyStream(
@@ -243,7 +280,9 @@ bool MessageLite::AppendPartialToString(string* output) const {
STLStringResizeUninitialized(output, old_size + byte_size);
uint8* start = reinterpret_cast<uint8*>(string_as_array(output) + old_size);
uint8* end = SerializeWithCachedSizesToArray(start);
- GOOGLE_CHECK_EQ(end - start, byte_size);
+ if (end - start != byte_size) {
+ ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
+ }
return true;
}
@@ -265,9 +304,11 @@ bool MessageLite::SerializeToArray(void* data, int size) const {
bool MessageLite::SerializePartialToArray(void* data, int size) const {
int byte_size = ByteSize();
if (size < byte_size) return false;
- uint8* end =
- SerializeWithCachedSizesToArray(reinterpret_cast<uint8*>(data));
- GOOGLE_CHECK_EQ(end, reinterpret_cast<uint8*>(data) + byte_size);
+ uint8* start = reinterpret_cast<uint8*>(data);
+ uint8* end = SerializeWithCachedSizesToArray(start);
+ if (end - start != byte_size) {
+ ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
+ }
return true;
}
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index 3230c04c..f7beb110 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -39,6 +39,18 @@ namespace google {
namespace protobuf {
namespace internal {
+void RepeatedPtrFieldBase::Reserve(int new_size) {
+ if (total_size_ >= new_size) return;
+
+ void** old_elements = elements_;
+ total_size_ = max(total_size_ * 2, new_size);
+ elements_ = new void*[total_size_];
+ memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
+ if (old_elements != initial_space_) {
+ delete [] old_elements;
+ }
+}
+
void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
void** swap_elements = elements_;
int swap_current_size = current_size_;
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 1696e2a3..5954db55 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -51,8 +51,8 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message_lite.h>
-
namespace google {
+
namespace protobuf {
class Message;
@@ -76,10 +76,11 @@ class RepeatedField {
int size() const;
- Element Get(int index) const;
+ const Element& Get(int index) const;
Element* Mutable(int index);
- void Set(int index, Element value);
- void Add(Element value);
+ void Set(int index, const Element& value);
+ void Add(const Element& value);
+ Element* Add();
// Remove the last element in the array.
// We don't provide a way to remove any element other than the last
// because it invites inefficient use, such as O(n^2) filtering loops
@@ -94,6 +95,13 @@ class RepeatedField {
// array is grown, it will always be at least doubled in size.
void Reserve(int new_size);
+ // Resize the RepeatedField to a new, smaller size. This is O(1).
+ void Truncate(int new_size);
+
+ void AddAlreadyReserved(const Element& value);
+ Element* AddAlreadyReserved();
+ int Capacity() const;
+
// Gets the underlying array. This pointer is possibly invalidated by
// any add or remove operation.
Element* mutable_data();
@@ -128,10 +136,19 @@ class RepeatedField {
int total_size_;
Element initial_space_[kInitialSize];
+
+ // Move the contents of |from| into |to|, possibly clobbering |from| in the
+ // process. For primitive types this is just a memcpy(), but it could be
+ // specialized for non-primitive types to, say, swap each element instead.
+ void MoveArray(Element to[], Element from[], int size);
+
+ // Copy the elements of |from| into |to|.
+ void CopyArray(Element to[], const Element from[], int size);
};
namespace internal {
template <typename It> class RepeatedPtrIterator;
+template <typename It> class RepeatedPtrOverPtrsIterator;
} // namespace internal
namespace internal {
@@ -189,8 +206,11 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
void Reserve(int new_size);
+ int Capacity() const;
+
// Used for constructing iterators.
void* const* raw_data() const;
+ void** raw_mutable_data() const;
template <typename TypeHandler>
typename TypeHandler::Type** mutable_data();
@@ -204,6 +224,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
int SpaceUsedExcludingSelf() const;
+
// Advanced memory management --------------------------------------
// Like Add(), but if there are no cleared objects to use, returns NULL.
@@ -215,7 +236,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
typename TypeHandler::Type* ReleaseLast();
- int ClearedCount();
+ int ClearedCount() const;
template <typename TypeHandler>
void AddCleared(typename TypeHandler::Type* value);
template <typename TypeHandler>
@@ -279,13 +300,14 @@ class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
static void Merge(const string& from, string* to) { *to = from; }
};
-class StringTypeHandler : public StringTypeHandlerBase {
+class LIBPROTOBUF_EXPORT StringTypeHandler : public StringTypeHandlerBase {
public:
static int SpaceUsed(const string& value) {
return sizeof(value) + StringSpaceUsedExcludingSelf(value);
}
};
+
} // namespace internal
// RepeatedPtrField is like RepeatedField, but used for repeated strings or
@@ -311,6 +333,8 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// array is grown, it will always be at least doubled in size.
void Reserve(int new_size);
+ int Capacity() const;
+
// Gets the underlying array. This pointer is possibly invalidated by
// any add or remove operation.
Element** mutable_data();
@@ -331,6 +355,12 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
iterator end();
const_iterator end() const;
+ // Custom STL-like iterator that iterates over and returns the underlying
+ // pointers to Element rather than Element itself.
+ typedef internal::RepeatedPtrOverPtrsIterator<Element> pointer_iterator;
+ pointer_iterator pointer_begin();
+ pointer_iterator pointer_end();
+
// Returns (an estimate of) the number of bytes used by the repeated field,
// excluding sizeof(*this).
int SpaceUsedExcludingSelf() const;
@@ -363,7 +393,7 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// Get the number of cleared objects that are currently being kept
// around for reuse.
- int ClearedCount();
+ int ClearedCount() const;
// Add an element to the pool of cleared objects, passing ownership to
// the RepeatedPtrField. The element must be cleared prior to calling
// this method.
@@ -373,16 +403,16 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// Requires: ClearedCount() > 0
Element* ReleaseCleared();
- private:
+ protected:
+ // Note: RepeatedPtrField SHOULD NOT be subclassed by users. We only
+ // subclass it in one place as a hack for compatibility with proto1. The
+ // subclass needs to know about TypeHandler in order to call protected
+ // methods on RepeatedPtrFieldBase.
class TypeHandler;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField);
- // prototype_ is used for RepeatedPtrField<Message> and
- // RepeatedPtrField<MessageLite> only (see constructor).
- // TODO(kenton): Can we use some template magic to avoid wasting space on
- // this field when it isn't used?
- const Element* prototype_;
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField);
};
// implementation ====================================================
@@ -406,9 +436,25 @@ inline int RepeatedField<Element>::size() const {
return current_size_;
}
+template <typename Element>
+inline int RepeatedField<Element>::Capacity() const {
+ return total_size_;
+}
+
+template<typename Element>
+inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) {
+ GOOGLE_DCHECK_LT(size(), Capacity());
+ elements_[current_size_++] = value;
+}
+
+template<typename Element>
+inline Element* RepeatedField<Element>::AddAlreadyReserved() {
+ GOOGLE_DCHECK_LT(size(), Capacity());
+ return &elements_[current_size_++];
+}
template <typename Element>
-inline Element RepeatedField<Element>::Get(int index) const {
+inline const Element& RepeatedField<Element>::Get(int index) const {
GOOGLE_DCHECK_LT(index, size());
return elements_[index];
}
@@ -420,18 +466,24 @@ inline Element* RepeatedField<Element>::Mutable(int index) {
}
template <typename Element>
-inline void RepeatedField<Element>::Set(int index, Element value) {
+inline void RepeatedField<Element>::Set(int index, const Element& value) {
GOOGLE_DCHECK_LT(index, size());
elements_[index] = value;
}
template <typename Element>
-inline void RepeatedField<Element>::Add(Element value) {
+inline void RepeatedField<Element>::Add(const Element& value) {
if (current_size_ == total_size_) Reserve(total_size_ + 1);
elements_[current_size_++] = value;
}
template <typename Element>
+inline Element* RepeatedField<Element>::Add() {
+ if (current_size_ == total_size_) Reserve(total_size_ + 1);
+ return &elements_[current_size_++];
+}
+
+template <typename Element>
inline void RepeatedField<Element>::RemoveLast() {
GOOGLE_DCHECK_GT(current_size_, 0);
--current_size_;
@@ -443,10 +495,9 @@ inline void RepeatedField<Element>::Clear() {
}
template <typename Element>
-void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
+inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
Reserve(current_size_ + other.current_size_);
- memcpy(elements_ + current_size_, other.elements_,
- sizeof(Element) * other.current_size_);
+ CopyArray(elements_ + current_size_, other.elements_, other.current_size_);
current_size_ += other.current_size_;
}
@@ -469,17 +520,17 @@ void RepeatedField<Element>::Swap(RepeatedField* other) {
// We may not be using initial_space_ but it's not worth checking. Just
// copy it anyway.
Element swap_initial_space[kInitialSize];
- memcpy(swap_initial_space, initial_space_, sizeof(initial_space_));
+ MoveArray(swap_initial_space, initial_space_, kInitialSize);
elements_ = other->elements_;
current_size_ = other->current_size_;
total_size_ = other->total_size_;
- memcpy(initial_space_, other->initial_space_, sizeof(initial_space_));
+ MoveArray(initial_space_, other->initial_space_, kInitialSize);
other->elements_ = swap_elements;
other->current_size_ = swap_current_size;
other->total_size_ = swap_total_size;
- memcpy(other->initial_space_, swap_initial_space, sizeof(swap_initial_space));
+ MoveArray(other->initial_space_, swap_initial_space, kInitialSize);
if (elements_ == other->initial_space_) {
elements_ = initial_space_;
@@ -520,19 +571,40 @@ inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
return (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
}
+// Avoid inlining of Reserve(): new, memcpy, and delete[] lead to a significant
+// amount of code bloat.
template <typename Element>
-inline void RepeatedField<Element>::Reserve(int new_size) {
+void RepeatedField<Element>::Reserve(int new_size) {
if (total_size_ >= new_size) return;
Element* old_elements = elements_;
total_size_ = max(total_size_ * 2, new_size);
elements_ = new Element[total_size_];
- memcpy(elements_, old_elements, current_size_ * sizeof(elements_[0]));
+ MoveArray(elements_, old_elements, current_size_);
if (old_elements != initial_space_) {
delete [] old_elements;
}
}
+template <typename Element>
+inline void RepeatedField<Element>::Truncate(int new_size) {
+ GOOGLE_DCHECK_LE(new_size, current_size_);
+ current_size_ = new_size;
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::MoveArray(
+ Element to[], Element from[], int size) {
+ memcpy(to, from, size * sizeof(Element));
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::CopyArray(
+ Element to[], const Element from[], int size) {
+ memcpy(to, from, size * sizeof(Element));
+}
+
+
// -------------------------------------------------------------------
namespace internal {
@@ -600,17 +672,25 @@ void RepeatedPtrFieldBase::Clear() {
}
template <typename TypeHandler>
-void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) {
+inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) {
Reserve(current_size_ + other.current_size_);
for (int i = 0; i < other.current_size_; i++) {
TypeHandler::Merge(other.Get<TypeHandler>(i), Add<TypeHandler>());
}
}
+inline int RepeatedPtrFieldBase::Capacity() const {
+ return total_size_;
+}
+
inline void* const* RepeatedPtrFieldBase::raw_data() const {
return elements_;
}
+inline void** RepeatedPtrFieldBase::raw_mutable_data() const {
+ return elements_;
+}
+
template <typename TypeHandler>
inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() {
// TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
@@ -650,15 +730,29 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() {
}
template <typename TypeHandler>
-inline void RepeatedPtrFieldBase::AddAllocated(
+void RepeatedPtrFieldBase::AddAllocated(
typename TypeHandler::Type* value) {
- if (allocated_size_ == total_size_) Reserve(total_size_ + 1);
- // We don't care about the order of cleared elements, so if there's one
- // in the way, just move it to the back of the array.
- if (current_size_ < allocated_size_) {
+ // Make room for the new pointer.
+ if (current_size_ == total_size_) {
+ // The array is completely full with no cleared objects, so grow it.
+ Reserve(total_size_ + 1);
+ ++allocated_size_;
+ } else if (allocated_size_ == total_size_) {
+ // There is no more space in the pointer array because it contains some
+ // cleared objects awaiting reuse. We don't want to grow the array in this
+ // case because otherwise a loop calling AddAllocated() followed by Clear()
+ // would leak memory.
+ TypeHandler::Delete(cast<TypeHandler>(elements_[current_size_]));
+ } else if (current_size_ < allocated_size_) {
+ // We have some cleared objects. We don't care about their order, so we
+ // can just move the first one to the end to make space.
elements_[allocated_size_] = elements_[current_size_];
+ ++allocated_size_;
+ } else {
+ // There are no cleared objects.
+ ++allocated_size_;
}
- ++allocated_size_;
+
elements_[current_size_++] = value;
}
@@ -677,7 +771,7 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLast() {
}
-inline int RepeatedPtrFieldBase::ClearedCount() {
+inline int RepeatedPtrFieldBase::ClearedCount() const {
return allocated_size_ - current_size_;
}
@@ -694,18 +788,6 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() {
return cast<TypeHandler>(elements_[--allocated_size_]);
}
-inline void RepeatedPtrFieldBase::Reserve(int new_size) {
- if (total_size_ >= new_size) return;
-
- void** old_elements = elements_;
- total_size_ = max(total_size_ * 2, new_size);
- elements_ = new void*[total_size_];
- memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
- if (old_elements != initial_space_) {
- delete [] old_elements;
- }
-}
-
} // namespace internal
// -------------------------------------------------------------------
@@ -720,9 +802,7 @@ class RepeatedPtrField<string>::TypeHandler
template <typename Element>
-inline RepeatedPtrField<Element>::RepeatedPtrField()
- : prototype_(NULL) {
-}
+inline RepeatedPtrField<Element>::RepeatedPtrField() {}
template <typename Element>
RepeatedPtrField<Element>::~RepeatedPtrField() {
@@ -802,7 +882,7 @@ inline Element* RepeatedPtrField<Element>::ReleaseLast() {
template <typename Element>
-inline int RepeatedPtrField<Element>::ClearedCount() {
+inline int RepeatedPtrField<Element>::ClearedCount() const {
return RepeatedPtrFieldBase::ClearedCount();
}
@@ -821,6 +901,11 @@ inline void RepeatedPtrField<Element>::Reserve(int new_size) {
return RepeatedPtrFieldBase::Reserve(new_size);
}
+template <typename Element>
+inline int RepeatedPtrField<Element>::Capacity() const {
+ return RepeatedPtrFieldBase::Capacity();
+}
+
// -------------------------------------------------------------------
namespace internal {
@@ -921,6 +1006,84 @@ class RepeatedPtrIterator
void* const* it_;
};
+// Provide an iterator that operates on pointers to the underlying objects
+// rather than the objects themselves as RepeatedPtrIterator does.
+// Consider using this when working with stl algorithms that change
+// the array.
+template<typename Element>
+class RepeatedPtrOverPtrsIterator
+ : public std::iterator<std::random_access_iterator_tag, Element*> {
+ public:
+ typedef RepeatedPtrOverPtrsIterator<Element> iterator;
+ typedef std::iterator<
+ std::random_access_iterator_tag, Element*> superclass;
+
+ // Let the compiler know that these are type names, so we don't have to
+ // write "typename" in front of them everywhere.
+ typedef typename superclass::reference reference;
+ typedef typename superclass::pointer pointer;
+ typedef typename superclass::difference_type difference_type;
+
+ RepeatedPtrOverPtrsIterator() : it_(NULL) {}
+ explicit RepeatedPtrOverPtrsIterator(void** it) : it_(it) {}
+
+ // dereferenceable
+ reference operator*() const { return *reinterpret_cast<Element**>(it_); }
+ pointer operator->() const { return &(operator*()); }
+
+ // {inc,dec}rementable
+ iterator& operator++() { ++it_; return *this; }
+ iterator operator++(int) { return iterator(it_++); }
+ iterator& operator--() { --it_; return *this; }
+ iterator operator--(int) { return iterator(it_--); }
+
+ // equality_comparable
+ bool operator==(const iterator& x) const { return it_ == x.it_; }
+ bool operator!=(const iterator& x) const { return it_ != x.it_; }
+
+ // less_than_comparable
+ bool operator<(const iterator& x) const { return it_ < x.it_; }
+ bool operator<=(const iterator& x) const { return it_ <= x.it_; }
+ bool operator>(const iterator& x) const { return it_ > x.it_; }
+ bool operator>=(const iterator& x) const { return it_ >= x.it_; }
+
+ // addable, subtractable
+ iterator& operator+=(difference_type d) {
+ it_ += d;
+ return *this;
+ }
+ friend iterator operator+(iterator it, difference_type d) {
+ it += d;
+ return it;
+ }
+ friend iterator operator+(difference_type d, iterator it) {
+ it += d;
+ return it;
+ }
+ iterator& operator-=(difference_type d) {
+ it_ -= d;
+ return *this;
+ }
+ friend iterator operator-(iterator it, difference_type d) {
+ it -= d;
+ return it;
+ }
+
+ // indexable
+ reference operator[](difference_type d) const { return *(*this + d); }
+
+ // random access iterator
+ difference_type operator-(const iterator& x) const { return it_ - x.it_; }
+
+ private:
+ template<typename OtherElement>
+ friend class RepeatedPtrIterator;
+
+ // The internal iterator.
+ void** it_;
+};
+
+
} // namespace internal
template <typename Element>
@@ -944,6 +1107,18 @@ RepeatedPtrField<Element>::end() const {
return iterator(raw_data() + size());
}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::pointer_iterator
+RepeatedPtrField<Element>::pointer_begin() {
+ return pointer_iterator(raw_mutable_data());
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::pointer_iterator
+RepeatedPtrField<Element>::pointer_end() {
+ return pointer_iterator(raw_mutable_data() + size());
+}
+
+
// Iterators and helper functions that follow the spirit of the STL
// std::back_insert_iterator and std::back_inserter but are tailor-made
// for RepeatedField and RepatedPtrField. Typical usage would be:
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 2d87ba88..798b05ee 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -37,6 +37,7 @@
#include <algorithm>
#include <list>
+#include <vector>
#include <google/protobuf/repeated_field.h>
@@ -241,6 +242,29 @@ TEST(RepeatedField, MutableDataIsMutable) {
EXPECT_EQ(2, field.Get(0));
}
+TEST(RepeatedField, Truncate) {
+ RepeatedField<int> field;
+
+ field.Add(12);
+ field.Add(34);
+ field.Add(56);
+ field.Add(78);
+ EXPECT_EQ(4, field.size());
+
+ field.Truncate(3);
+ EXPECT_EQ(3, field.size());
+
+ field.Add(90);
+ EXPECT_EQ(4, field.size());
+ EXPECT_EQ(90, field.Get(3));
+
+ // Truncations that don't change the size are allowed, but growing is not
+ // allowed.
+ field.Truncate(field.size());
+ EXPECT_DEBUG_DEATH(field.Truncate(field.size() + 1), "new_size");
+}
+
+
// ===================================================================
// RepeatedPtrField tests. These pretty much just mirror the RepeatedField
// tests above.
@@ -443,6 +467,52 @@ TEST(RepeatedPtrField, ClearedElements) {
EXPECT_EQ(field.ClearedCount(), 0);
}
+// Test all code paths in AddAllocated().
+TEST(RepeatedPtrField, AddAlocated) {
+ RepeatedPtrField<string> field;
+ while (field.size() < field.Capacity()) {
+ field.Add()->assign("filler");
+ }
+
+ int index = field.size();
+
+ // First branch: Field is at capacity with no cleared objects.
+ string* foo = new string("foo");
+ field.AddAllocated(foo);
+ EXPECT_EQ(index + 1, field.size());
+ EXPECT_EQ(0, field.ClearedCount());
+ EXPECT_EQ(foo, &field.Get(index));
+
+ // Last branch: Field is not at capacity and there are no cleared objects.
+ string* bar = new string("bar");
+ field.AddAllocated(bar);
+ ++index;
+ EXPECT_EQ(index + 1, field.size());
+ EXPECT_EQ(0, field.ClearedCount());
+ EXPECT_EQ(bar, &field.Get(index));
+
+ // Third branch: Field is not at capacity and there are no cleared objects.
+ field.RemoveLast();
+ string* baz = new string("baz");
+ field.AddAllocated(baz);
+ EXPECT_EQ(index + 1, field.size());
+ EXPECT_EQ(1, field.ClearedCount());
+ EXPECT_EQ(baz, &field.Get(index));
+
+ // Second branch: Field is at capacity but has some cleared objects.
+ while (field.size() < field.Capacity()) {
+ field.Add()->assign("filler2");
+ }
+ field.RemoveLast();
+ index = field.size();
+ string* qux = new string("qux");
+ field.AddAllocated(qux);
+ EXPECT_EQ(index + 1, field.size());
+ // We should have discarded the cleared object.
+ EXPECT_EQ(0, field.ClearedCount());
+ EXPECT_EQ(qux, &field.Get(index));
+}
+
TEST(RepeatedPtrField, MergeFrom) {
RepeatedPtrField<string> source, destination;
@@ -614,6 +684,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) {
string v = "f";
RepeatedPtrField<string>::const_iterator it =
lower_bound(proto_array_.begin(), proto_array_.end(), v);
+
EXPECT_EQ(*it, "n");
EXPECT_TRUE(it == proto_array_.begin() + 3);
}
@@ -624,6 +695,149 @@ TEST_F(RepeatedPtrFieldIteratorTest, Mutation) {
EXPECT_EQ("qux", proto_array_.Get(0));
}
+// -------------------------------------------------------------------
+
+class RepeatedPtrFieldPtrsIteratorTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ proto_array_.Add()->assign("foo");
+ proto_array_.Add()->assign("bar");
+ proto_array_.Add()->assign("baz");
+ }
+
+ RepeatedPtrField<string> proto_array_;
+};
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ EXPECT_EQ("foo", **iter);
+ ++iter;
+ EXPECT_EQ("bar", **(iter++));
+ EXPECT_EQ("baz", **iter);
+ ++iter;
+ EXPECT_TRUE(proto_array_.pointer_end() == iter);
+ EXPECT_EQ("baz", **(--proto_array_.pointer_end()));
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ RepeatedPtrField<string>::pointer_iterator iter2 = iter;
+ ++iter2;
+ ++iter2;
+ EXPECT_TRUE(iter + 2 == iter2);
+ EXPECT_TRUE(iter == iter2 - 2);
+ EXPECT_EQ("baz", *iter[2]);
+ EXPECT_EQ("baz", **(iter + 2));
+ EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ RepeatedPtrField<string>::pointer_iterator iter2 = iter + 1;
+ EXPECT_TRUE(iter == iter);
+ EXPECT_TRUE(iter != iter2);
+ EXPECT_TRUE(iter < iter2);
+ EXPECT_TRUE(iter <= iter2);
+ EXPECT_TRUE(iter <= iter);
+ EXPECT_TRUE(iter2 > iter);
+ EXPECT_TRUE(iter2 >= iter);
+ EXPECT_TRUE(iter >= iter);
+}
+
+// Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs.
+// Dereferencing an uninitialized iterator crashes the process.
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) {
+ RepeatedPtrField<string>::pointer_iterator iter;
+ EXPECT_TRUE(iter != proto_array_.pointer_begin());
+ EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1);
+ EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2);
+ EXPECT_TRUE(iter != proto_array_.pointer_begin() + 3);
+ EXPECT_TRUE(iter != proto_array_.pointer_end());
+}
+
+
+// This comparison functor is required by the tests for RepeatedPtrOverPtrs.
+// They operate on strings and need to compare strings as strings in
+// any stl algorithm, even though the iterator returns a pointer to a string
+// - i.e. *iter has type string*.
+struct StringLessThan {
+ bool operator()(const string* z, const string& y) {
+ return *z < y;
+ }
+ bool operator()(const string* z, const string* y) {
+ return *z < *y;
+ }
+};
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
+ proto_array_.Clear();
+ proto_array_.Add()->assign("a");
+ proto_array_.Add()->assign("c");
+ proto_array_.Add()->assign("d");
+ proto_array_.Add()->assign("n");
+ proto_array_.Add()->assign("p");
+ proto_array_.Add()->assign("x");
+ proto_array_.Add()->assign("y");
+
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ string v = "f";
+ RepeatedPtrField<string>::pointer_iterator it =
+ lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
+ v, StringLessThan());
+
+ GOOGLE_CHECK(*it != NULL);
+
+ EXPECT_EQ(**it, "n");
+ EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ **iter = "qux";
+ EXPECT_EQ("qux", proto_array_.Get(0));
+
+ EXPECT_EQ("bar", proto_array_.Get(1));
+ EXPECT_EQ("baz", proto_array_.Get(2));
+ ++iter;
+ delete *iter;
+ *iter = new string("a");
+ ++iter;
+ delete *iter;
+ *iter = new string("b");
+ EXPECT_EQ("a", proto_array_.Get(1));
+ EXPECT_EQ("b", proto_array_.Get(2));
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) {
+ proto_array_.Add()->assign("c");
+ proto_array_.Add()->assign("d");
+ proto_array_.Add()->assign("n");
+ proto_array_.Add()->assign("p");
+ proto_array_.Add()->assign("a");
+ proto_array_.Add()->assign("y");
+ proto_array_.Add()->assign("x");
+ EXPECT_EQ("foo", proto_array_.Get(0));
+ EXPECT_EQ("n", proto_array_.Get(5));
+ EXPECT_EQ("x", proto_array_.Get(9));
+ sort(proto_array_.pointer_begin(),
+ proto_array_.pointer_end(),
+ StringLessThan());
+ EXPECT_EQ("a", proto_array_.Get(0));
+ EXPECT_EQ("baz", proto_array_.Get(2));
+ EXPECT_EQ("y", proto_array_.Get(9));
+}
+
+
// -----------------------------------------------------------------------------
// Unit-tests for the insert iterators
// google::protobuf::RepeatedFieldBackInserter,
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index 3f002373..848ec3ab 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -171,7 +171,13 @@ static const int64 kint64min = -kint64max - 1;
static const uint32 kuint32max = 0xFFFFFFFFu;
static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
-#undef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+// -------------------------------------------------------------------
+// Annotations: Some parts of the code have been annotated in ways that might
+// be useful to some compilers or tools, but are not supported universally.
+// You can #define these annotations yourself if the default implementation
+// is not right for you.
+
+#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
// For functions we want to force inline.
// Introduced in gcc 3.1.
@@ -180,14 +186,35 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
// Other compilers will have to figure it out for themselves.
#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE
#endif
+#endif
-#undef GOOGLE_ATTRIBUTE_DEPRECATED
+#ifndef GOOGLE_ATTRIBUTE_DEPRECATED
#ifdef __GNUC__
// If the method/variable/type is used anywhere, produce a warning.
#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated))
#else
#define GOOGLE_ATTRIBUTE_DEPRECATED
#endif
+#endif
+
+#ifndef GOOGLE_PREDICT_TRUE
+#ifdef __GNUC__
+// Provided at least since GCC 3.0.
+#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#else
+#define GOOGLE_PREDICT_TRUE
+#endif
+#endif
+
+// Delimits a block of code which may write to memory which is simultaneously
+// written by other threads, but which has been determined to be thread-safe
+// (e.g. because it is an idempotent write).
+#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN
+#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN()
+#endif
+#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END
+#define GOOGLE_SAFE_CONCURRENT_WRITES_END()
+#endif
// ===================================================================
// from google3/base/basictypes.h
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 76d9d21e..bb658ba8 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -425,8 +425,8 @@ string UnescapeCEscapeString(const string& src) {
//
// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped.
// ----------------------------------------------------------------------
-static int CEscapeInternal(const char* src, int src_len, char* dest,
- int dest_len, bool use_hex) {
+int CEscapeInternal(const char* src, int src_len, char* dest,
+ int dest_len, bool use_hex, bool utf8_safe) {
const char* src_end = src + src_len;
int used = 0;
bool last_hex_escape = false; // true if last output char was \xNN
@@ -447,7 +447,9 @@ static int CEscapeInternal(const char* src, int src_len, char* dest,
// Note that if we emit \xNN and the src character after that is a hex
// digit then that digit must be escaped too to prevent it being
// interpreted as part of the character code by C.
- if (!isprint(*src) || (last_hex_escape && isxdigit(*src))) {
+ if ((!utf8_safe || static_cast<uint8>(*src) < 0x80) &&
+ (!isprint(*src) ||
+ (last_hex_escape && isxdigit(*src)))) {
if (dest_len - used < 4) // need space for 4 letter escape
return -1;
sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"),
@@ -469,7 +471,7 @@ static int CEscapeInternal(const char* src, int src_len, char* dest,
}
int CEscapeString(const char* src, int src_len, char* dest, int dest_len) {
- return CEscapeInternal(src, src_len, dest, dest_len, false);
+ return CEscapeInternal(src, src_len, dest, dest_len, false, false);
}
// ----------------------------------------------------------------------
@@ -486,11 +488,33 @@ string CEscape(const string& src) {
const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
scoped_array<char> dest(new char[dest_length]);
const int len = CEscapeInternal(src.data(), src.size(),
- dest.get(), dest_length, false);
+ dest.get(), dest_length, false, false);
GOOGLE_DCHECK_GE(len, 0);
return string(dest.get(), len);
}
+namespace strings {
+
+string Utf8SafeCEscape(const string& src) {
+ const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
+ scoped_array<char> dest(new char[dest_length]);
+ const int len = CEscapeInternal(src.data(), src.size(),
+ dest.get(), dest_length, false, true);
+ GOOGLE_DCHECK_GE(len, 0);
+ return string(dest.get(), len);
+}
+
+string CHexEscape(const string& src) {
+ const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
+ scoped_array<char> dest(new char[dest_length]);
+ const int len = CEscapeInternal(src.data(), src.size(),
+ dest.get(), dest_length, true, false);
+ GOOGLE_DCHECK_GE(len, 0);
+ return string(dest.get(), len);
+}
+
+} // namespace strings
+
// ----------------------------------------------------------------------
// strto32_adaptor()
// strtou32_adaptor()
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index c04c1230..777694b7 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -265,6 +265,14 @@ LIBPROTOBUF_EXPORT int CEscapeString(const char* src, int src_len,
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string CEscape(const string& src);
+namespace strings {
+// Like CEscape() but does not escape bytes with the upper bit set.
+LIBPROTOBUF_EXPORT string Utf8SafeCEscape(const string& src);
+
+// Like CEscape() but uses hex (\x) escapes instead of octals.
+LIBPROTOBUF_EXPORT string CHexEscape(const string& src);
+} // namespace strings
+
// ----------------------------------------------------------------------
// strto32()
// strtou32()
diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
index 0637c0a5..af8b3909 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -229,11 +229,11 @@ void TestUtil::ModifyRepeatedFields(unittest::TestAllTypes* message) {
message->GetReflection()->SetRepeatedString(
message,
message->GetDescriptor()->FindFieldByName("repeated_string_piece"),
- 1, "424");
+ 1, "524");
message->GetReflection()->SetRepeatedString(
message,
message->GetDescriptor()->FindFieldByName("repeated_cord"),
- 1, "425");
+ 1, "525");
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
}
@@ -692,6 +692,40 @@ void TestUtil::SetPackedFields(unittest::TestPackedTypes* message) {
message->add_packed_enum (unittest::FOREIGN_BAZ);
}
+void TestUtil::SetUnpackedFields(unittest::TestUnpackedTypes* message) {
+ // The values applied here must match those of SetPackedFields.
+
+ message->add_unpacked_int32 (601);
+ message->add_unpacked_int64 (602);
+ message->add_unpacked_uint32 (603);
+ message->add_unpacked_uint64 (604);
+ message->add_unpacked_sint32 (605);
+ message->add_unpacked_sint64 (606);
+ message->add_unpacked_fixed32 (607);
+ message->add_unpacked_fixed64 (608);
+ message->add_unpacked_sfixed32(609);
+ message->add_unpacked_sfixed64(610);
+ message->add_unpacked_float (611);
+ message->add_unpacked_double (612);
+ message->add_unpacked_bool (true);
+ message->add_unpacked_enum (unittest::FOREIGN_BAR);
+ // add a second one of each field
+ message->add_unpacked_int32 (701);
+ message->add_unpacked_int64 (702);
+ message->add_unpacked_uint32 (703);
+ message->add_unpacked_uint64 (704);
+ message->add_unpacked_sint32 (705);
+ message->add_unpacked_sint64 (706);
+ message->add_unpacked_fixed32 (707);
+ message->add_unpacked_fixed64 (708);
+ message->add_unpacked_sfixed32(709);
+ message->add_unpacked_sfixed64(710);
+ message->add_unpacked_float (711);
+ message->add_unpacked_double (712);
+ message->add_unpacked_bool (false);
+ message->add_unpacked_enum (unittest::FOREIGN_BAZ);
+}
+
// -------------------------------------------------------------------
void TestUtil::ModifyPackedFields(unittest::TestPackedTypes* message) {
@@ -760,6 +794,56 @@ void TestUtil::ExpectPackedFieldsSet(const unittest::TestPackedTypes& message) {
EXPECT_EQ(unittest::FOREIGN_BAZ, message.packed_enum(1));
}
+void TestUtil::ExpectUnpackedFieldsSet(
+ const unittest::TestUnpackedTypes& message) {
+ // The values expected here must match those of ExpectPackedFieldsSet.
+
+ ASSERT_EQ(2, message.unpacked_int32_size ());
+ ASSERT_EQ(2, message.unpacked_int64_size ());
+ ASSERT_EQ(2, message.unpacked_uint32_size ());
+ ASSERT_EQ(2, message.unpacked_uint64_size ());
+ ASSERT_EQ(2, message.unpacked_sint32_size ());
+ ASSERT_EQ(2, message.unpacked_sint64_size ());
+ ASSERT_EQ(2, message.unpacked_fixed32_size ());
+ ASSERT_EQ(2, message.unpacked_fixed64_size ());
+ ASSERT_EQ(2, message.unpacked_sfixed32_size());
+ ASSERT_EQ(2, message.unpacked_sfixed64_size());
+ ASSERT_EQ(2, message.unpacked_float_size ());
+ ASSERT_EQ(2, message.unpacked_double_size ());
+ ASSERT_EQ(2, message.unpacked_bool_size ());
+ ASSERT_EQ(2, message.unpacked_enum_size ());
+
+ EXPECT_EQ(601 , message.unpacked_int32 (0));
+ EXPECT_EQ(602 , message.unpacked_int64 (0));
+ EXPECT_EQ(603 , message.unpacked_uint32 (0));
+ EXPECT_EQ(604 , message.unpacked_uint64 (0));
+ EXPECT_EQ(605 , message.unpacked_sint32 (0));
+ EXPECT_EQ(606 , message.unpacked_sint64 (0));
+ EXPECT_EQ(607 , message.unpacked_fixed32 (0));
+ EXPECT_EQ(608 , message.unpacked_fixed64 (0));
+ EXPECT_EQ(609 , message.unpacked_sfixed32(0));
+ EXPECT_EQ(610 , message.unpacked_sfixed64(0));
+ EXPECT_EQ(611 , message.unpacked_float (0));
+ EXPECT_EQ(612 , message.unpacked_double (0));
+ EXPECT_EQ(true , message.unpacked_bool (0));
+ EXPECT_EQ(unittest::FOREIGN_BAR, message.unpacked_enum(0));
+
+ EXPECT_EQ(701 , message.unpacked_int32 (1));
+ EXPECT_EQ(702 , message.unpacked_int64 (1));
+ EXPECT_EQ(703 , message.unpacked_uint32 (1));
+ EXPECT_EQ(704 , message.unpacked_uint64 (1));
+ EXPECT_EQ(705 , message.unpacked_sint32 (1));
+ EXPECT_EQ(706 , message.unpacked_sint64 (1));
+ EXPECT_EQ(707 , message.unpacked_fixed32 (1));
+ EXPECT_EQ(708 , message.unpacked_fixed64 (1));
+ EXPECT_EQ(709 , message.unpacked_sfixed32(1));
+ EXPECT_EQ(710 , message.unpacked_sfixed64(1));
+ EXPECT_EQ(711 , message.unpacked_float (1));
+ EXPECT_EQ(712 , message.unpacked_double (1));
+ EXPECT_EQ(false, message.unpacked_bool (1));
+ EXPECT_EQ(unittest::FOREIGN_BAZ, message.unpacked_enum(1));
+}
+
// -------------------------------------------------------------------
void TestUtil::ExpectPackedClear(
diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
index 5a6ec88f..25165f3a 100644
--- a/src/google/protobuf/test_util.h
+++ b/src/google/protobuf/test_util.h
@@ -54,6 +54,7 @@ class TestUtil {
static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message);
static void SetPackedFields(unittest::TestPackedTypes* message);
static void SetPackedExtensions(unittest::TestPackedExtensions* message);
+ static void SetUnpackedFields(unittest::TestUnpackedTypes* message);
// Use the repeated versions of the set_*() accessors to modify all the
// repeated fields of the messsage (which should already have been
@@ -72,6 +73,8 @@ class TestUtil {
static void ExpectPackedFieldsSet(const unittest::TestPackedTypes& message);
static void ExpectPackedExtensionsSet(
const unittest::TestPackedExtensions& message);
+ static void ExpectUnpackedFieldsSet(
+ const unittest::TestUnpackedTypes& message);
// Expect that the message is modified as would be expected from
// Modify*Fields().
diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc
index f813e8ee..e224781d 100644
--- a/src/google/protobuf/testing/file.cc
+++ b/src/google/protobuf/testing/file.cc
@@ -84,10 +84,13 @@ void File::ReadFileToStringOrDie(const string& name, string* output) {
void File::WriteStringToFileOrDie(const string& contents, const string& name) {
FILE* file = fopen(name.c_str(), "wb");
- GOOGLE_CHECK(file != NULL);
+ GOOGLE_CHECK(file != NULL)
+ << "fopen(" << name << ", \"wb\"): " << strerror(errno);
GOOGLE_CHECK_EQ(fwrite(contents.data(), 1, contents.size(), file),
- contents.size());
- GOOGLE_CHECK(fclose(file) == 0);
+ contents.size())
+ << "fwrite(" << name << "): " << strerror(errno);
+ GOOGLE_CHECK(fclose(file) == 0)
+ << "fclose(" << name << "): " << strerror(errno);
}
bool File::CreateDir(const string& name, int mode) {
@@ -97,8 +100,10 @@ bool File::CreateDir(const string& name, int mode) {
bool File::RecursivelyCreateDir(const string& path, int mode) {
if (CreateDir(path, mode)) return true;
+ if (Exists(path)) return false;
+
// Try creating the parent.
- string::size_type slashpos = path.find_first_of('/');
+ string::size_type slashpos = path.find_last_of('/');
if (slashpos == string::npos) {
// No parent given.
return false;
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;
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 39a039d9..e78e1042 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -117,6 +117,24 @@ class LIBPROTOBUF_EXPORT TextFormat {
single_line_mode_ = single_line_mode;
}
+ // Set true to print repeated primitives in a format like:
+ // field_name: [1, 2, 3, 4]
+ // instead of printing each value on its own line. Short format applies
+ // only to primitive values -- i.e. everything except strings and
+ // sub-messages/groups. Note that at present this format is not recognized
+ // by the parser.
+ void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) {
+ use_short_repeated_primitives_ = use_short_repeated_primitives;
+ }
+
+ // Set true to output UTF-8 instead of ASCII. The only difference
+ // is that bytes >= 0x80 in string fields will not be escaped,
+ // because they are assumed to be part of UTF-8 multi-byte
+ // sequences.
+ void SetUseUtf8StringEscaping(bool as_utf8) {
+ utf8_string_escaping_ = as_utf8;
+ }
+
private:
// Forward declaration of an internal class used to print the text
// output to the OutputStream (see text_format.cc for implementation).
@@ -133,6 +151,19 @@ class LIBPROTOBUF_EXPORT TextFormat {
const FieldDescriptor* field,
TextGenerator& generator);
+ // Print a repeated primitive field in short form.
+ void PrintShortRepeatedField(const Message& message,
+ const Reflection* reflection,
+ const FieldDescriptor* field,
+ TextGenerator& generator);
+
+ // Print the name of a field -- i.e. everything that comes before the
+ // ':' for a single name/value pair.
+ void PrintFieldName(const Message& message,
+ const Reflection* reflection,
+ const FieldDescriptor* field,
+ TextGenerator& generator);
+
// Outputs a textual representation of the value of the field supplied on
// the message supplied or the default value if not set.
void PrintFieldValue(const Message& message,
@@ -150,6 +181,10 @@ class LIBPROTOBUF_EXPORT TextFormat {
int initial_indent_level_;
bool single_line_mode_;
+
+ bool use_short_repeated_primitives_;
+
+ bool utf8_string_escaping_;
};
// Parses a text-format protocol message from the given input stream to
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 7c31e80f..ddf8ff7f 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -138,12 +138,53 @@ TEST_F(TextFormatTest, ShortDebugString) {
proto_.ShortDebugString());
}
+TEST_F(TextFormatTest, ShortPrimitiveRepeateds) {
+ proto_.set_optional_int32(123);
+ proto_.add_repeated_int32(456);
+ proto_.add_repeated_int32(789);
+ proto_.add_repeated_string("foo");
+ proto_.add_repeated_string("bar");
+ proto_.add_repeated_nested_message()->set_bb(2);
+ proto_.add_repeated_nested_message()->set_bb(3);
+ proto_.add_repeated_nested_enum(unittest::TestAllTypes::FOO);
+ proto_.add_repeated_nested_enum(unittest::TestAllTypes::BAR);
+
+ TextFormat::Printer printer;
+ printer.SetUseShortRepeatedPrimitives(true);
+ string text;
+ printer.PrintToString(proto_, &text);
+
+ EXPECT_EQ("optional_int32: 123\n"
+ "repeated_int32: [456, 789]\n"
+ "repeated_string: \"foo\"\n"
+ "repeated_string: \"bar\"\n"
+ "repeated_nested_message {\n bb: 2\n}\n"
+ "repeated_nested_message {\n bb: 3\n}\n"
+ "repeated_nested_enum: [FOO, BAR]\n",
+ text);
+
+ // Try in single-line mode.
+ printer.SetSingleLineMode(true);
+ printer.PrintToString(proto_, &text);
+
+ EXPECT_EQ("optional_int32: 123 "
+ "repeated_int32: [456, 789] "
+ "repeated_string: \"foo\" "
+ "repeated_string: \"bar\" "
+ "repeated_nested_message { bb: 2 } "
+ "repeated_nested_message { bb: 3 } "
+ "repeated_nested_enum: [FOO, BAR] ",
+ text);
+}
+
+
TEST_F(TextFormatTest, StringEscape) {
// Set the string value to test.
proto_.set_optional_string(kEscapeTestString);
// Get the DebugString from the proto.
string debug_string = proto_.DebugString();
+ string utf8_debug_string = proto_.Utf8DebugString();
// Hardcode a correct value to test against.
string correct_string = "optional_string: "
@@ -152,12 +193,36 @@ TEST_F(TextFormatTest, StringEscape) {
// Compare.
EXPECT_EQ(correct_string, debug_string);
+ // UTF-8 string is the same as non-UTF-8 because
+ // the protocol buffer contains no UTF-8 text.
+ EXPECT_EQ(correct_string, utf8_debug_string);
string expected_short_debug_string = "optional_string: "
+ kEscapeTestStringEscaped;
EXPECT_EQ(expected_short_debug_string, proto_.ShortDebugString());
}
+TEST_F(TextFormatTest, Utf8DebugString) {
+ // Set the string value to test.
+ proto_.set_optional_string("\350\260\267\346\255\214");
+
+ // Get the DebugString from the proto.
+ string debug_string = proto_.DebugString();
+ string utf8_debug_string = proto_.Utf8DebugString();
+
+ // Hardcode a correct value to test against.
+ string correct_utf8_string = "optional_string: "
+ "\"\350\260\267\346\255\214\""
+ "\n";
+ string correct_string = "optional_string: "
+ "\"\\350\\260\\267\\346\\255\\214\""
+ "\n";
+
+ // Compare.
+ EXPECT_EQ(correct_utf8_string, utf8_debug_string);
+ EXPECT_EQ(correct_string, debug_string);
+}
+
TEST_F(TextFormatTest, PrintUnknownFields) {
// Test printing of unknown fields in a message.
@@ -603,10 +668,15 @@ class TextFormatParserTest : public testing::Test {
void ExpectFailure(const string& input, const string& message, int line,
int col, Message* proto) {
+ ExpectMessage(input, message, line, col, proto, false);
+ }
+
+ void ExpectMessage(const string& input, const string& message, int line,
+ int col, Message* proto, bool expected_result) {
TextFormat::Parser parser;
MockErrorCollector error_collector;
parser.RecordErrorsTo(&error_collector);
- EXPECT_FALSE(parser.ParseFromString(input, proto));
+ EXPECT_EQ(parser.ParseFromString(input, proto), expected_result);
EXPECT_EQ(SimpleItoa(line) + ":" + SimpleItoa(col) + ": " + message + "\n",
error_collector.text_);
}
@@ -625,6 +695,10 @@ class TextFormatParserTest : public testing::Test {
strings::SubstituteAndAppend(&text_, "$0:$1: $2\n",
line + 1, column + 1, message);
}
+
+ void AddWarning(int line, int column, const string& message) {
+ AddError(line, column, "WARNING:" + message);
+ }
};
};
@@ -945,6 +1019,12 @@ TEST_F(TextFormatParserTest, FailsOnTokenizationError) {
errors[0]);
}
+TEST_F(TextFormatParserTest, ParseDeprecatedField) {
+ unittest::TestDeprecatedFields message;
+ ExpectMessage("deprecated_int32: 42",
+ "WARNING:text format contains deprecated field "
+ "\"deprecated_int32\"", 1, 21, &message, true);
+}
class TextFormatMessageSetTest : public testing::Test {
protected:
@@ -991,5 +1071,4 @@ TEST_F(TextFormatMessageSetTest, Deserialize) {
} // namespace text_format_unittest
} // namespace protobuf
-
} // namespace google
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index 03811de8..d51fa1e7 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -155,6 +155,10 @@ message TestAllTypes {
optional string default_cord = 85 [ctype=CORD,default="123"];
}
+message TestDeprecatedFields {
+ optional int32 deprecated_int32 = 1 [deprecated=true];
+}
+
// Define these after TestAllTypes to make sure the compiler can handle
// that.
message ForeignMessage {
@@ -348,6 +352,12 @@ message TestEmptyMessageWithExtensions {
extensions 1 to max;
}
+message TestMultipleExtensionRanges {
+ extensions 42;
+ extensions 4143 to 4243;
+ extensions 65536 to max;
+}
+
// Test that really large tag numbers don't break anything.
message TestReallyLargeTagNumber {
// The largest possible tag number is 2^28 - 1, since the wire format uses
@@ -372,13 +382,14 @@ message TestMutualRecursionB {
}
// Test that groups have disjoint field numbers from their siblings and
-// parents. This is NOT possible in proto1; only proto2. When outputting
-// proto1, the dup fields should be dropped.
-message TestDupFieldNumber {
- optional int32 a = 1;
- optional group Foo = 2 { optional int32 a = 1; }
- optional group Bar = 3 { optional int32 a = 1; }
-}
+// parents. This is NOT possible in proto1; only proto2. When attempting
+// to compile with proto1, this will emit an error; so we only include it
+// in protobuf_unittest_proto.
+message TestDupFieldNumber { // NO_PROTO1
+ optional int32 a = 1; // NO_PROTO1
+ optional group Foo = 2 { optional int32 a = 1; } // NO_PROTO1
+ optional group Bar = 3 { optional int32 a = 1; } // NO_PROTO1
+} // NO_PROTO1
// Needed for a Python test.
@@ -468,6 +479,14 @@ message TestExtremeDefaultValues {
// Using exponents
optional float large_float = 12 [default = 2E8];
optional float small_negative_float = 13 [default = -8e-28];
+
+ // Text for nonfinite floating-point values.
+ optional double inf_double = 14 [default = inf];
+ optional double neg_inf_double = 15 [default = -inf];
+ optional double nan_double = 16 [default = nan];
+ optional float inf_float = 17 [default = inf];
+ optional float neg_inf_float = 18 [default = -inf];
+ optional float nan_float = 19 [default = nan];
}
// Test String and Bytes: string is for valid UTF-8 strings
@@ -498,6 +517,25 @@ message TestPackedTypes {
repeated ForeignEnum packed_enum = 103 [packed = true];
}
+// A message with the same fields as TestPackedTypes, but without packing. Used
+// to test packed <-> unpacked wire compatibility.
+message TestUnpackedTypes {
+ repeated int32 unpacked_int32 = 90 [packed = false];
+ repeated int64 unpacked_int64 = 91 [packed = false];
+ repeated uint32 unpacked_uint32 = 92 [packed = false];
+ repeated uint64 unpacked_uint64 = 93 [packed = false];
+ repeated sint32 unpacked_sint32 = 94 [packed = false];
+ repeated sint64 unpacked_sint64 = 95 [packed = false];
+ repeated fixed32 unpacked_fixed32 = 96 [packed = false];
+ repeated fixed64 unpacked_fixed64 = 97 [packed = false];
+ repeated sfixed32 unpacked_sfixed32 = 98 [packed = false];
+ repeated sfixed64 unpacked_sfixed64 = 99 [packed = false];
+ repeated float unpacked_float = 100 [packed = false];
+ repeated double unpacked_double = 101 [packed = false];
+ repeated bool unpacked_bool = 102 [packed = false];
+ repeated ForeignEnum unpacked_enum = 103 [packed = false];
+}
+
message TestPackedExtensions {
extensions 1 to max;
}
@@ -519,6 +557,47 @@ extend TestPackedExtensions {
repeated ForeignEnum packed_enum_extension = 103 [packed = true];
}
+// Used by ExtensionSetTest/DynamicExtensions. The test actually builds
+// a set of extensions to TestAllExtensions dynamically, based on the fields
+// of this message type.
+message TestDynamicExtensions {
+ enum DynamicEnumType {
+ DYNAMIC_FOO = 2200;
+ DYNAMIC_BAR = 2201;
+ DYNAMIC_BAZ = 2202;
+ }
+ message DynamicMessageType {
+ optional int32 dynamic_field = 2100;
+ }
+
+ optional fixed32 scalar_extension = 2000;
+ optional ForeignEnum enum_extension = 2001;
+ optional DynamicEnumType dynamic_enum_extension = 2002;
+
+ optional ForeignMessage message_extension = 2003;
+ optional DynamicMessageType dynamic_message_extension = 2004;
+
+ repeated string repeated_extension = 2005;
+ repeated sint32 packed_extension = 2006 [packed = true];
+}
+
+message TestRepeatedScalarDifferentTagSizes {
+ // Parsing repeated fixed size values used to fail. This message needs to be
+ // used in order to get a tag of the right size; all of the repeated fields
+ // in TestAllTypes didn't trigger the check.
+ repeated fixed32 repeated_fixed32 = 12;
+ // Check for a varint type, just for good measure.
+ repeated int32 repeated_int32 = 13;
+
+ // These have two-byte tags.
+ repeated fixed64 repeated_fixed64 = 2046;
+ repeated int64 repeated_int64 = 2047;
+
+ // Three byte tags.
+ repeated float repeated_float = 262142;
+ repeated uint64 repeated_uint64 = 262143;
+}
+
// Test that RPC services work.
message FooRequest {}
message FooResponse {}
diff --git a/src/google/protobuf/unittest_enormous_descriptor.proto b/src/google/protobuf/unittest_enormous_descriptor.proto
index 6ad2dab3..bc0b7c16 100644
--- a/src/google/protobuf/unittest_enormous_descriptor.proto
+++ b/src/google/protobuf/unittest_enormous_descriptor.proto
@@ -35,6 +35,7 @@
// A proto file that has an extremely large descriptor. Used to test that
// descriptors over 64k don't break the string literal length limit in Java.
+
package google.protobuf;
option java_package = "com.google.protobuf";
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 318ffafe..e1f8b838 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -32,6 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/stubs/stl_util-inl.h>
#include <google/protobuf/io/coded_stream.h>
@@ -50,13 +51,12 @@ UnknownFieldSet::~UnknownFieldSet() {
delete fields_;
}
-void UnknownFieldSet::Clear() {
- if (fields_ != NULL) {
- for (int i = 0; i < fields_->size(); i++) {
- (*fields_)[i].Delete();
- }
- fields_->clear();
+void UnknownFieldSet::ClearFallback() {
+ GOOGLE_DCHECK(fields_ != NULL);
+ for (int i = 0; i < fields_->size(); i++) {
+ (*fields_)[i].Delete();
}
+ fields_->clear();
}
void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index d6ca70fc..84c2e2b6 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -66,7 +66,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
~UnknownFieldSet();
// Remove all fields.
- void Clear();
+ inline void Clear();
// Is this set empty?
inline bool empty() const;
@@ -119,6 +119,8 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
}
private:
+ void ClearFallback();
+
vector<UnknownField>* fields_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
@@ -180,6 +182,12 @@ class LIBPROTOBUF_EXPORT UnknownField {
// ===================================================================
// inline implementations
+inline void UnknownFieldSet::Clear() {
+ if (fields_ != NULL) {
+ ClearFallback();
+ }
+}
+
inline bool UnknownFieldSet::empty() const {
return fields_ == NULL || fields_->empty();
}
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index 5aa67727..831a5794 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -391,7 +391,12 @@ bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input,
// If that failed, check if the field is an extension.
if (field == NULL && descriptor->IsExtensionNumber(field_number)) {
- field = message_reflection->FindKnownExtensionByNumber(field_number);
+ if (input->GetExtensionPool() == NULL) {
+ field = message_reflection->FindKnownExtensionByNumber(field_number);
+ } else {
+ field = input->GetExtensionPool()
+ ->FindExtensionByNumber(descriptor, field_number);
+ }
}
// If that failed, but we're a MessageSet, and this is the tag for a
@@ -419,52 +424,67 @@ bool WireFormat::ParseAndMergeField(
io::CodedInputStream* input) {
const Reflection* message_reflection = message->GetReflection();
- if (field == NULL ||
- WireFormatLite::GetTagWireType(tag) != WireTypeForField(field)) {
- // We don't recognize this field. Either the field number is unknown
- // or the wire type doesn't match. Put it in our unknown field set.
- return SkipField(input, tag,
- message_reflection->MutableUnknownFields(message));
+ enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format;
+
+ if (field == NULL) {
+ value_format = UNKNOWN;
+ } else if (WireFormatLite::GetTagWireType(tag) ==
+ WireTypeForFieldType(field->type())) {
+ value_format = NORMAL_FORMAT;
+ } else if (field->is_packable() &&
+ WireFormatLite::GetTagWireType(tag) ==
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ value_format = PACKED_FORMAT;
+ } else {
+ // We don't recognize this field. Either the field number is unknown
+ // or the wire type doesn't match. Put it in our unknown field set.
+ value_format = UNKNOWN;
}
- if (field->options().packed()) {
+ if (value_format == UNKNOWN) {
+ return SkipField(input, tag,
+ message_reflection->MutableUnknownFields(message));
+ } else if (value_format == PACKED_FORMAT) {
uint32 length;
if (!input->ReadVarint32(&length)) return false;
io::CodedInputStream::Limit limit = input->PushLimit(length);
switch (field->type()) {
-#define HANDLE_PACKED_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \
+#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: { \
while (input->BytesUntilLimit() > 0) { \
CPPTYPE value; \
- if (!WireFormatLite::Read##TYPE_METHOD(input, &value)) return false; \
+ if (!WireFormatLite::ReadPrimitive< \
+ CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \
+ return false; \
message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
} \
break; \
}
- HANDLE_PACKED_TYPE( INT32, Int32, int32, Int32)
- HANDLE_PACKED_TYPE( INT64, Int64, int64, Int64)
- HANDLE_PACKED_TYPE(SINT32, SInt32, int32, Int32)
- HANDLE_PACKED_TYPE(SINT64, SInt64, int64, Int64)
- HANDLE_PACKED_TYPE(UINT32, UInt32, uint32, UInt32)
- HANDLE_PACKED_TYPE(UINT64, UInt64, uint64, UInt64)
+ HANDLE_PACKED_TYPE( INT32, int32, Int32)
+ HANDLE_PACKED_TYPE( INT64, int64, Int64)
+ HANDLE_PACKED_TYPE(SINT32, int32, Int32)
+ HANDLE_PACKED_TYPE(SINT64, int64, Int64)
+ HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
+ HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
- HANDLE_PACKED_TYPE( FIXED32, Fixed32, uint32, UInt32)
- HANDLE_PACKED_TYPE( FIXED64, Fixed64, uint64, UInt64)
- HANDLE_PACKED_TYPE(SFIXED32, SFixed32, int32, Int32)
- HANDLE_PACKED_TYPE(SFIXED64, SFixed64, int64, Int64)
+ HANDLE_PACKED_TYPE( FIXED32, uint32, UInt32)
+ HANDLE_PACKED_TYPE( FIXED64, uint64, UInt64)
+ HANDLE_PACKED_TYPE(SFIXED32, int32, Int32)
+ HANDLE_PACKED_TYPE(SFIXED64, int64, Int64)
- HANDLE_PACKED_TYPE(FLOAT , Float , float , Float )
- HANDLE_PACKED_TYPE(DOUBLE, Double, double, Double)
+ HANDLE_PACKED_TYPE(FLOAT , float , Float )
+ HANDLE_PACKED_TYPE(DOUBLE, double, Double)
- HANDLE_PACKED_TYPE(BOOL, Bool, bool, Bool)
+ HANDLE_PACKED_TYPE(BOOL, bool, Bool)
#undef HANDLE_PACKED_TYPE
case FieldDescriptor::TYPE_ENUM: {
while (input->BytesUntilLimit() > 0) {
int value;
- if (!WireFormatLite::ReadEnum(input, &value)) return false;
+ if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ input, &value)) return false;
const EnumValueDescriptor* enum_value =
field->enum_type()->FindValueByNumber(value);
if (enum_value != NULL) {
@@ -487,11 +507,14 @@ bool WireFormat::ParseAndMergeField(
input->PopLimit(limit);
} else {
+ // Non-packed value (value_format == NORMAL_FORMAT)
switch (field->type()) {
-#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \
+#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: { \
CPPTYPE value; \
- if (!WireFormatLite::Read##TYPE_METHOD(input, &value)) return false; \
+ if (!WireFormatLite::ReadPrimitive< \
+ CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \
+ return false; \
if (field->is_repeated()) { \
message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
} else { \
@@ -500,31 +523,28 @@ bool WireFormat::ParseAndMergeField(
break; \
}
- HANDLE_TYPE( INT32, Int32, int32, Int32)
- HANDLE_TYPE( INT64, Int64, int64, Int64)
- HANDLE_TYPE(SINT32, SInt32, int32, Int32)
- HANDLE_TYPE(SINT64, SInt64, int64, Int64)
- HANDLE_TYPE(UINT32, UInt32, uint32, UInt32)
- HANDLE_TYPE(UINT64, UInt64, uint64, UInt64)
-
- HANDLE_TYPE( FIXED32, Fixed32, uint32, UInt32)
- HANDLE_TYPE( FIXED64, Fixed64, uint64, UInt64)
- HANDLE_TYPE(SFIXED32, SFixed32, int32, Int32)
- HANDLE_TYPE(SFIXED64, SFixed64, int64, Int64)
-
- HANDLE_TYPE(FLOAT , Float , float , Float )
- HANDLE_TYPE(DOUBLE, Double, double, Double)
+ HANDLE_TYPE( INT32, int32, Int32)
+ HANDLE_TYPE( INT64, int64, Int64)
+ HANDLE_TYPE(SINT32, int32, Int32)
+ HANDLE_TYPE(SINT64, int64, Int64)
+ HANDLE_TYPE(UINT32, uint32, UInt32)
+ HANDLE_TYPE(UINT64, uint64, UInt64)
- HANDLE_TYPE(BOOL, Bool, bool, Bool)
+ HANDLE_TYPE( FIXED32, uint32, UInt32)
+ HANDLE_TYPE( FIXED64, uint64, UInt64)
+ HANDLE_TYPE(SFIXED32, int32, Int32)
+ HANDLE_TYPE(SFIXED64, int64, Int64)
- HANDLE_TYPE(STRING, String, string, String)
- HANDLE_TYPE(BYTES, Bytes, string, String)
+ HANDLE_TYPE(FLOAT , float , Float )
+ HANDLE_TYPE(DOUBLE, double, Double)
+ HANDLE_TYPE(BOOL, bool, Bool)
#undef HANDLE_TYPE
case FieldDescriptor::TYPE_ENUM: {
int value;
- if (!WireFormatLite::ReadEnum(input, &value)) return false;
+ if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ input, &value)) return false;
const EnumValueDescriptor* enum_value =
field->enum_type()->FindValueByNumber(value);
if (enum_value != NULL) {
@@ -544,13 +564,38 @@ bool WireFormat::ParseAndMergeField(
break;
}
+ // Handle strings separately so that we can optimize the ctype=CORD case.
+ case FieldDescriptor::TYPE_STRING: {
+ string value;
+ if (!WireFormatLite::ReadString(input, &value)) return false;
+ VerifyUTF8String(value.data(), value.length(), PARSE);
+ if (field->is_repeated()) {
+ message_reflection->AddString(message, field, value);
+ } else {
+ message_reflection->SetString(message, field, value);
+ }
+ break;
+ }
+
+ case FieldDescriptor::TYPE_BYTES: {
+ string value;
+ if (!WireFormatLite::ReadBytes(input, &value)) return false;
+ if (field->is_repeated()) {
+ message_reflection->AddString(message, field, value);
+ } else {
+ message_reflection->SetString(message, field, value);
+ }
+ break;
+ }
case FieldDescriptor::TYPE_GROUP: {
Message* sub_message;
if (field->is_repeated()) {
- sub_message = message_reflection->AddMessage(message, field);
+ sub_message = message_reflection->AddMessage(
+ message, field, input->GetExtensionFactory());
} else {
- sub_message = message_reflection->MutableMessage(message, field);
+ sub_message = message_reflection->MutableMessage(
+ message, field, input->GetExtensionFactory());
}
if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag),
@@ -562,9 +607,11 @@ bool WireFormat::ParseAndMergeField(
case FieldDescriptor::TYPE_MESSAGE: {
Message* sub_message;
if (field->is_repeated()) {
- sub_message = message_reflection->AddMessage(message, field);
+ sub_message = message_reflection->AddMessage(
+ message, field, input->GetExtensionFactory());
} else {
- sub_message = message_reflection->MutableMessage(message, field);
+ sub_message = message_reflection->MutableMessage(
+ message, field, input->GetExtensionFactory());
}
if (!WireFormatLite::ReadMessage(input, sub_message)) return false;
@@ -782,23 +829,23 @@ void WireFormat::SerializeFieldWithCachedSizes(
// Handle strings separately so that we can get string references
// instead of copying.
case FieldDescriptor::TYPE_STRING: {
- string scratch;
- const string& value = field->is_repeated() ?
- message_reflection->GetRepeatedStringReference(
- message, field, j, &scratch) :
- message_reflection->GetStringReference(message, field, &scratch);
- VerifyUTF8String(value.data(), value.length(), SERIALIZE);
- WireFormatLite::WriteString(field->number(), value, output);
+ string scratch;
+ const string& value = field->is_repeated() ?
+ message_reflection->GetRepeatedStringReference(
+ message, field, j, &scratch) :
+ message_reflection->GetStringReference(message, field, &scratch);
+ VerifyUTF8String(value.data(), value.length(), SERIALIZE);
+ WireFormatLite::WriteString(field->number(), value, output);
break;
}
case FieldDescriptor::TYPE_BYTES: {
- string scratch;
- const string& value = field->is_repeated() ?
- message_reflection->GetRepeatedStringReference(
- message, field, j, &scratch) :
- message_reflection->GetStringReference(message, field, &scratch);
- WireFormatLite::WriteBytes(field->number(), value, output);
+ string scratch;
+ const string& value = field->is_repeated() ?
+ message_reflection->GetRepeatedStringReference(
+ message, field, j, &scratch) :
+ message_reflection->GetStringReference(message, field, &scratch);
+ WireFormatLite::WriteBytes(field->number(), value, output);
break;
}
}
@@ -961,14 +1008,14 @@ int WireFormat::FieldDataOnlyByteSize(
// instead of copying.
case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_BYTES: {
- for (int j = 0; j < count; j++) {
- string scratch;
- const string& value = field->is_repeated() ?
- message_reflection->GetRepeatedStringReference(
- message, field, j, &scratch) :
- message_reflection->GetStringReference(message, field, &scratch);
- data_size += WireFormatLite::StringSize(value);
- }
+ for (int j = 0; j < count; j++) {
+ string scratch;
+ const string& value = field->is_repeated() ?
+ message_reflection->GetRepeatedStringReference(
+ message, field, j, &scratch) :
+ message_reflection->GetStringReference(message, field, &scratch);
+ data_size += WireFormatLite::StringSize(value);
+ }
break;
}
}
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 5d09803a..d347d116 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -32,14 +32,13 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/wire_format_lite_inl.h>
+
#include <stack>
#include <string>
#include <vector>
-
-#include <google/protobuf/wire_format_lite_inl.h>
-
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/coded_stream_inl.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -187,6 +186,174 @@ void FieldSkipper::SkipUnknownEnum(
// Nothing.
}
+bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
+ bool (*is_valid)(int),
+ RepeatedField<int>* values) {
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ io::CodedInputStream::Limit limit = input->PushLimit(length);
+ while (input->BytesUntilLimit() > 0) {
+ int value;
+ if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+ return false;
+ }
+ if (is_valid(value)) {
+ values->Add(value);
+ }
+ }
+ input->PopLimit(limit);
+ return true;
+}
+
+void WireFormatLite::WriteInt32(int field_number, int32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteInt32NoTag(value, output);
+}
+void WireFormatLite::WriteInt64(int field_number, int64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteInt64NoTag(value, output);
+}
+void WireFormatLite::WriteUInt32(int field_number, uint32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteUInt32NoTag(value, output);
+}
+void WireFormatLite::WriteUInt64(int field_number, uint64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteUInt64NoTag(value, output);
+}
+void WireFormatLite::WriteSInt32(int field_number, int32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteSInt32NoTag(value, output);
+}
+void WireFormatLite::WriteSInt64(int field_number, int64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteSInt64NoTag(value, output);
+}
+void WireFormatLite::WriteFixed32(int field_number, uint32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED32, output);
+ WriteFixed32NoTag(value, output);
+}
+void WireFormatLite::WriteFixed64(int field_number, uint64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED64, output);
+ WriteFixed64NoTag(value, output);
+}
+void WireFormatLite::WriteSFixed32(int field_number, int32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED32, output);
+ WriteSFixed32NoTag(value, output);
+}
+void WireFormatLite::WriteSFixed64(int field_number, int64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED64, output);
+ WriteSFixed64NoTag(value, output);
+}
+void WireFormatLite::WriteFloat(int field_number, float value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED32, output);
+ WriteFloatNoTag(value, output);
+}
+void WireFormatLite::WriteDouble(int field_number, double value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED64, output);
+ WriteDoubleNoTag(value, output);
+}
+void WireFormatLite::WriteBool(int field_number, bool value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteBoolNoTag(value, output);
+}
+void WireFormatLite::WriteEnum(int field_number, int value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteEnumNoTag(value, output);
+}
+
+void WireFormatLite::WriteString(int field_number, const string& value,
+ io::CodedOutputStream* output) {
+ // String is for UTF-8 text only
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ output->WriteVarint32(value.size());
+ output->WriteString(value);
+}
+void WireFormatLite::WriteBytes(int field_number, const string& value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ output->WriteVarint32(value.size());
+ output->WriteString(value);
+}
+
+
+void WireFormatLite::WriteGroup(int field_number,
+ const MessageLite& value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_START_GROUP, output);
+ value.SerializeWithCachedSizes(output);
+ WriteTag(field_number, WIRETYPE_END_GROUP, output);
+}
+
+void WireFormatLite::WriteMessage(int field_number,
+ const MessageLite& value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ const int size = value.GetCachedSize();
+ output->WriteVarint32(size);
+ value.SerializeWithCachedSizes(output);
+}
+
+void WireFormatLite::WriteGroupMaybeToArray(int field_number,
+ const MessageLite& value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_START_GROUP, output);
+ const int size = value.GetCachedSize();
+ uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
+ if (target != NULL) {
+ uint8* end = value.SerializeWithCachedSizesToArray(target);
+ GOOGLE_DCHECK_EQ(end - target, size);
+ } else {
+ value.SerializeWithCachedSizes(output);
+ }
+ WriteTag(field_number, WIRETYPE_END_GROUP, output);
+}
+
+void WireFormatLite::WriteMessageMaybeToArray(int field_number,
+ const MessageLite& value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ const int size = value.GetCachedSize();
+ output->WriteVarint32(size);
+ uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
+ if (target != NULL) {
+ uint8* end = value.SerializeWithCachedSizesToArray(target);
+ GOOGLE_DCHECK_EQ(end - target, size);
+ } else {
+ value.SerializeWithCachedSizes(output);
+ }
+}
+
+bool WireFormatLite::ReadString(io::CodedInputStream* input,
+ string* value) {
+ // String is for UTF-8 text only
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ if (!input->InternalReadStringInline(value, length)) return false;
+ return true;
+}
+bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
+ string* value) {
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ return input->InternalReadStringInline(value, length);
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index 9b7a4010..e3d5b2d8 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -46,15 +46,18 @@
namespace google {
namespace protobuf {
+ template <typename T> class RepeatedField; // repeated_field.h
namespace io {
- class CodedInputStream; // coded_stream.h
- class CodedOutputStream; // coded_stream.h
+ class CodedInputStream; // coded_stream.h
+ class CodedOutputStream; // coded_stream.h
}
}
namespace protobuf {
namespace internal {
+class StringPieceField;
+
// This class is for internal use by the protocol buffer library and by
// protocol-complier-generated message classes. It must not be called
// directly by clients.
@@ -183,14 +186,21 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// required string message = 3;
// }
// }
+ static const int kMessageSetItemNumber = 1;
+ static const int kMessageSetTypeIdNumber = 2;
+ static const int kMessageSetMessageNumber = 3;
static const int kMessageSetItemStartTag =
- GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormatLite::WIRETYPE_START_GROUP);
+ GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
+ WireFormatLite::WIRETYPE_START_GROUP);
static const int kMessageSetItemEndTag =
- GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormatLite::WIRETYPE_END_GROUP);
+ GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
+ WireFormatLite::WIRETYPE_END_GROUP);
static const int kMessageSetTypeIdTag =
- GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(2, WireFormatLite::WIRETYPE_VARINT);
+ GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetTypeIdNumber,
+ WireFormatLite::WIRETYPE_VARINT);
static const int kMessageSetMessageTag =
- GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(3, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetMessageNumber,
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
// Byte size of all tags of a MessageSet::Item combined.
static const int kMessageSetItemTagsSize;
@@ -227,23 +237,59 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// Read fields, not including tags. The assumption is that you already
// read the tag to determine what field to read.
- static inline bool ReadInt32 (input, int32* value);
- static inline bool ReadInt64 (input, int64* value);
- static inline bool ReadUInt32 (input, uint32* value);
- static inline bool ReadUInt64 (input, uint64* value);
- static inline bool ReadSInt32 (input, int32* value);
- static inline bool ReadSInt64 (input, int64* value);
- static inline bool ReadFixed32 (input, uint32* value);
- static inline bool ReadFixed64 (input, uint64* value);
- static inline bool ReadSFixed32(input, int32* value);
- static inline bool ReadSFixed64(input, int64* value);
- static inline bool ReadFloat (input, float* value);
- static inline bool ReadDouble (input, double* value);
- static inline bool ReadBool (input, bool* value);
- static inline bool ReadEnum (input, int* value);
-
- static inline bool ReadString(input, string* value);
- static inline bool ReadBytes (input, string* value);
+
+ // For primitive fields, we just use a templatized routine parameterized by
+ // the represented type and the FieldType. These are specialized with the
+ // appropriate definition for each declared type.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline bool ReadPrimitive(input, CType* value) INL;
+
+ // Reads repeated primitive values, with optimizations for repeats.
+ // tag_size and tag should both be compile-time constants provided by the
+ // protocol compiler.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline bool ReadRepeatedPrimitive(int tag_size,
+ uint32 tag,
+ input,
+ RepeatedField<CType>* value) INL;
+
+ // Identical to ReadRepeatedPrimitive, except will not inline the
+ // implementation.
+ template <typename CType, enum FieldType DeclaredType>
+ static bool ReadRepeatedPrimitiveNoInline(int tag_size,
+ uint32 tag,
+ input,
+ RepeatedField<CType>* value);
+
+ // Reads a primitive value directly from the provided buffer. It returns a
+ // pointer past the segment of data that was read.
+ //
+ // This is only implemented for the types with fixed wire size, e.g.
+ // float, double, and the (s)fixed* types.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline const uint8* ReadPrimitiveFromArray(const uint8* buffer,
+ CType* value) INL;
+
+ // Reads a primitive packed field.
+ //
+ // This is only implemented for packable types.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline bool ReadPackedPrimitive(input,
+ RepeatedField<CType>* value) INL;
+
+ // Identical to ReadPackedPrimitive, except will not inline the
+ // implementation.
+ template <typename CType, enum FieldType DeclaredType>
+ static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value);
+
+ // Read a packed enum field. Values for which is_valid() returns false are
+ // dropped.
+ static bool ReadPackedEnumNoInline(input,
+ bool (*is_valid)(int),
+ RepeatedField<int>* value);
+
+ static bool ReadString(input, string* value);
+ static bool ReadBytes (input, string* value);
static inline bool ReadGroup (field_number, input, MessageLite* value);
static inline bool ReadMessage(input, MessageLite* value);
@@ -279,38 +325,44 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
static inline void WriteEnumNoTag (int value, output) INL;
// Write fields, including tags.
- static inline void WriteInt32 (field_number, int32 value, output) INL;
- static inline void WriteInt64 (field_number, int64 value, output) INL;
- static inline void WriteUInt32 (field_number, uint32 value, output) INL;
- static inline void WriteUInt64 (field_number, uint64 value, output) INL;
- static inline void WriteSInt32 (field_number, int32 value, output) INL;
- static inline void WriteSInt64 (field_number, int64 value, output) INL;
- static inline void WriteFixed32 (field_number, uint32 value, output) INL;
- static inline void WriteFixed64 (field_number, uint64 value, output) INL;
- static inline void WriteSFixed32(field_number, int32 value, output) INL;
- static inline void WriteSFixed64(field_number, int64 value, output) INL;
- static inline void WriteFloat (field_number, float value, output) INL;
- static inline void WriteDouble (field_number, double value, output) INL;
- static inline void WriteBool (field_number, bool value, output) INL;
- static inline void WriteEnum (field_number, int value, output) INL;
-
- static inline void WriteString(field_number, const string& value, output) INL;
- static inline void WriteBytes (field_number, const string& value, output) INL;
-
- static inline void WriteGroup(
- field_number, const MessageLite& value, output) INL;
- static inline void WriteMessage(
- field_number, const MessageLite& value, output) INL;
+ static void WriteInt32 (field_number, int32 value, output);
+ static void WriteInt64 (field_number, int64 value, output);
+ static void WriteUInt32 (field_number, uint32 value, output);
+ static void WriteUInt64 (field_number, uint64 value, output);
+ static void WriteSInt32 (field_number, int32 value, output);
+ static void WriteSInt64 (field_number, int64 value, output);
+ static void WriteFixed32 (field_number, uint32 value, output);
+ static void WriteFixed64 (field_number, uint64 value, output);
+ static void WriteSFixed32(field_number, int32 value, output);
+ static void WriteSFixed64(field_number, int64 value, output);
+ static void WriteFloat (field_number, float value, output);
+ static void WriteDouble (field_number, double value, output);
+ static void WriteBool (field_number, bool value, output);
+ static void WriteEnum (field_number, int value, output);
+
+ static void WriteString(field_number, const string& value, output);
+ static void WriteBytes (field_number, const string& value, output);
+
+ static void WriteGroup(
+ field_number, const MessageLite& value, output);
+ static void WriteMessage(
+ field_number, const MessageLite& value, output);
+ // Like above, but these will check if the output stream has enough
+ // space to write directly to a flat array.
+ static void WriteGroupMaybeToArray(
+ field_number, const MessageLite& value, output);
+ static void WriteMessageMaybeToArray(
+ field_number, const MessageLite& value, output);
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
// pointer must point at an instance of MessageType, *not* a subclass (or
// the subclass must not override SerializeWithCachedSizes()).
template<typename MessageType>
static inline void WriteGroupNoVirtual(
- field_number, const MessageType& value, output) INL;
+ field_number, const MessageType& value, output);
template<typename MessageType>
static inline void WriteMessageNoVirtual(
- field_number, const MessageType& value, output) INL;
+ field_number, const MessageType& value, output);
#undef output
#define output uint8* target
@@ -426,6 +478,16 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
static inline int MessageSizeNoVirtual(const MessageType& value);
private:
+ // A helper method for the repeated primitive reader. This method has
+ // optimizations for primitive types that have fixed size on the wire, and
+ // can be read using potentially faster paths.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline bool ReadRepeatedFixedSizePrimitive(
+ int tag_size,
+ uint32 tag,
+ google::protobuf::io::CodedInputStream* input,
+ RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
static const CppType kFieldTypeToCppTypeMap[];
static const WireFormatLite::WireType kWireTypeForFieldType[];
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index eb9155e9..d7b2c302 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -39,7 +39,9 @@
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message_lite.h>
+#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/io/coded_stream.h>
@@ -47,106 +49,295 @@ namespace google {
namespace protobuf {
namespace internal {
-inline bool WireFormatLite::ReadInt32(io::CodedInputStream* input,
- int32* value) {
+// Implementation details of ReadPrimitive.
+
+template <>
+inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(
+ io::CodedInputStream* input,
+ int32* value) {
uint32 temp;
if (!input->ReadVarint32(&temp)) return false;
*value = static_cast<int32>(temp);
return true;
}
-inline bool WireFormatLite::ReadInt64(io::CodedInputStream* input,
- int64* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_INT64>(
+ io::CodedInputStream* input,
+ int64* value) {
uint64 temp;
if (!input->ReadVarint64(&temp)) return false;
*value = static_cast<int64>(temp);
return true;
}
-inline bool WireFormatLite::ReadUInt32(io::CodedInputStream* input,
- uint32* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(
+ io::CodedInputStream* input,
+ uint32* value) {
return input->ReadVarint32(value);
}
-inline bool WireFormatLite::ReadUInt64(io::CodedInputStream* input,
- uint64* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_UINT64>(
+ io::CodedInputStream* input,
+ uint64* value) {
return input->ReadVarint64(value);
}
-inline bool WireFormatLite::ReadSInt32(io::CodedInputStream* input,
- int32* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(
+ io::CodedInputStream* input,
+ int32* value) {
uint32 temp;
if (!input->ReadVarint32(&temp)) return false;
*value = ZigZagDecode32(temp);
return true;
}
-inline bool WireFormatLite::ReadSInt64(io::CodedInputStream* input,
- int64* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SINT64>(
+ io::CodedInputStream* input,
+ int64* value) {
uint64 temp;
if (!input->ReadVarint64(&temp)) return false;
*value = ZigZagDecode64(temp);
return true;
}
-inline bool WireFormatLite::ReadFixed32(io::CodedInputStream* input,
- uint32* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_FIXED32>(
+ io::CodedInputStream* input,
+ uint32* value) {
return input->ReadLittleEndian32(value);
}
-inline bool WireFormatLite::ReadFixed64(io::CodedInputStream* input,
- uint64* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_FIXED64>(
+ io::CodedInputStream* input,
+ uint64* value) {
return input->ReadLittleEndian64(value);
}
-inline bool WireFormatLite::ReadSFixed32(io::CodedInputStream* input,
- int32* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SFIXED32>(
+ io::CodedInputStream* input,
+ int32* value) {
uint32 temp;
if (!input->ReadLittleEndian32(&temp)) return false;
*value = static_cast<int32>(temp);
return true;
}
-inline bool WireFormatLite::ReadSFixed64(io::CodedInputStream* input,
- int64* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SFIXED64>(
+ io::CodedInputStream* input,
+ int64* value) {
uint64 temp;
if (!input->ReadLittleEndian64(&temp)) return false;
*value = static_cast<int64>(temp);
return true;
}
-inline bool WireFormatLite::ReadFloat(io::CodedInputStream* input,
- float* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<float, WireFormatLite::TYPE_FLOAT>(
+ io::CodedInputStream* input,
+ float* value) {
uint32 temp;
if (!input->ReadLittleEndian32(&temp)) return false;
*value = DecodeFloat(temp);
return true;
}
-inline bool WireFormatLite::ReadDouble(io::CodedInputStream* input,
- double* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<double, WireFormatLite::TYPE_DOUBLE>(
+ io::CodedInputStream* input,
+ double* value) {
uint64 temp;
if (!input->ReadLittleEndian64(&temp)) return false;
*value = DecodeDouble(temp);
return true;
}
-inline bool WireFormatLite::ReadBool(io::CodedInputStream* input,
- bool* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>(
+ io::CodedInputStream* input,
+ bool* value) {
uint32 temp;
if (!input->ReadVarint32(&temp)) return false;
*value = temp != 0;
return true;
}
-inline bool WireFormatLite::ReadEnum(io::CodedInputStream* input,
- int* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ io::CodedInputStream* input,
+ int* value) {
uint32 temp;
if (!input->ReadVarint32(&temp)) return false;
*value = static_cast<int>(temp);
return true;
}
-inline bool WireFormatLite::ReadString(io::CodedInputStream* input,
- string* value) {
- // String is for UTF-8 text only
- uint32 length;
- if (!input->ReadVarint32(&length)) return false;
- if (!input->ReadString(value, length)) return false;
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ uint32, WireFormatLite::TYPE_FIXED32>(
+ const uint8* buffer,
+ uint32* value) {
+ return io::CodedInputStream::ReadLittleEndian32FromArray(buffer, value);
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ uint64, WireFormatLite::TYPE_FIXED64>(
+ const uint8* buffer,
+ uint64* value) {
+ return io::CodedInputStream::ReadLittleEndian64FromArray(buffer, value);
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ int32, WireFormatLite::TYPE_SFIXED32>(
+ const uint8* buffer,
+ int32* value) {
+ uint32 temp;
+ buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
+ *value = static_cast<int32>(temp);
+ return buffer;
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ int64, WireFormatLite::TYPE_SFIXED64>(
+ const uint8* buffer,
+ int64* value) {
+ uint64 temp;
+ buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
+ *value = static_cast<int64>(temp);
+ return buffer;
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ float, WireFormatLite::TYPE_FLOAT>(
+ const uint8* buffer,
+ float* value) {
+ uint32 temp;
+ buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
+ *value = DecodeFloat(temp);
+ return buffer;
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ double, WireFormatLite::TYPE_DOUBLE>(
+ const uint8* buffer,
+ double* value) {
+ uint64 temp;
+ buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
+ *value = DecodeDouble(temp);
+ return buffer;
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadRepeatedPrimitive(int tag_size,
+ uint32 tag,
+ io::CodedInputStream* input,
+ RepeatedField<CType>* values) {
+ CType value;
+ if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+ values->Add(value);
+ int elements_already_reserved = values->Capacity() - values->size();
+ while (elements_already_reserved > 0 && input->ExpectTag(tag)) {
+ if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+ values->AddAlreadyReserved(value);
+ elements_already_reserved--;
+ }
+ return true;
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive(
+ int tag_size,
+ uint32 tag,
+ io::CodedInputStream* input,
+ RepeatedField<CType>* values) {
+ GOOGLE_DCHECK_EQ(UInt32Size(tag), tag_size);
+ CType value;
+ if (!ReadPrimitive<CType, DeclaredType>(input, &value))
+ return false;
+ values->Add(value);
+
+ // For fixed size values, repeated values can be read more quickly by
+ // reading directly from a raw array.
+ //
+ // We can get a tight loop by only reading as many elements as can be
+ // added to the RepeatedField without having to do any resizing. Additionally,
+ // we only try to read as many elements as are available from the current
+ // buffer space. Doing so avoids having to perform boundary checks when
+ // reading the value: the maximum number of elements that can be read is
+ // known outside of the loop.
+ const void* void_pointer;
+ int size;
+ input->GetDirectBufferPointerInline(&void_pointer, &size);
+ if (size > 0) {
+ const uint8* buffer = reinterpret_cast<const uint8*>(void_pointer);
+ // The number of bytes each type occupies on the wire.
+ const int per_value_size = tag_size + sizeof(value);
+
+ int elements_available = min(values->Capacity() - values->size(),
+ size / per_value_size);
+ int num_read = 0;
+ while (num_read < elements_available &&
+ (buffer = io::CodedInputStream::ExpectTagFromArray(
+ buffer, tag)) != NULL) {
+ buffer = ReadPrimitiveFromArray<CType, DeclaredType>(buffer, &value);
+ values->AddAlreadyReserved(value);
+ ++num_read;
+ }
+ const int read_bytes = num_read * per_value_size;
+ if (read_bytes > 0) {
+ input->Skip(read_bytes);
+ }
+ }
return true;
}
-inline bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
- string* value) {
+
+// Specializations of ReadRepeatedPrimitive for the fixed size types, which use
+// the optimized code path.
+#define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \
+template <> \
+inline bool WireFormatLite::ReadRepeatedPrimitive< \
+ CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
+ int tag_size, \
+ uint32 tag, \
+ io::CodedInputStream* input, \
+ RepeatedField<CPPTYPE>* values) { \
+ return ReadRepeatedFixedSizePrimitive< \
+ CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
+ tag_size, tag, input, values); \
+}
+
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE);
+
+#undef READ_REPEATED_FIXED_SIZE_PRIMITIVE
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+bool WireFormatLite::ReadRepeatedPrimitiveNoInline(
+ int tag_size,
+ uint32 tag,
+ io::CodedInputStream* input,
+ RepeatedField<CType>* value) {
+ return ReadRepeatedPrimitive<CType, DeclaredType>(
+ tag_size, tag, input, value);
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input,
+ RepeatedField<CType>* values) {
uint32 length;
if (!input->ReadVarint32(&length)) return false;
- return input->ReadString(value, length);
+ io::CodedInputStream::Limit limit = input->PushLimit(length);
+ while (input->BytesUntilLimit() > 0) {
+ CType value;
+ if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+ values->Add(value);
+ }
+ input->PopLimit(limit);
+ return true;
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input,
+ RepeatedField<CType>* values) {
+ return ReadPackedPrimitive<CType, DeclaredType>(input, values);
}
@@ -270,107 +461,6 @@ inline void WireFormatLite::WriteEnumNoTag(int value,
output->WriteVarint32SignExtended(value);
}
-inline void WireFormatLite::WriteInt32(int field_number, int32 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_VARINT, output);
- WriteInt32NoTag(value, output);
-}
-inline void WireFormatLite::WriteInt64(int field_number, int64 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_VARINT, output);
- WriteInt64NoTag(value, output);
-}
-inline void WireFormatLite::WriteUInt32(int field_number, uint32 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_VARINT, output);
- WriteUInt32NoTag(value, output);
-}
-inline void WireFormatLite::WriteUInt64(int field_number, uint64 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_VARINT, output);
- WriteUInt64NoTag(value, output);
-}
-inline void WireFormatLite::WriteSInt32(int field_number, int32 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_VARINT, output);
- WriteSInt32NoTag(value, output);
-}
-inline void WireFormatLite::WriteSInt64(int field_number, int64 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_VARINT, output);
- WriteSInt64NoTag(value, output);
-}
-inline void WireFormatLite::WriteFixed32(int field_number, uint32 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_FIXED32, output);
- WriteFixed32NoTag(value, output);
-}
-inline void WireFormatLite::WriteFixed64(int field_number, uint64 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_FIXED64, output);
- WriteFixed64NoTag(value, output);
-}
-inline void WireFormatLite::WriteSFixed32(int field_number, int32 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_FIXED32, output);
- WriteSFixed32NoTag(value, output);
-}
-inline void WireFormatLite::WriteSFixed64(int field_number, int64 value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_FIXED64, output);
- WriteSFixed64NoTag(value, output);
-}
-inline void WireFormatLite::WriteFloat(int field_number, float value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_FIXED32, output);
- WriteFloatNoTag(value, output);
-}
-inline void WireFormatLite::WriteDouble(int field_number, double value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_FIXED64, output);
- WriteDoubleNoTag(value, output);
-}
-inline void WireFormatLite::WriteBool(int field_number, bool value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_VARINT, output);
- WriteBoolNoTag(value, output);
-}
-inline void WireFormatLite::WriteEnum(int field_number, int value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_VARINT, output);
- WriteEnumNoTag(value, output);
-}
-
-inline void WireFormatLite::WriteString(int field_number, const string& value,
- io::CodedOutputStream* output) {
- // String is for UTF-8 text only
- WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
- output->WriteVarint32(value.size());
- output->WriteString(value);
-}
-inline void WireFormatLite::WriteBytes(int field_number, const string& value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
- output->WriteVarint32(value.size());
- output->WriteString(value);
-}
-
-
-inline void WireFormatLite::WriteGroup(int field_number,
- const MessageLite& value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_START_GROUP, output);
- value.SerializeWithCachedSizes(output);
- WriteTag(field_number, WIRETYPE_END_GROUP, output);
-}
-inline void WireFormatLite::WriteMessage(int field_number,
- const MessageLite& value,
- io::CodedOutputStream* output) {
- WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
- output->WriteVarint32(value.GetCachedSize());
- value.SerializeWithCachedSizes(output);
-}
-
template<typename MessageType>
inline void WireFormatLite::WriteGroupNoVirtual(int field_number,
const MessageType& value,
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 51960ee7..867970c4 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -126,6 +126,38 @@ TEST(WireFormatTest, ParsePacked) {
TestUtil::ExpectPackedFieldsSet(dest);
}
+TEST(WireFormatTest, ParsePackedFromUnpacked) {
+ // Serialize using the generated code.
+ unittest::TestUnpackedTypes source;
+ TestUtil::SetUnpackedFields(&source);
+ string data = source.SerializeAsString();
+
+ // Parse using WireFormat.
+ unittest::TestPackedTypes dest;
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ WireFormat::ParseAndMergePartial(&input, &dest);
+
+ // Check.
+ TestUtil::ExpectPackedFieldsSet(dest);
+}
+
+TEST(WireFormatTest, ParseUnpackedFromPacked) {
+ // Serialize using the generated code.
+ unittest::TestPackedTypes source;
+ TestUtil::SetPackedFields(&source);
+ string data = source.SerializeAsString();
+
+ // Parse using WireFormat.
+ unittest::TestUnpackedTypes dest;
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ WireFormat::ParseAndMergePartial(&input, &dest);
+
+ // Check.
+ TestUtil::ExpectUnpackedFieldsSet(dest);
+}
+
TEST(WireFormatTest, ParsePackedExtensions) {
unittest::TestPackedExtensions source, dest;
string data;
@@ -568,6 +600,45 @@ TEST(WireFormatTest, ZigZag) {
LL(-75123905439571256))));
}
+TEST(WireFormatTest, RepeatedScalarsDifferentTagSizes) {
+ // At one point checks would trigger when parsing repeated fixed scalar
+ // fields.
+ protobuf_unittest::TestRepeatedScalarDifferentTagSizes msg1, msg2;
+ for (int i = 0; i < 100; ++i) {
+ msg1.add_repeated_fixed32(i);
+ msg1.add_repeated_int32(i);
+ msg1.add_repeated_fixed64(i);
+ msg1.add_repeated_int64(i);
+ msg1.add_repeated_float(i);
+ msg1.add_repeated_uint64(i);
+ }
+
+ // Make sure that we have a variety of tag sizes.
+ const google::protobuf::Descriptor* desc = msg1.GetDescriptor();
+ const google::protobuf::FieldDescriptor* field;
+ field = desc->FindFieldByName("repeated_fixed32");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(1, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_int32");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(1, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_fixed64");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(2, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_int64");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(2, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_float");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(3, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_uint64");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(3, WireFormat::TagSize(field->number(), field->type()));
+
+ EXPECT_TRUE(msg2.ParseFromString(msg1.SerializeAsString()));
+ EXPECT_EQ(msg1.DebugString(), msg2.DebugString());
+}
+
class WireFormatInvalidInputTest : public testing::Test {
protected:
// Make a serialized TestAllTypes in which the field optional_nested_message