aboutsummaryrefslogtreecommitdiffstats
path: root/src/google/protobuf/compiler
diff options
context:
space:
mode:
authorWink Saville <wink@google.com>2010-05-29 13:00:38 -0700
committerWink Saville <wink@google.com>2010-05-29 13:00:38 -0700
commitd0332953cda33fb4f8e24ebff9c49159b69c43d6 (patch)
tree81612e8b12f590310aeb0ebf1da37b304eb7baa6 /src/google/protobuf/compiler
parentede38fe9b9f93888e6e41afc7abb09525f44da95 (diff)
downloadexternal_protobuf-d0332953cda33fb4f8e24ebff9c49159b69c43d6.zip
external_protobuf-d0332953cda33fb4f8e24ebff9c49159b69c43d6.tar.gz
external_protobuf-d0332953cda33fb4f8e24ebff9c49159b69c43d6.tar.bz2
Add protobuf 2.3.0 sources
This is the contents of protobuf-2.3.0.tar.bz2 from http://code.google.com/p/protobuf/downloads/list. Change-Id: Idfde09ce7ef5ac027b07ee83f2674fbbed5c30b2
Diffstat (limited to 'src/google/protobuf/compiler')
-rw-r--r--src/google/protobuf/compiler/code_generator.cc9
-rw-r--r--src/google/protobuf/compiler/code_generator.h13
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc687
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h71
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc654
-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.cc108
-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_plugin_unittest.cc121
-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/importer.cc1
-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.cc65
-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.cc96
-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_plugin_unittest.cc121
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc48
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.h3
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_enum.cc96
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc333
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_enum_field.h94
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_field.cc102
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_file.cc251
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_generator.cc209
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_helpers.cc381
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_helpers.h128
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_message.cc474
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_message.h93
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_message_field.cc302
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_message_field.h95
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_params.h143
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc660
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_primitive_field.h94
-rw-r--r--src/google/protobuf/compiler/main.cc7
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.cc209
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.h108
-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/plugin.cc152
-rw-r--r--src/google/protobuf/compiler/plugin.h (renamed from src/google/protobuf/compiler/javamicro/javamicro_file.h)77
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc1084
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h727
-rw-r--r--src/google/protobuf/compiler/plugin.proto145
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc235
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h16
-rw-r--r--src/google/protobuf/compiler/python/python_plugin_unittest.cc116
-rw-r--r--src/google/protobuf/compiler/subprocess.cc458
-rw-r--r--src/google/protobuf/compiler/subprocess.h (renamed from src/google/protobuf/compiler/javamicro/javamicro_field.h)97
-rw-r--r--src/google/protobuf/compiler/test_plugin.cc (renamed from src/google/protobuf/compiler/javamicro/javamicro_enum.h)70
-rwxr-xr-xsrc/google/protobuf/compiler/zip_output_unittest.sh85
-rw-r--r--src/google/protobuf/compiler/zip_writer.cc188
-rw-r--r--src/google/protobuf/compiler/zip_writer.h (renamed from src/google/protobuf/compiler/javamicro/javamicro_generator.h)47
75 files changed, 5594 insertions, 4402 deletions
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 0def84d..3413a36 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 8a7081f..ea094cd 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -98,11 +98,20 @@ class LIBPROTOC_EXPORT OutputDirectory {
//
// The filename given should be relative to the root of the source tree.
// E.g. the C++ generator, when generating code for "foo/bar.proto", will
- // generate the files "foo/bar.pb2.h" and "foo/bar.pb2.cc"; note that
+ // generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that
// "foo/" is included in these filenames. The filename is not allowed to
// 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 (plugin.pb.h) for more
+ // information on insertion points. The default implementation
+ // assert-fails -- it exists only for backwards-compatibility.
+ //
+ // WARNING: This feature is currently EXPERIMENTAL and is subject to change.
+ virtual io::ZeroCopyOutputStream* OpenForInsert(
+ const string& filename, const string& insertion_point);
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory);
};
@@ -114,7 +123,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 3629f68..d3495ca 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,22 @@
#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/compiler/zip_writer.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>
+#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/hash.h>
namespace google {
@@ -126,6 +135,47 @@ void SetFdToBinaryMode(int fd) {
// (Text and binary are the same on non-Windows platforms.)
}
+void AddTrailingSlash(string* path) {
+ if (!path->empty() && path->at(path->size() - 1) != '/') {
+ path->push_back('/');
+ }
+}
+
+bool VerifyDirectoryExists(const string& path) {
+ if (path.empty()) return true;
+
+ if (access(path.c_str(), W_OK) == -1) {
+ cerr << path << ": " << strerror(errno) << endl;
+ return false;
+ } else {
+ return true;
+ }
+}
+
+// Try to create the parent directory of the given file, creating the parent's
+// parent if necessary, and so on. The full file name is actually
+// (prefix + filename), but we assume |prefix| already exists and only create
+// directories listed in |filename|.
+bool TryCreateParentDirectory(const string& prefix, const string& filename) {
+ // Recursively create parent directories to the output file.
+ vector<string> parts;
+ SplitStringUsing(filename, "/", &parts);
+ string path_so_far = prefix;
+ for (int i = 0; i < parts.size() - 1; i++) {
+ path_so_far += parts[i];
+ if (mkdir(path_so_far.c_str(), 0777) != 0) {
+ if (errno != EEXIST) {
+ cerr << filename << ": while trying to create directory "
+ << path_so_far << ": " << strerror(errno) << endl;
+ return false;
+ }
+ }
+ path_so_far += '/';
+ }
+
+ return true;
+}
+
} // namespace
// A MultiFileErrorCollector that prints errors to stderr.
@@ -169,72 +219,142 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
// -------------------------------------------------------------------
-// An OutputDirectory implementation that writes to disk.
-class CommandLineInterface::DiskOutputDirectory : public OutputDirectory {
+// An OutputDirectory implementation that buffers files in memory, then dumps
+// them all to disk on demand.
+class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory {
public:
- DiskOutputDirectory(const string& root);
- ~DiskOutputDirectory();
+ MemoryOutputDirectory();
+ ~MemoryOutputDirectory();
+
+ // Write all files in the directory to disk at the given output location,
+ // which must end in a '/'.
+ bool WriteAllToDisk(const string& prefix);
- bool VerifyExistence();
+ // Write the contents of this directory to a ZIP-format archive with the
+ // given name.
+ bool WriteAllToZip(const string& filename);
- inline bool had_error() { return had_error_; }
- inline void set_had_error(bool value) { had_error_ = value; }
+ // Add a boilerplate META-INF/MANIFEST.MF file as required by the Java JAR
+ // format, unless one has already been written.
+ void AddJarManifest();
// implements OutputDirectory --------------------------------------
io::ZeroCopyOutputStream* Open(const string& filename);
+ io::ZeroCopyOutputStream* OpenForInsert(
+ const string& filename, const string& insertion_point);
private:
- string root_;
+ friend class MemoryOutputStream;
+
+ // map instead of hash_map so that files are written in order (good when
+ // writing zips).
+ map<string, string*> files_;
bool had_error_;
};
-// A FileOutputStream that checks for errors in the destructor and reports
-// them. We extend FileOutputStream via wrapping rather than inheritance
-// for two reasons:
-// 1) Implementation inheritance is evil.
-// 2) We need to close the file descriptor *after* the FileOutputStream's
-// destructor is run to make sure it flushes the file contents.
-class CommandLineInterface::ErrorReportingFileOutput
+class CommandLineInterface::MemoryOutputStream
: public io::ZeroCopyOutputStream {
public:
- ErrorReportingFileOutput(int file_descriptor,
- const string& filename,
- DiskOutputDirectory* directory);
- ~ErrorReportingFileOutput();
+ MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename);
+ MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename,
+ const string& insertion_point);
+ virtual ~MemoryOutputStream();
// implements ZeroCopyOutputStream ---------------------------------
- bool Next(void** data, int* size) { return file_stream_->Next(data, size); }
- void BackUp(int count) { file_stream_->BackUp(count); }
- int64 ByteCount() const { return file_stream_->ByteCount(); }
+ virtual bool Next(void** data, int* size) { return inner_->Next(data, size); }
+ virtual void BackUp(int count) { inner_->BackUp(count); }
+ virtual int64 ByteCount() const { return inner_->ByteCount(); }
private:
- scoped_ptr<io::FileOutputStream> file_stream_;
- int file_descriptor_;
+ // Where to insert the string when it's done.
+ MemoryOutputDirectory* directory_;
string filename_;
- DiskOutputDirectory* directory_;
+ string insertion_point_;
+
+ // The string we're building.
+ string data_;
+
+ // StringOutputStream writing to data_.
+ scoped_ptr<io::StringOutputStream> inner_;
};
// -------------------------------------------------------------------
-CommandLineInterface::DiskOutputDirectory::DiskOutputDirectory(
- const string& root)
- : root_(root), had_error_(false) {
- // Add a '/' to the end if it doesn't already have one. But don't add a
- // '/' to an empty string since this probably means the current directory.
- if (!root_.empty() && root[root_.size() - 1] != '/') {
- root_ += '/';
- }
-}
+CommandLineInterface::MemoryOutputDirectory::MemoryOutputDirectory()
+ : had_error_(false) {}
-CommandLineInterface::DiskOutputDirectory::~DiskOutputDirectory() {
+CommandLineInterface::MemoryOutputDirectory::~MemoryOutputDirectory() {
+ STLDeleteValues(&files_);
}
-bool CommandLineInterface::DiskOutputDirectory::VerifyExistence() {
- if (!root_.empty()) {
- // Make sure the directory exists. If it isn't a directory, this will fail
- // because we added a '/' to the end of the name in the constructor.
- if (access(root_.c_str(), W_OK) == -1) {
- cerr << root_ << ": " << strerror(errno) << endl;
+bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk(
+ const string& prefix) {
+ if (had_error_) {
+ return false;
+ }
+
+ if (!VerifyDirectoryExists(prefix)) {
+ return false;
+ }
+
+ for (map<string, string*>::const_iterator iter = files_.begin();
+ iter != files_.end(); ++iter) {
+ const string& relative_filename = iter->first;
+ const char* data = iter->second->data();
+ int size = iter->second->size();
+
+ if (!TryCreateParentDirectory(prefix, relative_filename)) {
+ return false;
+ }
+ string filename = prefix + relative_filename;
+
+ // Create the output file.
+ int file_descriptor;
+ do {
+ file_descriptor =
+ open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ } while (file_descriptor < 0 && errno == EINTR);
+
+ if (file_descriptor < 0) {
+ int error = errno;
+ cerr << filename << ": " << strerror(error);
+ return false;
+ }
+
+ // Write the file.
+ while (size > 0) {
+ int write_result;
+ do {
+ write_result = write(file_descriptor, data, size);
+ } while (write_result < 0 && errno == EINTR);
+
+ if (write_result <= 0) {
+ // Write error.
+
+ // FIXME(kenton): According to the man page, if write() returns zero,
+ // there was no error; write() simply did not write anything. It's
+ // unclear under what circumstances this might happen, but presumably
+ // errno won't be set in this case. I am confused as to how such an
+ // event should be handled. For now I'm treating it as an error,
+ // since retrying seems like it could lead to an infinite loop. I
+ // suspect this never actually happens anyway.
+
+ if (write_result < 0) {
+ int error = errno;
+ cerr << filename << ": write: " << strerror(error);
+ } else {
+ cerr << filename << ": write() returned zero?" << endl;
+ }
+ return false;
+ }
+
+ data += write_result;
+ size -= write_result;
+ }
+
+ if (close(file_descriptor) != 0) {
+ int error = errno;
+ cerr << filename << ": close: " << strerror(error);
return false;
}
}
@@ -242,65 +362,183 @@ bool CommandLineInterface::DiskOutputDirectory::VerifyExistence() {
return true;
}
-io::ZeroCopyOutputStream* CommandLineInterface::DiskOutputDirectory::Open(
+bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip(
const string& filename) {
- // Recursively create parent directories to the output file.
- vector<string> parts;
- SplitStringUsing(filename, "/", &parts);
- string path_so_far = root_;
- for (int i = 0; i < parts.size() - 1; i++) {
- path_so_far += parts[i];
- if (mkdir(path_so_far.c_str(), 0777) != 0) {
- if (errno != EEXIST) {
- cerr << filename << ": while trying to create directory "
- << path_so_far << ": " << strerror(errno) << endl;
- had_error_ = true;
- // Return a dummy stream.
- return new io::ArrayOutputStream(NULL, 0);
- }
- }
- path_so_far += '/';
+ if (had_error_) {
+ return false;
}
// Create the output file.
int file_descriptor;
do {
file_descriptor =
- open((root_ + filename).c_str(),
- O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
} while (file_descriptor < 0 && errno == EINTR);
if (file_descriptor < 0) {
- // Failed to open.
- cerr << filename << ": " << strerror(errno) << endl;
- had_error_ = true;
- // Return a dummy stream.
- return new io::ArrayOutputStream(NULL, 0);
+ int error = errno;
+ cerr << filename << ": " << strerror(error);
+ return false;
}
- return new ErrorReportingFileOutput(file_descriptor, filename, this);
-}
+ // Create the ZipWriter
+ io::FileOutputStream stream(file_descriptor);
+ ZipWriter zip_writer(&stream);
+
+ for (map<string, string*>::const_iterator iter = files_.begin();
+ iter != files_.end(); ++iter) {
+ zip_writer.Write(iter->first, *iter->second);
+ }
+
+ zip_writer.WriteDirectory();
+
+ if (stream.GetErrno() != 0) {
+ cerr << filename << ": " << strerror(stream.GetErrno()) << endl;
+ }
-CommandLineInterface::ErrorReportingFileOutput::ErrorReportingFileOutput(
- int file_descriptor,
- const string& filename,
- DiskOutputDirectory* directory)
- : file_stream_(new io::FileOutputStream(file_descriptor)),
- file_descriptor_(file_descriptor),
- filename_(filename),
- directory_(directory) {}
+ if (!stream.Close()) {
+ cerr << filename << ": " << strerror(stream.GetErrno()) << endl;
+ }
+
+ return true;
+}
-CommandLineInterface::ErrorReportingFileOutput::~ErrorReportingFileOutput() {
- // Check if we had any errors while writing.
- if (file_stream_->GetErrno() != 0) {
- cerr << filename_ << ": " << strerror(file_stream_->GetErrno()) << endl;
- directory_->set_had_error(true);
+void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() {
+ string** map_slot = &files_["META-INF/MANIFEST.MF"];
+ if (*map_slot == NULL) {
+ *map_slot = new string(
+ "Manifest-Version: 1.0\n"
+ "Created-By: 1.6.0 (protoc)\n"
+ "\n");
}
+}
+
+io::ZeroCopyOutputStream* CommandLineInterface::MemoryOutputDirectory::Open(
+ const string& filename) {
+ return new MemoryOutputStream(this, filename);
+}
+
+io::ZeroCopyOutputStream*
+CommandLineInterface::MemoryOutputDirectory::OpenForInsert(
+ const string& filename, const string& insertion_point) {
+ return new MemoryOutputStream(this, filename, insertion_point);
+}
+
+// -------------------------------------------------------------------
+
+CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
+ MemoryOutputDirectory* directory, const string& filename)
+ : directory_(directory),
+ filename_(filename),
+ inner_(new io::StringOutputStream(&data_)) {
+}
+
+CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
+ MemoryOutputDirectory* directory, const string& filename,
+ const string& insertion_point)
+ : directory_(directory),
+ filename_(filename),
+ insertion_point_(insertion_point),
+ inner_(new io::StringOutputStream(&data_)) {
+}
+
+CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
+ // Make sure all data has been written.
+ inner_.reset();
- // Close the file stream.
- if (!file_stream_->Close()) {
- cerr << filename_ << ": " << strerror(file_stream_->GetErrno()) << endl;
- directory_->set_had_error(true);
+ // Insert into the directory.
+ string** map_slot = &directory_->files_[filename_];
+
+ if (insertion_point_.empty()) {
+ // This was just a regular Open().
+ if (*map_slot != NULL) {
+ cerr << filename_ << ": Tried to write the same file twice." << endl;
+ directory_->had_error_ = true;
+ return;
+ }
+
+ *map_slot = new string;
+ (*map_slot)->swap(data_);
+ } else {
+ // This was an OpenForInsert().
+
+ // If the data doens't end with a clean line break, add one.
+ if (!data_.empty() && data_[data_.size() - 1] != '\n') {
+ data_.push_back('\n');
+ }
+
+ // Find the file we are going to insert into.
+ if (*map_slot == NULL) {
+ cerr << filename_ << ": Tried to insert into file that doesn't exist."
+ << endl;
+ directory_->had_error_ = true;
+ return;
+ }
+ string* target = *map_slot;
+
+ // Find the insertion point.
+ string magic_string = strings::Substitute(
+ "@@protoc_insertion_point($0)", insertion_point_);
+ string::size_type pos = target->find(magic_string);
+
+ if (pos == string::npos) {
+ cerr << filename_ << ": insertion point \"" << insertion_point_
+ << "\" not found." << endl;
+ directory_->had_error_ = true;
+ return;
+ }
+
+ // Seek backwards to the beginning of the line, which is where we will
+ // insert the data. Note that this has the effect of pushing the insertion
+ // point down, so the data is inserted before it. This is intentional
+ // because it means that multiple insertions at the same point will end
+ // up in the expected order in the final output.
+ pos = target->find_last_of('\n', pos);
+ if (pos == string::npos) {
+ // Insertion point is on the first line.
+ pos = 0;
+ } else {
+ // Advance to character after '\n'.
+ ++pos;
+ }
+
+ // Extract indent.
+ string indent_(*target, pos, target->find_first_not_of(" \t", pos) - pos);
+
+ if (indent_.empty()) {
+ // No indent. This makes things easier.
+ target->insert(pos, data_);
+ } else {
+ // Calculate how much space we need.
+ int indent_size = 0;
+ for (int i = 0; i < data_.size(); i++) {
+ if (data_[i] == '\n') indent_size += indent_.size();
+ }
+
+ // Make a hole for it.
+ target->insert(pos, data_.size() + indent_size, '\0');
+
+ // Now copy in the data.
+ string::size_type data_pos = 0;
+ char* target_ptr = string_as_array(target) + pos;
+ while (data_pos < data_.size()) {
+ // Copy indent.
+ memcpy(target_ptr, indent_.data(), indent_.size());
+ target_ptr += indent_.size();
+
+ // Copy line from data_.
+ // We already guaranteed that data_ ends with a newline (above), so this
+ // search can't fail.
+ string::size_type line_length =
+ data_.find_first_of('\n', data_pos) + 1 - data_pos;
+ memcpy(target_ptr, data_.data() + data_pos, line_length);
+ target_ptr += line_length;
+ data_pos += line_length;
+ }
+
+ GOOGLE_CHECK_EQ(target_ptr,
+ string_as_array(target) + pos + data_.size() + indent_size);
+ }
}
}
@@ -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,17 +601,60 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
"--disallow_services was used." << endl;
return 1;
}
+ }
+
+ // We construct a separate OutputDirectory for each output location. Note
+ // that two code generators may output to the same location, in which case
+ // they should share a single OutputDirectory (so that OpenForInsert() works).
+ typedef hash_map<string, MemoryOutputDirectory*> OutputDirectoryMap;
+ OutputDirectoryMap output_directories;
+
+ // Generate output.
+ if (mode_ == MODE_COMPILE) {
+ for (int i = 0; i < output_directives_.size(); i++) {
+ string output_location = output_directives_[i].output_location;
+ if (!HasSuffixString(output_location, ".zip") &&
+ !HasSuffixString(output_location, ".jar")) {
+ AddTrailingSlash(&output_location);
+ }
+ MemoryOutputDirectory** map_slot = &output_directories[output_location];
+
+ if (*map_slot == NULL) {
+ // First time we've seen this output location.
+ *map_slot = new MemoryOutputDirectory;
+ }
+
+ if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) {
+ STLDeleteValues(&output_directories);
+ 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;
- }
+ // Write all output to disk.
+ for (OutputDirectoryMap::iterator iter = output_directories.begin();
+ iter != output_directories.end(); ++iter) {
+ const string& location = iter->first;
+ MemoryOutputDirectory* directory = iter->second;
+ if (HasSuffixString(location, "/")) {
+ if (!directory->WriteAllToDisk(location)) {
+ STLDeleteValues(&output_directories);
+ return 1;
+ }
+ } else {
+ if (HasSuffixString(location, ".jar")) {
+ directory->AddJarManifest();
+ }
+
+ if (!directory->WriteAllToZip(location)) {
+ STLDeleteValues(&output_directories);
+ return 1;
}
}
}
+ STLDeleteValues(&output_directories);
+
if (!descriptor_set_name_.empty()) {
if (!WriteDescriptorSet(parsed_files)) {
return 1;
@@ -439,7 +724,11 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative(
} else {
cerr << input_files_[i] << ": File does not reside within any path "
"specified using --proto_path (or -I). You must specify a "
- "--proto_path which encompasses this file." << endl;
+ "--proto_path which encompasses this file. Note that the "
+ "proto_path must be an exact prefix of the .proto file "
+ "names -- protoc is too dumb to figure out when two paths "
+ "(e.g. absolute and relative) are equivalent (it's harder "
+ "than you think)." << endl;
}
return false;
}
@@ -682,10 +971,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;
}
@@ -699,7 +1015,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
@@ -751,6 +1071,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) {
@@ -764,28 +1095,116 @@ void CommandLineInterface::PrintHelpText() {
}
bool CommandLineInterface::GenerateOutput(
- const FileDescriptor* parsed_file,
- const OutputDirective& output_directive) {
- // Create the output directory.
- DiskOutputDirectory output_directory(output_directive.output_location);
- if (!output_directory.VerifyExistence()) {
- return false;
+ const vector<const FileDescriptor*>& parsed_files,
+ const OutputDirective& output_directive,
+ OutputDirectory* output_directory) {
+ // Call the generator.
+ string error;
+ 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;
+ }
+ }
}
- // Opened successfully. Write it.
+ return true;
+}
- // 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;
+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;
}
- // Check for write errors.
- if (output_directory.had_error()) {
+ // 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;
}
@@ -858,22 +1277,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());
}
}
@@ -902,6 +1315,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 ec65863..d25a50e 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().
//
@@ -140,8 +174,8 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// -----------------------------------------------------------------
class ErrorPrinter;
- class DiskOutputDirectory;
- class ErrorReportingFileOutput;
+ class MemoryOutputDirectory;
+ class MemoryOutputStream;
// Clear state from previous Run().
void Clear();
@@ -176,8 +210,14 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Generate the given output file from the given input.
struct OutputDirective; // see below
- bool GenerateOutput(const FileDescriptor* proto_file,
- const OutputDirective& output_directive);
+ bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
+ const OutputDirective& output_directive,
+ OutputDirectory* output_directory);
+ 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 719771e..9129ebf 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>
@@ -66,6 +68,9 @@ namespace compiler {
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
+#ifndef F_OK
+#define F_OK 00 // not defined by MSVC for whatever reason
+#endif
#endif
namespace {
@@ -83,28 +88,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 +126,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 +137,19 @@ 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 ExpectNullCodeGeneratorCalled(const string& parameter);
void ReadDescriptorSet(const string& filename,
FileDescriptorSet* descriptor_set);
@@ -150,6 +158,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
@@ -164,40 +175,8 @@ class CommandLineInterfaceTest : public testing::Test {
// Pointers which need to be deleted later.
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_;
+ NullCodeGenerator* null_generator_;
};
class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator {
@@ -237,6 +216,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 = null_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 +249,44 @@ void CommandLineInterfaceTest::Run(const string& command) {
vector<string> args;
SplitStringUsing(command, " ", &args);
+ if (!disallow_plugins_) {
+ cli_.AllowPlugins("prefix-");
+
+ const char* possible_paths[] = {
+ // When building with shared libraries, libtool hides the real executable
+ // in .libs and puts a fake wrapper in the current directory.
+ // Unfortunately, due to an apparent bug on Cygwin/MinGW, if one program
+ // wrapped in this way (e.g. protobuf-tests.exe) tries to execute another
+ // program wrapped in this way (e.g. test_plugin.exe), the latter fails
+ // with error code 127 and no explanation message. Presumably the problem
+ // is that the wrapper for protobuf-tests.exe set some environment
+ // variables that confuse the wrapper for test_plugin.exe. Luckily, it
+ // turns out that if we simply invoke the wrapped test_plugin.exe
+ // directly, it works -- I guess the environment variables set by the
+ // protobuf-tests.exe wrapper happen to be correct for it too. So we do
+ // that.
+ ".libs/test_plugin.exe", // Win32 w/autotool (Cygwin / MinGW)
+ "test_plugin.exe", // Other Win32 (MSVC)
+ "test_plugin", // Unix
+ };
+
+ string plugin_path;
+
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(possible_paths); i++) {
+ if (access(possible_paths[i], F_OK) == 0) {
+ plugin_path = possible_paths[i];
+ break;
+ }
+ }
+
+ if (plugin_path.empty()) {
+ GOOGLE_LOG(ERROR)
+ << "Plugin executable not found. Plugin tests are likely to fail.";
+ } else {
+ args.push_back("--plugin=prefix-gen-plug=" + plugin_path);
+ }
+ }
+
scoped_array<const char*> argv(new const char*[args.size()]);
for (int i = 0; i < args.size(); i++) {
@@ -270,44 +303,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 +318,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 +351,37 @@ 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::ExpectNullCodeGeneratorCalled(
+ const string& parameter) {
+ EXPECT_TRUE(null_generator_->called_);
+ EXPECT_EQ(parameter, null_generator_->parameter_);
}
void CommandLineInterfaceTest::ReadDescriptorSet(
@@ -383,77 +398,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");
+
+ Run("protocol_compiler --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
+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 +451,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", "output.test");
+ 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();
+ 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,42 +520,33 @@ 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();
- EXPECT_TRUE(generator->called_);
- EXPECT_EQ("", generator->parameter_);
+ ExpectNullCodeGeneratorCalled("");
}
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();
- EXPECT_TRUE(generator->called_);
- EXPECT_EQ("bar", generator->parameter_);
+ ExpectNullCodeGeneratorCalled("bar");
}
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 +555,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 +563,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 +578,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 +608,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 +622,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 +658,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 +678,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 +687,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 +695,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 +703,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) {
@@ -775,8 +750,8 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
if (HasFatalFailure()) return;
ASSERT_EQ(2, descriptor_set.file_size());
if (descriptor_set.file(0).name() == "bar.proto") {
- swap(descriptor_set.mutable_file()->mutable_data()[0],
- descriptor_set.mutable_file()->mutable_data()[1]);
+ std::swap(descriptor_set.mutable_file()->mutable_data()[0],
+ descriptor_set.mutable_file()->mutable_data()[1]);
}
EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
@@ -787,9 +762,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 +776,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 +803,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 +816,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 +829,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");
@@ -882,7 +842,11 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) {
ExpectErrorText(
"$tmpdir/foo.proto: File does not reside within any path "
"specified using --proto_path (or -I). You must specify a "
- "--proto_path which encompasses this file.\n");
+ "--proto_path which encompasses this file. Note that the "
+ "proto_path must be an exact prefix of the .proto file "
+ "names -- protoc is too dumb to figure out when two paths "
+ "(e.g. absolute and relative) are equivalent (it's harder "
+ "than you think).\n");
}
TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) {
@@ -891,9 +855,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", "");
@@ -910,9 +871,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");
@@ -934,9 +892,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");
@@ -948,9 +903,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");
@@ -958,9 +910,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");
@@ -971,35 +920,59 @@ 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");
+ // MockCodeGenerator no longer detects an error because we actually write to
+ // an in-memory location first, then dump to disk at the end. This is no
+ // big deal.
+ // 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");
@@ -1007,14 +980,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");
@@ -1033,45 +1013,124 @@ 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.");
+
+#ifdef _WIN32
+ // Windows doesn't have signals. It looks like abort()ing causes the process
+ // to exit with status code 3, but let's not depend on the exact number here.
+ ExpectErrorSubstring(
+ "--plug_out: prefix-gen-plug: Plugin failed with status code");
+#else
+ // Don't depend on the exact signal number.
+ ExpectErrorSubstring(
+ "--plug_out: prefix-gen-plug: Plugin killed by signal");
+#endif
+}
+
+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");
+
+#ifdef _WIN32
+ ExpectErrorSubstring(
+ "--badplug_out: prefix-gen-badplug: The system cannot find the file "
+ "specified.");
+#else
+ // Error written to stdout by child process after exec() fails.
+ ExpectErrorSubstring(
+ "no_such_file: program not found or is not executable");
+
+ // Error written by parent process when child fails.
+ ExpectErrorSubstring(
+ "--badplug_out: prefix-gen-badplug: Plugin failed with status code 1.");
+#endif
+}
+
+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");
@@ -1086,9 +1145,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");
@@ -1104,9 +1160,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");
@@ -1124,9 +1177,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");
@@ -1135,15 +1185,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");
@@ -1152,16 +1199,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");
@@ -1170,15 +1214,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");
@@ -1188,9 +1229,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 a7bc35b..30b1d2b 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 90e9172..76d2b79 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 7ca11c8..91ce493 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 20dd57b..0793430 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 7208ed3..658a707 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 c546e96..103cac4 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 00ec2c7..c303a33 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 51859bb..80da7e4 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 723a8b4..e3df88b 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 83e1250..f99b5fe 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 ae243dd..cbdcce8 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,12 +843,16 @@ GenerateSharedDestructorCode(io::Printer* printer) {
void MessageGenerator::
GenerateStructors(io::Printer* printer) {
+ string superclass = SuperClassName(descriptor_);
+
// Generate the default constructor.
printer->Print(
- "$classname$::$classname$() {\n"
+ "$classname$::$classname$()\n"
+ " : $superclass$() {\n"
" SharedCtor();\n"
"}\n",
- "classname", classname_);
+ "classname", classname_,
+ "superclass", superclass);
printer->Print(
"\n"
@@ -859,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(
@@ -868,12 +882,14 @@ GenerateStructors(io::Printer* printer) {
// Generate the copy constructor.
printer->Print(
- "$classname$::$classname$(const $classname$& from) {\n"
+ "$classname$::$classname$(const $classname$& from)\n"
+ " : $superclass$() {\n"
" SharedCtor();\n"
" MergeFrom(from);\n"
"}\n"
"\n",
- "classname", classname_);
+ "classname", classname_,
+ "superclass", superclass);
// Generate the shared constructor code.
GenerateSharedConstructorCode(printer);
@@ -889,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()) {
@@ -917,6 +942,7 @@ GenerateStructors(io::Printer* printer) {
"classname", classname_,
"adddescriptorsname",
GlobalAddDescriptorsName(descriptor_->file()->name()));
+
}
void MessageGenerator::
@@ -1230,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())) {
@@ -1245,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.
@@ -1427,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();
@@ -1548,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;
@@ -1640,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();
@@ -1712,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 f1c5714..04778f6 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 059fba6..c04bdc6 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_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
new file mode 100644
index 0000000..440b716
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -0,0 +1,121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// TODO(kenton): Share code with the versions of this test in other languages?
+// It seemed like parameterizing it would add more complexity than it is
+// worth.
+
+#include <google/protobuf/compiler/cpp/cpp_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+ TestGenerator() {}
+ ~TestGenerator() {}
+
+ virtual bool Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const {
+ TryInsert("test.pb.h", "includes", output_directory);
+ TryInsert("test.pb.h", "namespace_scope", output_directory);
+ TryInsert("test.pb.h", "global_scope", output_directory);
+ TryInsert("test.pb.h", "class_scope:foo.Bar", output_directory);
+ TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", output_directory);
+
+ TryInsert("test.pb.cc", "includes", output_directory);
+ TryInsert("test.pb.cc", "namespace_scope", output_directory);
+ TryInsert("test.pb.cc", "global_scope", output_directory);
+ return true;
+ }
+
+ void TryInsert(const string& filename, const string& insertion_point,
+ OutputDirectory* output_directory) const {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->OpenForInsert(filename, insertion_point));
+ io::Printer printer(output.get(), '$');
+ printer.Print("// inserted $name$\n", "name", insertion_point);
+ }
+};
+
+// This test verifies that all the expected insertion points exist. It does
+// not verify that they are correctly-placed; that would require actually
+// compiling the output which is a bit more than I care to do for this test.
+TEST(CppPluginTest, PluginTest) {
+ File::WriteStringToFileOrDie(
+ "syntax = \"proto2\";\n"
+ "package foo;\n"
+ "message Bar {\n"
+ " message Baz {}\n"
+ "}\n",
+ TestTempDir() + "/test.proto");
+
+ google::protobuf::compiler::CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+
+ CppGenerator cpp_generator;
+ TestGenerator test_generator;
+ cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
+ cli.RegisterGenerator("--test_out", &test_generator, "");
+
+ string proto_path = "-I" + TestTempDir();
+ string cpp_out = "--cpp_out=" + TestTempDir();
+ string test_out = "--test_out=" + TestTempDir();
+
+ const char* argv[] = {
+ "protoc",
+ proto_path.c_str(),
+ cpp_out.c_str(),
+ test_out.c_str(),
+ "test.proto"
+ };
+
+ EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+} // namespace
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 81f5ce0..a69c48b 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 6b96614..8fcd74a 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 72258e8..ea6809a 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 d7575c0..a7e852d 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/importer.cc b/src/google/protobuf/compiler/importer.cc
index 8a07dfc..7689ce9 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -59,6 +59,7 @@ namespace compiler {
#ifndef F_OK
#define F_OK 00 // not defined by MSVC for whatever reason
#endif
+#include <ctype.h>
#endif
// Returns true if the text looks like a Windows-style absolute path, starting
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 8ade50c..85e39f5 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 dc36e06..af6b1cd 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 63f6815..c54a0fa 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 4403220..903b0a9 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -112,16 +112,20 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
"public static final int $constant_name$ = $number$;\n");
if (descriptor_->is_repeated()) {
printer->Print(vars,
- "public static\n"
+ "public static final\n"
" com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
" $containing_type$,\n"
- " java.util.List<$type$>> $name$;\n");
+ " java.util.List<$type$>> $name$ =\n"
+ " com.google.protobuf.GeneratedMessage$lite$\n"
+ " .newGeneratedExtension();\n");
} else {
printer->Print(vars,
- "public static\n"
+ "public static final\n"
" com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
" $containing_type$,\n"
- " $type$> $name$;\n");
+ " $type$> $name$ =\n"
+ " com.google.protobuf.GeneratedMessage$lite$\n"
+ " .newGeneratedExtension();\n");
}
}
@@ -133,7 +137,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";
@@ -157,43 +161,29 @@ void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) {
}
if (HasDescriptorMethods(descriptor_->file())) {
- if (descriptor_->is_repeated()) {
- printer->Print(vars,
- "$scope$.$name$ =\n"
- " com.google.protobuf.GeneratedMessage\n"
- " .newRepeatedGeneratedExtension(\n"
- " $scope$.getDescriptor().getExtensions().get($index$),\n"
- " $type$.class);\n");
- } else {
- printer->Print(vars,
- "$scope$.$name$ =\n"
- " com.google.protobuf.GeneratedMessage.newGeneratedExtension(\n"
- " $scope$.getDescriptor().getExtensions().get($index$),\n"
- " $type$.class);\n");
- }
+ printer->Print(vars,
+ "$scope$.$name$.internalInit(\n"
+ " $scope$.getDescriptor().getExtensions().get($index$),\n"
+ " $type$.class);\n");
} else {
if (descriptor_->is_repeated()) {
printer->Print(vars,
- "$scope$.$name$ =\n"
- " com.google.protobuf.GeneratedMessageLite\n"
- " .newRepeatedGeneratedExtension(\n"
- " $extendee$.getDefaultInstance(),\n"
- " $prototype$,\n"
- " $enum_map$,\n"
- " $number$,\n"
- " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
- " $packed$);\n");
+ "$scope$.$name$.internalInitRepeated(\n"
+ " $extendee$.getDefaultInstance(),\n"
+ " $prototype$,\n"
+ " $enum_map$,\n"
+ " $number$,\n"
+ " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
+ " $packed$);\n");
} else {
printer->Print(vars,
- "$scope$.$name$ =\n"
- " com.google.protobuf.GeneratedMessageLite\n"
- " .newGeneratedExtension(\n"
- " $extendee$.getDefaultInstance(),\n"
- " $default$,\n"
- " $prototype$,\n"
- " $enum_map$,\n"
- " $number$,\n"
- " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
+ "$scope$.$name$.internalInitSingular(\n"
+ " $extendee$.getDefaultInstance(),\n"
+ " $default$,\n"
+ " $prototype$,\n"
+ " $enum_map$,\n"
+ " $number$,\n"
+ " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
}
}
}
@@ -208,5 +198,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 f9d34ad..978c8f3 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 cab463c..f5bef7a 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 2aedde5..7ea127c 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 cb82cea..9e35d33 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 8ed3aff..745b55a 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 dc6748e..7ed0c3c 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 f1b643c..3c8974c 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 332a118..a326057 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");
@@ -394,6 +408,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
"public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
" throws java.io.IOException {\n");
printer->Indent();
+ // writeTo(CodedOutputStream output) might be invoked without
+ // getSerializedSize() ever being called, but we need the memoized
+ // sizes in case this message has packed fields. Rather than emit checks for
+ // each packed field, just call getSerializedSize() up front for all messages.
+ // In most cases, getSerializedSize() will have already been called anyway by
+ // one of the wrapper writeTo() methods, making this call cheap.
+ printer->Print(
+ "getSerializedSize();\n");
if (descriptor_->extension_range_count() > 0) {
if (descriptor_->options().message_set_wire_format()) {
@@ -521,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"
@@ -614,6 +645,11 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
.GenerateBuilderMembers(printer);
}
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
printer->Outdent();
printer->Print("}\n");
}
@@ -819,7 +855,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",
@@ -832,6 +868,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();
@@ -867,7 +921,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 bbddddd..71edc02 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 90a9097..66bdd88 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_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
new file mode 100644
index 0000000..cfe0188
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -0,0 +1,121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// TODO(kenton): Share code with the versions of this test in other languages?
+// It seemed like parameterizing it would add more complexity than it is
+// worth.
+
+#include <google/protobuf/compiler/java/java_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+ TestGenerator() {}
+ ~TestGenerator() {}
+
+ virtual bool Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const {
+ TryInsert("Test.java", "outer_class_scope", output_directory);
+ TryInsert("Test.java", "class_scope:foo.Bar", output_directory);
+ TryInsert("Test.java", "class_scope:foo.Bar.Baz", output_directory);
+ TryInsert("Test.java", "builder_scope:foo.Bar", output_directory);
+ TryInsert("Test.java", "builder_scope:foo.Bar.Baz", output_directory);
+ TryInsert("Test.java", "enum_scope:foo.Qux", output_directory);
+ return true;
+ }
+
+ void TryInsert(const string& filename, const string& insertion_point,
+ OutputDirectory* output_directory) const {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->OpenForInsert(filename, insertion_point));
+ io::Printer printer(output.get(), '$');
+ printer.Print("// inserted $name$\n", "name", insertion_point);
+ }
+};
+
+// This test verifies that all the expected insertion points exist. It does
+// not verify that they are correctly-placed; that would require actually
+// compiling the output which is a bit more than I care to do for this test.
+TEST(JavaPluginTest, PluginTest) {
+ File::WriteStringToFileOrDie(
+ "syntax = \"proto2\";\n"
+ "package foo;\n"
+ "option java_package = \"\";\n"
+ "option java_outer_classname = \"Test\";\n"
+ "message Bar {\n"
+ " message Baz {}\n"
+ "}\n"
+ "enum Qux { BLAH = 1; }\n",
+ TestTempDir() + "/test.proto");
+
+ google::protobuf::compiler::CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+
+ JavaGenerator java_generator;
+ TestGenerator test_generator;
+ cli.RegisterGenerator("--java_out", &java_generator, "");
+ cli.RegisterGenerator("--test_out", &test_generator, "");
+
+ string proto_path = "-I" + TestTempDir();
+ string java_out = "--java_out=" + TestTempDir();
+ string test_out = "--test_out=" + TestTempDir();
+
+ const char* argv[] = {
+ "protoc",
+ proto_path.c_str(),
+ java_out.c_str(),
+ test_out.c_str(),
+ "test.proto"
+ };
+
+ EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+} // namespace
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 327c205..f6179bf 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"
@@ -298,7 +304,7 @@ GenerateMembers(io::Printer* printer) const {
if (descriptor_->options().packed() &&
HasGeneratedMethods(descriptor_->containing_type())) {
printer->Print(variables_,
- "private int $name$MemoizedSerializedSize;\n");
+ "private int $name$MemoizedSerializedSize = -1;\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 f9da0a6..4e482a0 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/javamicro/javamicro_enum.cc b/src/google/protobuf/compiler/javamicro/javamicro_enum.cc
deleted file mode 100644
index d74a149..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_enum.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <map>
-#include <string>
-
-#include <google/protobuf/compiler/javamicro/javamicro_params.h>
-#include <google/protobuf/compiler/javamicro/javamicro_enum.h>
-#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& params)
- : params_(params), descriptor_(descriptor) {
- for (int i = 0; i < descriptor_->value_count(); i++) {
- const EnumValueDescriptor* value = descriptor_->value(i);
- const EnumValueDescriptor* canonical_value =
- descriptor_->FindValueByNumber(value->number());
-
- if (value == canonical_value) {
- canonical_values_.push_back(value);
- } else {
- Alias alias;
- alias.value = value;
- alias.canonical_value = canonical_value;
- aliases_.push_back(alias);
- }
- }
-}
-
-EnumGenerator::~EnumGenerator() {}
-
-void EnumGenerator::Generate(io::Printer* printer) {
- printer->Print("// enum $classname$\n", "classname", descriptor_->name());
- for (int i = 0; i < canonical_values_.size(); i++) {
- map<string, string> vars;
- vars["name"] = canonical_values_[i]->name();
- vars["canonical_value"] = SimpleItoa(canonical_values_[i]->number());
- printer->Print(vars,
- "public static final int $name$ = $canonical_value$;\n");
- }
-
- // -----------------------------------------------------------------
-
- for (int i = 0; i < aliases_.size(); i++) {
- map<string, string> vars;
- vars["name"] = aliases_[i].value->name();
- vars["canonical_name"] = aliases_[i].canonical_value->name();
- printer->Print(vars,
- "public static final int $name$ = $canonical_name$;\n");
- }
-
- printer->Print("\n");
-}
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc b/src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc
deleted file mode 100644
index 0ff49a3..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc
+++ /dev/null
@@ -1,333 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <map>
-#include <string>
-
-#include <google/protobuf/compiler/javamicro/javamicro_enum_field.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-namespace {
-
-// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
-// repeat code between this and the other field types.
-void SetEnumVariables(const Params& params,
- const FieldDescriptor* descriptor, map<string, string>* variables) {
- (*variables)["name"] =
- UnderscoresToCamelCase(descriptor);
- (*variables)["capitalized_name"] =
- UnderscoresToCapitalizedCamelCase(descriptor);
- (*variables)["number"] = SimpleItoa(descriptor->number());
- (*variables)["type"] = "int";
- (*variables)["default"] = DefaultValue(params, descriptor);
- (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
- (*variables)["tag_size"] = SimpleItoa(
- internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
- (*variables)["message_name"] = descriptor->containing_type()->name();
-}
-
-} // namespace
-
-// ===================================================================
-
-EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
- : FieldGenerator(params), descriptor_(descriptor) {
- SetEnumVariables(params, descriptor, &variables_);
-}
-
-EnumFieldGenerator::~EnumFieldGenerator() {}
-
-void EnumFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
- printer->Print(variables_,
- "private boolean has$capitalized_name$;\n"
- "private int $name$_ = $default$;\n"
- "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
- "public int get$capitalized_name$() { return $name$_; }\n"
- "public $message_name$ set$capitalized_name$(int value) {\n"
- " has$capitalized_name$ = true;\n"
- " $name$_ = value;\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " has$capitalized_name$ = false;\n"
- " $name$_ = $default$;\n"
- " return this;\n"
- "}\n");
-}
-
-void EnumFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "what is other??"
- "if (other.has$capitalized_name$()) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
- "}\n");
-}
-
-void EnumFieldGenerator::
-GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- " set$capitalized_name$(input.readInt32());\n");
-}
-
-void EnumFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (has$capitalized_name$()) {\n"
- " output.writeInt32($number$, get$capitalized_name$());\n"
- "}\n");
-}
-
-void EnumFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (has$capitalized_name$()) {\n"
- " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .computeInt32Size($number$, get$capitalized_name$());\n"
- "}\n");
-}
-
-string EnumFieldGenerator::GetBoxedType() const {
- return ClassName(params_, descriptor_->enum_type());
-}
-
-// ===================================================================
-
-RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
- : FieldGenerator(params), descriptor_(descriptor) {
- SetEnumVariables(params, descriptor, &variables_);
- if (descriptor_->options().packed()) {
- GOOGLE_LOG(FATAL) << "MicroRuntime does not support packed";
- }
-}
-
-RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
-
-void RepeatedEnumFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "private java.util.Vector $name$_ = new java.util.Vector();\n"
- "public java.util.Vector get$capitalized_name$List() {\n"
- " return $name$_;\n"
- "}\n"
- "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
- "public int get$capitalized_name$(int index) {\n"
- " return ((Integer)$name$_.elementAt(index)).intValue();\n"
- "}\n"
- "public $message_name$ set$capitalized_name$(int index, int value) {\n"
- " $name$_.setElementAt(new Integer(value), index);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ add$capitalized_name$(int value) {\n"
- " $name$_.addElement(new Integer(value));\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " $name$_.removeAllElements();\n"
- " return this;\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "private java.util.List<Integer> $name$_ =\n"
- " java.util.Collections.emptyList();\n"
- "public java.util.List<Integer> get$capitalized_name$List() {\n"
- " return $name$_;\n" // note: unmodifiable list
- "}\n"
- "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
- "public int get$capitalized_name$(int index) {\n"
- " return $name$_.get(index);\n"
- "}\n"
- "public $message_name$ set$capitalized_name$(int index, int value) {\n"
- " $name$_.set(index, value);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ add$capitalized_name$(int value) {\n"
- " if ($name$_.isEmpty()) {\n"
- " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
- " }\n"
- " $name$_.add(value);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " $name$_ = java.util.Collections.emptyList();\n"
- " return this;\n"
- "}\n");
- }
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "private int $name$MemoizedSerializedSize;\n");
- }
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "if (other.$name$_.size() != 0) {\n"
- " for (int i = 0; i < other.$name$_.size(); i++)) {\n"
- " result.$name$_.addElement(other.$name$_.elementAt(i));\n"
- " }\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "if (!other.$name$_.isEmpty()) {\n"
- " if (result.$name$_.isEmpty()) {\n"
- " result.$name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
- " }\n"
- " result.$name$_.addAll(other.$name$_);\n"
- "}\n");
- }
-}
-
-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_,
- " add$capitalized_name$(input.readInt32());\n");
-
- if (descriptor_->options().packed()) {
- printer->Outdent();
- printer->Print(variables_,
- "}\n"
- "input.popLimit(oldLimit);\n");
- }
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "if (get$capitalized_name$List().size() > 0) {\n"
- " output.writeRawVarint32($tag$);\n"
- " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
- "}\n");
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
- " output.writeRawVarint32(get$capitalized_name$(i));\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " output.writeRawVarint32(element.getNumber());\n"
- "}\n");
- }
- } else {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
- " output.writeInt32($number$, (int)get$capitalized_name$(i));\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "for (java.lang.Integer element : get$capitalized_name$List()) {\n"
- " output.writeInt32($number$, element);\n"
- "}\n");
- }
- }
-}
-
-void RepeatedEnumFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
- printer->Print(variables_,
- "{\n"
- " int dataSize = 0;\n");
- printer->Indent();
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
- " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .computeInt32SizeNoTag(get$capitalized_name$(i));\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "for (java.lang.Integer element : get$capitalized_name$List()) {\n"
- " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .computeInt32SizeNoTag(element);\n"
- "}\n");
- }
- printer->Print(
- "size += dataSize;\n");
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "if (get$capitalized_name$List().size() != 0) {"
- " size += $tag_size$;\n"
- " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .computeRawVarint32Size(dataSize);\n"
- "}");
- } else {
- printer->Print(variables_,
- "size += $tag_size$ * get$capitalized_name$List().size();\n");
- }
-
- // cache the data size for packed fields.
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "$name$MemoizedSerializedSize = dataSize;\n");
- }
-
- printer->Outdent();
- printer->Print("}\n");
-}
-
-string RepeatedEnumFieldGenerator::GetBoxedType() const {
- return ClassName(params_, descriptor_->enum_type());
-}
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_enum_field.h b/src/google/protobuf/compiler/javamicro/javamicro_enum_field.h
deleted file mode 100644
index ab671c1..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_enum_field.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
-
-#include <map>
-#include <string>
-#include <google/protobuf/compiler/javamicro/javamicro_field.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-class EnumFieldGenerator : public FieldGenerator {
- public:
- explicit EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
- ~EnumFieldGenerator();
-
- // implements FieldGenerator ---------------------------------------
- void GenerateMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
- void GenerateParsingCode(io::Printer* printer) const;
- void GenerateSerializationCode(io::Printer* printer) const;
- void GenerateSerializedSizeCode(io::Printer* printer) const;
-
- string GetBoxedType() const;
-
- private:
- const FieldDescriptor* descriptor_;
- map<string, string> variables_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
-};
-
-class RepeatedEnumFieldGenerator : public FieldGenerator {
- public:
- explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
- ~RepeatedEnumFieldGenerator();
-
- // implements FieldGenerator ---------------------------------------
- void GenerateMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
- void GenerateParsingCode(io::Printer* printer) const;
- void GenerateSerializationCode(io::Printer* printer) const;
- void GenerateSerializedSizeCode(io::Printer* printer) const;
-
- string GetBoxedType() const;
-
- private:
- const FieldDescriptor* descriptor_;
- map<string, string> variables_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
-};
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_field.cc b/src/google/protobuf/compiler/javamicro/javamicro_field.cc
deleted file mode 100644
index a2ea4f9..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_field.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <google/protobuf/compiler/javamicro/javamicro_field.h>
-#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
-#include <google/protobuf/compiler/javamicro/javamicro_primitive_field.h>
-#include <google/protobuf/compiler/javamicro/javamicro_enum_field.h>
-#include <google/protobuf/compiler/javamicro/javamicro_message_field.h>
-#include <google/protobuf/stubs/common.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-FieldGenerator::~FieldGenerator() {}
-
-FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Params &params)
- : descriptor_(descriptor),
- field_generators_(
- new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
- extension_generators_(
- new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
-
- // Construct all the FieldGenerators.
- for (int i = 0; i < descriptor->field_count(); i++) {
- field_generators_[i].reset(MakeGenerator(descriptor->field(i), params));
- }
- for (int i = 0; i < descriptor->extension_count(); i++) {
- extension_generators_[i].reset(MakeGenerator(descriptor->extension(i), params));
- }
-}
-
-FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, const Params &params) {
- if (field->is_repeated()) {
- switch (GetJavaType(field)) {
- case JAVATYPE_MESSAGE:
- return new RepeatedMessageFieldGenerator(field, params);
- case JAVATYPE_ENUM:
- return new RepeatedEnumFieldGenerator(field, params);
- default:
- return new RepeatedPrimitiveFieldGenerator(field, params);
- }
- } else {
- switch (GetJavaType(field)) {
- case JAVATYPE_MESSAGE:
- return new MessageFieldGenerator(field, params);
- case JAVATYPE_ENUM:
- return new EnumFieldGenerator(field, params);
- default:
- return new PrimitiveFieldGenerator(field, params);
- }
- }
-}
-
-FieldGeneratorMap::~FieldGeneratorMap() {}
-
-const FieldGenerator& FieldGeneratorMap::get(
- const FieldDescriptor* field) const {
- GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
- return *field_generators_[field->index()];
-}
-
-const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
- return *extension_generators_[index];
-}
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_file.cc b/src/google/protobuf/compiler/javamicro/javamicro_file.cc
deleted file mode 100644
index 0985538..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_file.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <google/protobuf/compiler/javamicro/javamicro_file.h>
-#include <google/protobuf/compiler/javamicro/javamicro_enum.h>
-#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
-#include <google/protobuf/compiler/javamicro/javamicro_message.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-namespace {
-
-// Recursively searches the given message to see if it contains any extensions.
-bool UsesExtensions(const Message& message) {
- const Reflection* reflection = message.GetReflection();
-
- // We conservatively assume that unknown fields are extensions.
- if (reflection->GetUnknownFields(message).field_count() > 0) return true;
-
- vector<const FieldDescriptor*> fields;
- reflection->ListFields(message, &fields);
-
- for (int i = 0; i < fields.size(); i++) {
- if (fields[i]->is_extension()) return true;
-
- if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- if (fields[i]->is_repeated()) {
- int size = reflection->FieldSize(message, fields[i]);
- for (int j = 0; j < size; j++) {
- const Message& sub_message =
- reflection->GetRepeatedMessage(message, fields[i], j);
- if (UsesExtensions(sub_message)) return true;
- }
- } else {
- const Message& sub_message = reflection->GetMessage(message, fields[i]);
- if (UsesExtensions(sub_message)) return true;
- }
- }
- }
-
- return false;
-}
-
-} // namespace
-
-FileGenerator::FileGenerator(const FileDescriptor* file, const Params& params)
- : file_(file),
- params_(params),
- java_package_(FileJavaPackage(params, file)),
- classname_(FileClassName(params, file)) {}
-
-FileGenerator::~FileGenerator() {}
-
-bool FileGenerator::Validate(string* error) {
- // Check for extensions
- FileDescriptorProto file_proto;
- file_->CopyTo(&file_proto);
- if (UsesExtensions(file_proto)) {
- error->assign(file_->name());
- error->append(
- ": Java MICRO_RUNTIME does not support extensions\"");
- return false;
- }
-
- // If there is no outer class name then there must be only
- // message and no enums defined in the file scope.
- if (!params_.has_java_outer_classname(file_->name())) {
- if (file_->message_type_count() != 1) {
- error->assign(file_->name());
- error->append(
- ": Java MICRO_RUNTIME may only have 1 message if there is no 'option java_outer_classname'\"");
- return false;
- }
-
- if (file_->enum_type_count() != 0) {
- error->assign(file_->name());
- error->append(
- ": Java MICRO_RUNTIME must have an 'option java_outer_classname' if file scope enums are present\"");
- return false;
- }
- }
-
- // Check that no class name matches the file's class name. This is a common
- // problem that leads to Java compile errors that can be hard to understand.
- // It's especially bad when using the java_multiple_files, since we would
- // end up overwriting the outer class with one of the inner ones.
- int found_fileName = 0;
- for (int i = 0; i < file_->enum_type_count(); i++) {
- if (file_->enum_type(i)->name() == classname_) {
- found_fileName += 1;
- }
- }
- for (int i = 0; i < file_->message_type_count(); i++) {
- if (file_->message_type(i)->name() == classname_) {
- found_fileName += 1;
- }
- }
- if (file_->service_count() != 0) {
- error->assign(file_->name());
- error->append(
- ": Java MICRO_RUNTIME does not support services\"");
- return false;
- }
-
- if (found_fileName > 1) {
- error->assign(file_->name());
- error->append(
- ": Cannot generate Java output because there is more than one class name, \"");
- error->append(classname_);
- error->append(
- "\", matches the name of one of the types declared inside it. "
- "Please either rename the type or use the java_outer_classname "
- "option to specify a different outer class name for the .proto file."
- " -- FIX THIS MESSAGE");
- return false;
- }
- return true;
-}
-
-void FileGenerator::Generate(io::Printer* printer) {
- // We don't import anything because we refer to all classes by their
- // fully-qualified names in the generated source.
- printer->Print(
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "\n");
- if (!java_package_.empty()) {
- printer->Print(
- "package $package$;\n"
- "\n",
- "package", java_package_);
- }
-
- if (params_.has_java_outer_classname(file_->name())) {
- printer->Print(
- "public final class $classname$ {\n"
- " private $classname$() {}\n",
- "classname", classname_);
- printer->Indent();
- }
-
- // -----------------------------------------------------------------
-
- if (!params_.java_multiple_files()) {
- for (int i = 0; i < file_->enum_type_count(); i++) {
- EnumGenerator(file_->enum_type(i), params_).Generate(printer);
- }
- for (int i = 0; i < file_->message_type_count(); i++) {
- MessageGenerator(file_->message_type(i), params_).Generate(printer);
- }
- }
-
- // Static variables.
- for (int i = 0; i < file_->message_type_count(); i++) {
- // TODO(kenton): Reuse MessageGenerator objects?
- MessageGenerator(file_->message_type(i), params_).GenerateStaticVariables(printer);
- }
-
- if (params_.has_java_outer_classname(file_->name())) {
- printer->Outdent();
- printer->Print(
- "}\n");
- }
-}
-
-template<typename GeneratorClass, typename DescriptorClass>
-static void GenerateSibling(const string& package_dir,
- const string& java_package,
- const DescriptorClass* descriptor,
- OutputDirectory* output_directory,
- vector<string>* file_list,
- const Params& params) {
- string filename = package_dir + descriptor->name() + ".java";
- file_list->push_back(filename);
-
- scoped_ptr<io::ZeroCopyOutputStream> output(
- output_directory->Open(filename));
- io::Printer printer(output.get(), '$');
-
- printer.Print(
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "\n");
- if (!java_package.empty()) {
- printer.Print(
- "package $package$;\n"
- "\n",
- "package", java_package);
- }
-
- GeneratorClass(descriptor, params).Generate(&printer);
-}
-
-void FileGenerator::GenerateSiblings(const string& package_dir,
- OutputDirectory* output_directory,
- vector<string>* file_list) {
- if (params_.java_multiple_files()) {
- for (int i = 0; i < file_->enum_type_count(); i++) {
- GenerateSibling<EnumGenerator>(package_dir, java_package_,
- file_->enum_type(i),
- output_directory, file_list, params_);
- }
- for (int i = 0; i < file_->message_type_count(); i++) {
- GenerateSibling<MessageGenerator>(package_dir, java_package_,
- file_->message_type(i),
- output_directory, file_list, params_);
- }
- }
-}
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_generator.cc b/src/google/protobuf/compiler/javamicro/javamicro_generator.cc
deleted file mode 100644
index bfba8c5..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_generator.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <google/protobuf/compiler/javamicro/javamicro_params.h>
-#include <google/protobuf/compiler/javamicro/javamicro_generator.h>
-#include <google/protobuf/compiler/javamicro/javamicro_file.h>
-#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-void UpdateParamsRecursively(Params& params,
- const FileDescriptor* file) {
- // Add any parameters for this file
- if (file->options().has_java_outer_classname()) {
- params.set_java_outer_classname(
- file->name(), file->options().java_outer_classname());
- }
- if (file->options().has_java_package()) {
- params.set_java_package(
- file->name(), file->options().java_package());
- }
-
- // Loop through all dependent files recursively
- // adding dep
- for (int i = 0; i < file->dependency_count(); i++) {
- UpdateParamsRecursively(params, file->dependency(i));
- }
-}
-
-JavaMicroGenerator::JavaMicroGenerator() {}
-JavaMicroGenerator::~JavaMicroGenerator() {}
-
-bool JavaMicroGenerator::Generate(const FileDescriptor* file,
- const string& parameter,
- OutputDirectory* output_directory,
- string* error) const {
- vector<pair<string, string> > options;
-
-// GOOGLE_LOG(INFO) << "wink: JavaMicroGenerator::Generate INFO";
-// GOOGLE_LOG(WARNING) << "wink: JavaMicroGenerator::Generate WARNING";
-// GOOGLE_LOG(ERROR) << "wink: JavaMicroGenerator::Generate ERROR";
-// GOOGLE_LOG(FATAL) << "wink: JavaMicroGenerator::Generate";
-
- ParseGeneratorParameter(parameter, &options);
-
- // -----------------------------------------------------------------
- // parse generator options
-
- // Name a file where we will write a list of generated file names, one
- // per line.
- string output_list_file;
- Params params(file->name());
-
- // Get options from the proto file
- if (file->options().has_java_multiple_files()) {
- params.set_java_multiple_files(file->options().java_multiple_files());
- }
-
- // Update per file params
- UpdateParamsRecursively(params, file);
-
- // Replace any existing options with ones from command line
- for (int i = 0; i < options.size(); i++) {
- // GOOGLE_LOG(WARNING) << "first=" << options[i].first
- // << " second=" << options[i].second;
- if (options[i].first == "output_list_file") {
- output_list_file = options[i].second;
- } else if (options[i].first == "opt") {
- if (options[i].second == "speed") {
- params.set_optimization(JAVAMICRO_OPT_SPEED);
- } else if (options[i].second == "space") {
- params.set_optimization(JAVAMICRO_OPT_SPACE);
- } else {
- *error = "Unknown javamicro generator option: opt="
- + options[i].second + " expecting opt=space or opt=speed";
- return false;
- }
- } else if (options[i].first == "java_package") {
- vector<string> parts;
- SplitStringUsing(options[i].second, "|", &parts);
- if (parts.size() != 2) {
- *error = "Bad java_package, expecting filename|PackageName found '"
- + options[i].second + "'";
- return false;
- }
- params.set_java_package(parts[0], parts[1]);
- } else if (options[i].first == "java_outer_classname") {
- vector<string> parts;
- SplitStringUsing(options[i].second, "|", &parts);
- if (parts.size() != 2) {
- *error = "Bad java_outer_classname, "
- "expecting filename|ClassName found '"
- + options[i].second + "'";
- return false;
- }
- params.set_java_outer_classname(parts[0], parts[1]);
- } else if (options[i].first == "java_multiple_files") {
- params.set_java_multiple_files(options[i].second == "true");
- } else if (options[i].first == "java_use_vector") {
- params.set_java_use_vector(options[i].second == "true");
- } else {
- *error = "Ignore unknown javamicro generator option: " + options[i].first;
- }
- }
-
-#if 0
- GOOGLE_LOG(WARNING) << "optimization()=" << params.optimization();
- GOOGLE_LOG(WARNING) << "java_multiple_files()=" << params.java_multiple_files();
- GOOGLE_LOG(WARNING) << "java_use_vector()=" << params.java_use_vector();
-
- GOOGLE_LOG(WARNING) << "----------";
- for (Params::NameMap::const_iterator it = params.java_packages().begin();
- it != params.java_packages().end();
- ++it) {
- GOOGLE_LOG(WARNING) << "cn.filename=" << it->first << " package=" << it->second;
- }
- for (Params::NameMap::const_iterator it = params.java_outer_classnames().begin();
- it != params.java_outer_classnames().end();
- ++it) {
- GOOGLE_LOG(WARNING) << "cn.filename=" << it->first << " classname=" << it->second;
- }
- GOOGLE_LOG(WARNING) << "==========";
-
-#endif
-
- // -----------------------------------------------------------------
-
- FileGenerator file_generator(file, params);
- if (!file_generator.Validate(error)) {
- return false;
- }
-
- string package_dir =
- StringReplace(file_generator.java_package(), ".", "/", true);
- if (!package_dir.empty()) package_dir += "/";
-
- vector<string> all_files;
-
- string java_filename = package_dir;
- java_filename += file_generator.classname();
- java_filename += ".java";
- all_files.push_back(java_filename);
-
- // Generate main java file.
- scoped_ptr<io::ZeroCopyOutputStream> output(
- output_directory->Open(java_filename));
- io::Printer printer(output.get(), '$');
- file_generator.Generate(&printer);
-
- // Generate sibling files.
- file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
-
- // Generate output list if requested.
- if (!output_list_file.empty()) {
- // Generate output list. This is just a simple text file placed in a
- // deterministic location which lists the .java files being generated.
- scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
- output_directory->Open(output_list_file));
- io::Printer srclist_printer(srclist_raw_output.get(), '$');
- for (int i = 0; i < all_files.size(); i++) {
- srclist_printer.Print("$filename$\n", "filename", all_files[i]);
- }
- }
-
- return true;
-}
-
-} // namespace java
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc b/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc
deleted file mode 100644
index 11ba71a..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc
+++ /dev/null
@@ -1,381 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <vector>
-
-#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
-#include <google/protobuf/compiler/javamicro/javamicro_params.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-const char kThickSeparator[] =
- "// ===================================================================\n";
-const char kThinSeparator[] =
- "// -------------------------------------------------------------------\n";
-
-namespace {
-
-const char* kDefaultPackage = "";
-
-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) {
- return field->message_type()->name();
- } else {
- return field->name();
- }
-}
-
-string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) {
- string result;
- // Note: I distrust ctype.h due to locales.
- for (int i = 0; i < input.size(); i++) {
- if ('a' <= input[i] && input[i] <= 'z') {
- if (cap_next_letter) {
- result += input[i] + ('A' - 'a');
- } else {
- result += input[i];
- }
- cap_next_letter = false;
- } else if ('A' <= input[i] && input[i] <= 'Z') {
- if (i == 0 && !cap_next_letter) {
- // Force first letter to lower-case unless explicitly told to
- // capitalize it.
- result += input[i] + ('a' - 'A');
- } else {
- // Capital letters after the first are left as-is.
- result += input[i];
- }
- cap_next_letter = false;
- } else if ('0' <= input[i] && input[i] <= '9') {
- result += input[i];
- cap_next_letter = true;
- } else {
- cap_next_letter = true;
- }
- }
- return result;
-}
-
-} // namespace
-
-string UnderscoresToCamelCase(const FieldDescriptor* field) {
- return UnderscoresToCamelCaseImpl(FieldName(field), false);
-}
-
-string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
- return UnderscoresToCamelCaseImpl(FieldName(field), true);
-}
-
-string UnderscoresToCamelCase(const MethodDescriptor* method) {
- return UnderscoresToCamelCaseImpl(method->name(), false);
-}
-
-string StripProto(const string& filename) {
- if (HasSuffixString(filename, ".protodevel")) {
- return StripSuffixString(filename, ".protodevel");
- } else {
- return StripSuffixString(filename, ".proto");
- }
-}
-
-string FileClassName(const Params& params, const FileDescriptor* file) {
- string name;
-
- if (params.has_java_outer_classname(file->name())) {
- name = params.java_outer_classname(file->name());
- } else {
- if ((file->message_type_count() == 1)
- || (file->enum_type_count() == 0)) {
- // If no outer calls and only one message then
- // use the message name as the file name
- name = file->message_type(0)->name();
- } else {
- // Use the filename it self with underscores removed
- // and a CamelCase style name.
- string basename;
- string::size_type last_slash = file->name().find_last_of('/');
- if (last_slash == string::npos) {
- basename = file->name();
- } else {
- basename = file->name().substr(last_slash + 1);
- }
- name = UnderscoresToCamelCaseImpl(StripProto(basename), true);
- }
- }
-
- return name;
-}
-
-string FileJavaPackage(const Params& params, const FileDescriptor* file) {
- if (params.has_java_package(file->name())) {
- return params.java_package(file->name());
- } else {
- string result = kDefaultPackage;
- if (!file->package().empty()) {
- if (!result.empty()) result += '.';
- result += file->package();
- }
- return result;
- }
-}
-
-string ToJavaName(const Params& params, const string& full_name,
- const FileDescriptor* file) {
- string result;
- if (params.java_multiple_files()) {
- result = FileJavaPackage(params, file);
- } else {
- result = ClassName(params, file);
- }
- if (file->package().empty()) {
- result += '.';
- result += full_name;
- } else {
- // Strip the proto package from full_name since we've replaced it with
- // the Java package. If there isn't an outer classname then strip it too.
- int sizeToSkipPackageName = file->package().size();
- int sizeToSkipOutClassName;
- if (params.has_java_outer_classname(file->name())) {
- sizeToSkipOutClassName = 0;
- } else {
- sizeToSkipOutClassName =
- full_name.find_first_of('.', sizeToSkipPackageName + 1);
- }
- int sizeToSkip = sizeToSkipOutClassName > 0 ?
- sizeToSkipOutClassName : sizeToSkipPackageName;
- string class_name = full_name.substr(sizeToSkip + 1);
- if (class_name == FileClassName(params, file)) {
- // Done class_name is already present.
- } else {
- result += '.';
- result += class_name;
- }
- }
- return result;
-}
-
-string ClassName(const Params& params, const FileDescriptor* descriptor) {
- string result = FileJavaPackage(params, descriptor);
- if (!result.empty()) result += '.';
- result += FileClassName(params, descriptor);
- return result;
-}
-
-string ClassName(const Params& params, const EnumDescriptor* descriptor) {
- string result;
- const FileDescriptor* file = descriptor->file();
- const string file_name = file->name();
- const string full_name = descriptor->full_name();
- int last_period = full_name.find_last_of('.');
- int first_period = full_name.find_first_of('.');
-
- // Remove class_name as we're using public static final int's not enums
- string base_name = full_name.substr(0, full_name.find_last_of('.'));
-
- if (!file->package().empty()) {
- // Remove package name.
- int offset = first_period;
- if (last_period > first_period) {
- // There was two or more periods so we need to remove this one too.
- offset += 1;
- }
- base_name = base_name.substr(offset);
- }
-
- if (params.has_java_package(file_name)) {
- result += params.java_package(file_name);
- }
- if (params.has_java_outer_classname(file_name)) {
- result += ".";
- result += params.java_outer_classname(file_name);
- }
- if (!base_name.empty()) {
- result += ".";
- result += base_name;
- }
- return result;
-}
-
-string FieldConstantName(const FieldDescriptor *field) {
- string name = field->name() + "_FIELD_NUMBER";
- UpperString(&name);
- return name;
-}
-
-JavaType GetJavaType(FieldDescriptor::Type field_type) {
- switch (field_type) {
- case FieldDescriptor::TYPE_INT32:
- case FieldDescriptor::TYPE_UINT32:
- case FieldDescriptor::TYPE_SINT32:
- case FieldDescriptor::TYPE_FIXED32:
- case FieldDescriptor::TYPE_SFIXED32:
- return JAVATYPE_INT;
-
- case FieldDescriptor::TYPE_INT64:
- case FieldDescriptor::TYPE_UINT64:
- case FieldDescriptor::TYPE_SINT64:
- case FieldDescriptor::TYPE_FIXED64:
- case FieldDescriptor::TYPE_SFIXED64:
- return JAVATYPE_LONG;
-
- case FieldDescriptor::TYPE_FLOAT:
- return JAVATYPE_FLOAT;
-
- case FieldDescriptor::TYPE_DOUBLE:
- return JAVATYPE_DOUBLE;
-
- case FieldDescriptor::TYPE_BOOL:
- return JAVATYPE_BOOLEAN;
-
- case FieldDescriptor::TYPE_STRING:
- return JAVATYPE_STRING;
-
- case FieldDescriptor::TYPE_BYTES:
- return JAVATYPE_BYTES;
-
- case FieldDescriptor::TYPE_ENUM:
- return JAVATYPE_ENUM;
-
- case FieldDescriptor::TYPE_GROUP:
- case FieldDescriptor::TYPE_MESSAGE:
- return JAVATYPE_MESSAGE;
-
- // No default because we want the compiler to complain if any new
- // types are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return JAVATYPE_INT;
-}
-
-const char* BoxedPrimitiveTypeName(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return "java.lang.Integer";
- case JAVATYPE_LONG : return "java.lang.Long";
- case JAVATYPE_FLOAT : return "java.lang.Float";
- case JAVATYPE_DOUBLE : return "java.lang.Double";
- case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
- case JAVATYPE_STRING : return "java.lang.String";
- case JAVATYPE_BYTES : return "com.google.protobuf.micro.ByteStringMicro";
- case JAVATYPE_ENUM : return "java.lang.Integer";
- case JAVATYPE_MESSAGE: return NULL;
-
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return NULL;
-}
-
-bool AllAscii(const string& text) {
- for (int i = 0; i < text.size(); i++) {
- if ((text[i] & 0x80) != 0) {
- return false;
- }
- }
- return true;
-}
-
-string DefaultValue(const Params& params, const FieldDescriptor* field) {
- // Switch on cpp_type since we need to know which default_value_* method
- // of FieldDescriptor to call.
- switch (field->cpp_type()) {
- case FieldDescriptor::CPPTYPE_INT32:
- return SimpleItoa(field->default_value_int32());
- case FieldDescriptor::CPPTYPE_UINT32:
- // Need to print as a signed int since Java has no unsigned.
- return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
- case FieldDescriptor::CPPTYPE_INT64:
- return SimpleItoa(field->default_value_int64()) + "L";
- 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_BOOL:
- return field->default_value_bool() ? "true" : "false";
- case FieldDescriptor::CPPTYPE_STRING:
- if (field->type() == FieldDescriptor::TYPE_BYTES) {
- if (field->has_default_value()) {
- // See comments in Internal.java for gory details.
- return strings::Substitute(
- "com.google.protobuf.micro.ByteStringMicro.copyFromUtf8(\"$0\")",
- CEscape(field->default_value_string()));
- } else {
- return "com.google.protobuf.micro.ByteStringMicro.EMPTY";
- }
- } else {
- if (AllAscii(field->default_value_string())) {
- // All chars are ASCII. In this case CEscape() works fine.
- return "\"" + CEscape(field->default_value_string()) + "\"";
- } else {
- // See comments in Internal.java for gory details.
- // BUG: Internal NOT SUPPORTED need to fix!!
- return strings::Substitute(
- "com.google.protobuf.micro.Internal.stringDefaultValue(\"$0\")",
- CEscape(field->default_value_string()));
- }
- }
-
- case FieldDescriptor::CPPTYPE_ENUM:
- return ClassName(params, field->enum_type()) + "." +
- field->default_value_enum()->name();
-
- case FieldDescriptor::CPPTYPE_MESSAGE:
- return ClassName(params, field->message_type()) + ".getDefaultInstance()";
-
- // No default because we want the compiler to complain if any new
- // types are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return "";
-}
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_helpers.h b/src/google/protobuf/compiler/javamicro/javamicro_helpers.h
deleted file mode 100644
index eeddbf9..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_helpers.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
-
-#include <string>
-#include <google/protobuf/compiler/javamicro/javamicro_params.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-// Commonly-used separator comments. Thick is a line of '=', thin is a line
-// of '-'.
-extern const char kThickSeparator[];
-extern const char kThinSeparator[];
-
-// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
-// "fooBarBaz" or "FooBarBaz", respectively.
-string UnderscoresToCamelCase(const FieldDescriptor* field);
-string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
-
-// Similar, but for method names. (Typically, this merely has the effect
-// of lower-casing the first letter of the name.)
-string UnderscoresToCamelCase(const MethodDescriptor* method);
-
-// Strips ".proto" or ".protodevel" from the end of a filename.
-string StripProto(const string& filename);
-
-// Gets the unqualified class name for the file. Each .proto file becomes a
-// single Java class, with all its contents nested in that class.
-string FileClassName(const Params& params, const FileDescriptor* file);
-
-// Returns the file's Java package name.
-string FileJavaPackage(const Params& params, const FileDescriptor* file);
-
-// Converts the given fully-qualified name in the proto namespace to its
-// fully-qualified name in the Java namespace, given that it is in the given
-// file.
-string ToJavaName(const Params& params, const string& full_name,
- const FileDescriptor* file);
-
-// These return the fully-qualified class name corresponding to the given
-// descriptor.
-inline string ClassName(const Params& params, const Descriptor* descriptor) {
- return ToJavaName(params, descriptor->full_name(), descriptor->file());
-}
-string ClassName(const Params& params, const EnumDescriptor* descriptor);
-inline string ClassName(const Params& params,
- const ServiceDescriptor* descriptor) {
- return ToJavaName(params, descriptor->full_name(), descriptor->file());
-}
-inline string ExtensionIdentifierName(const Params& params,
- const FieldDescriptor* descriptor) {
- return ToJavaName(params, descriptor->full_name(), descriptor->file());
-}
-string ClassName(const Params& params, const FileDescriptor* descriptor);
-
-// Get the unqualified name that should be used for a field's field
-// number constant.
-string FieldConstantName(const FieldDescriptor *field);
-
-enum JavaType {
- JAVATYPE_INT,
- JAVATYPE_LONG,
- JAVATYPE_FLOAT,
- JAVATYPE_DOUBLE,
- JAVATYPE_BOOLEAN,
- JAVATYPE_STRING,
- JAVATYPE_BYTES,
- JAVATYPE_ENUM,
- JAVATYPE_MESSAGE
-};
-
-JavaType GetJavaType(FieldDescriptor::Type field_type);
-
-inline JavaType GetJavaType(const FieldDescriptor* field) {
- return GetJavaType(field->type());
-}
-
-// 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
-// types.
-const char* BoxedPrimitiveTypeName(JavaType type);
-
-string DefaultValue(const Params& params, const FieldDescriptor* field);
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_message.cc b/src/google/protobuf/compiler/javamicro/javamicro_message.cc
deleted file mode 100644
index 7fc6c3d..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_message.cc
+++ /dev/null
@@ -1,474 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <algorithm>
-#include <google/protobuf/stubs/hash.h>
-#include <google/protobuf/compiler/javamicro/javamicro_message.h>
-#include <google/protobuf/compiler/javamicro/javamicro_enum.h>
-#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/descriptor.pb.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-using internal::WireFormat;
-using internal::WireFormatLite;
-
-namespace {
-
-void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
- // Print the field's proto-syntax definition as a comment. We don't want to
- // print group bodies so we cut off after the first line.
- string def = field->DebugString();
- printer->Print("// $def$\n",
- "def", def.substr(0, def.find_first_of('\n')));
-}
-
-struct FieldOrderingByNumber {
- inline bool operator()(const FieldDescriptor* a,
- const FieldDescriptor* b) const {
- return a->number() < b->number();
- }
-};
-
-// Sort the fields of the given Descriptor by number into a new[]'d array
-// and return it.
-const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
- const FieldDescriptor** fields =
- new const FieldDescriptor*[descriptor->field_count()];
- for (int i = 0; i < descriptor->field_count(); i++) {
- fields[i] = descriptor->field(i);
- }
- sort(fields, fields + descriptor->field_count(),
- FieldOrderingByNumber());
- return fields;
-}
-
-// Get an identifier that uniquely identifies this type within the file.
-// This is used to declare static variables related to this type at the
-// outermost file scope.
-string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
- return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
-}
-
-// Returns true if the message type has any required fields. If it doesn't,
-// we can optimize out calls to its isInitialized() method.
-//
-// already_seen is used to avoid checking the same type multiple times
-// (and also to protect against recursion).
-static bool HasRequiredFields(
- const Descriptor* type,
- hash_set<const Descriptor*>* already_seen) {
- if (already_seen->count(type) > 0) {
- // The type is already in cache. This means that either:
- // a. The type has no required fields.
- // b. We are in the midst of checking if the type has required fields,
- // somewhere up the stack. In this case, we know that if the type
- // has any required fields, they'll be found when we return to it,
- // and the whole call to HasRequiredFields() will return true.
- // Therefore, we don't have to check if this type has required fields
- // here.
- return false;
- }
- already_seen->insert(type);
-
- // If the type has extensions, an extension with message type could contain
- // required fields, so we have to be conservative and assume such an
- // extension exists.
- if (type->extension_range_count() > 0) return true;
-
- for (int i = 0; i < type->field_count(); i++) {
- const FieldDescriptor* field = type->field(i);
- if (field->is_required()) {
- return true;
- }
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- if (HasRequiredFields(field->message_type(), already_seen)) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-static bool HasRequiredFields(const Descriptor* type) {
- hash_set<const Descriptor*> already_seen;
- return HasRequiredFields(type, &already_seen);
-}
-
-} // namespace
-
-// ===================================================================
-
-MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
- : params_(params),
- descriptor_(descriptor),
- field_generators_(descriptor, params) {
-}
-
-MessageGenerator::~MessageGenerator() {}
-
-void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
- // Generate static members for all nested types.
- for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- // TODO(kenton): Reuse MessageGenerator objects?
- MessageGenerator(descriptor_->nested_type(i), params_)
- .GenerateStaticVariables(printer);
- }
-}
-
-void MessageGenerator::GenerateStaticVariableInitializers(
- io::Printer* printer) {
- // Generate static member initializers for all nested types.
- for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- // TODO(kenton): Reuse MessageGenerator objects?
- MessageGenerator(descriptor_->nested_type(i), params_)
- .GenerateStaticVariableInitializers(printer);
- }
-
- if (descriptor_->extension_count() != 0) {
- GOOGLE_LOG(FATAL) << "Extensions not supported in MICRO_RUNTIME\n";
- }
-}
-
-void MessageGenerator::Generate(io::Printer* printer) {
- bool is_own_file =
- params_.java_multiple_files() || ((descriptor_->containing_type() == NULL)
- && !params_.has_java_outer_classname(descriptor_->file()->name()));
-
-#if 0
- GOOGLE_LOG(INFO) << "is_own_file=" << is_own_file;
- GOOGLE_LOG(INFO) << "containing_type()=" << ((descriptor_->containing_type() == NULL) ? "NULL" : "not null");
- GOOGLE_LOG(INFO) << "java_multiple_files()=" << params_.java_multiple_files();
- GOOGLE_LOG(INFO) << "has_java_outer_classname()=" << params_.has_java_outer_classname(file_->name());
-#endif
-
- if ((descriptor_->extension_count() != 0)
- || (descriptor_->extension_range_count() != 0)) {
- GOOGLE_LOG(FATAL) << "Extensions not supported in MICRO_RUNTIME\n";
- }
-
- printer->Print(
- "public $modifiers$ final class $classname$ extends\n"
- " com.google.protobuf.micro.MessageMicro {\n",
- "modifiers", is_own_file ? "" : "static",
- "classname", descriptor_->name());
- printer->Indent();
- printer->Print(
- "public $classname$() {}\n"
- "\n",
- "classname", descriptor_->name());
-
- // Nested types and extensions
- for (int i = 0; i < descriptor_->enum_type_count(); i++) {
- EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
- }
-
- for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
- }
-
- // Fields
- for (int i = 0; i < descriptor_->field_count(); i++) {
- PrintFieldComment(printer, descriptor_->field(i));
- printer->Print("public static final int $constant_name$ = $number$;\n",
- "constant_name", FieldConstantName(descriptor_->field(i)),
- "number", SimpleItoa(descriptor_->field(i)->number()));
- field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
- printer->Print("\n");
- }
-
- GenerateClear(printer);
- GenerateIsInitialized(printer);
- GenerateMessageSerializationMethods(printer);
- GenerateMergeFromMethods(printer);
- GenerateParseFromMethods(printer);
-
- printer->Outdent();
- printer->Print("}\n\n");
-}
-
-// ===================================================================
-
-void MessageGenerator::
-GenerateMessageSerializationMethods(io::Printer* printer) {
- scoped_array<const FieldDescriptor*> sorted_fields(
- SortFieldsByNumber(descriptor_));
-
- if (descriptor_->extension_range_count() != 0) {
- GOOGLE_LOG(FATAL) << "Extensions not supported in MICRO_RUNTIME\n";
- }
-
- printer->Print(
- "public void writeTo(com.google.protobuf.micro.CodedOutputStreamMicro output)\n"
- " throws java.io.IOException {\n");
- printer->Indent();
-
- // Output the fields in sorted order
- for (int i = 0; i < descriptor_->field_count(); i++) {
- GenerateSerializeOneField(printer, sorted_fields[i]);
- }
-
- printer->Outdent();
- printer->Print(
- "}\n"
- "\n"
- "private int cachedSize = -1;\n"
- "public int getCachedSize() {\n"
- " if (cachedSize < 0) {\n"
- " // getSerializedSize sets cachedSize\n"
- " getSerializedSize();\n"
- " }\n"
- " return cachedSize;\n"
- "}\n"
- "\n"
- "public int getSerializedSize() {\n"
- " int size = 0;\n");
- printer->Indent();
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
- }
-
- printer->Outdent();
- printer->Print(
- " cachedSize = size;\n"
- " return size;\n"
- "}\n"
- "\n");
-}
-
-void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
- scoped_array<const FieldDescriptor*> sorted_fields(
- SortFieldsByNumber(descriptor_));
-
- if (params_.java_use_vector()) {
- printer->Print(
- "public com.google.protobuf.micro.MessageMicro mergeFrom(\n"
- " com.google.protobuf.micro.CodedInputStreamMicro input)\n"
- " throws java.io.IOException {\n",
- "classname", descriptor_->name());
- } else {
- printer->Print(
- "public $classname$ mergeFrom(\n"
- " com.google.protobuf.micro.CodedInputStreamMicro input)\n"
- " throws java.io.IOException {\n",
- "classname", descriptor_->name());
- }
- printer->Indent();
-
- printer->Print(
- "while (true) {\n");
- printer->Indent();
-
- printer->Print(
- "int tag = input.readTag();\n"
- "switch (tag) {\n");
- printer->Indent();
-
- printer->Print(
- "case 0:\n" // zero signals EOF / limit reached
- " return this;\n"
- "default: {\n"
- " if (!parseUnknownField(input, tag)) {\n"
- " return this;\n" // it's an endgroup tag
- " }\n"
- " break;\n"
- "}\n");
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = sorted_fields[i];
- uint32 tag = WireFormatLite::MakeTag(field->number(),
- WireFormat::WireTypeForField(field));
-
- printer->Print(
- "case $tag$: {\n",
- "tag", SimpleItoa(tag));
- printer->Indent();
-
- field_generators_.get(field).GenerateParsingCode(printer);
-
- printer->Outdent();
- printer->Print(
- " break;\n"
- "}\n");
- }
-
- printer->Outdent();
- printer->Outdent();
- printer->Outdent();
- printer->Print(
- " }\n" // switch (tag)
- " }\n" // while (true)
- "}\n"
- "\n");
-}
-
-void MessageGenerator::
-GenerateParseFromMethods(io::Printer* printer) {
- bool is_own_file =
- descriptor_->containing_type() == NULL;
-
- // Note: These are separate from GenerateMessageSerializationMethods()
- // because they need to be generated even for messages that are optimized
- // for code size.
- printer->Print(
- "public $static$ $classname$ parseFrom(byte[] data)\n"
- " throws com.google.protobuf.micro.InvalidProtocolBufferMicroException {\n"
- " return ($classname$) (new $classname$().mergeFrom(data));\n"
- "}\n"
- "\n"
- "public $static$ $classname$ parseFrom(\n"
- " com.google.protobuf.micro.CodedInputStreamMicro input)\n"
- " throws java.io.IOException {\n"
- " return ($classname$) (new $classname$().mergeFrom(input));\n"
- "}\n"
- "\n",
- "static", (is_own_file ? "static" : ""),
- "classname", descriptor_->name());
-}
-
-void MessageGenerator::GenerateSerializeOneField(
- io::Printer* printer, const FieldDescriptor* field) {
- field_generators_.get(field).GenerateSerializationCode(printer);
-}
-
-void MessageGenerator::GenerateClear(io::Printer* printer) {
- printer->Print(
- "public final $classname$ clear() {\n",
- "classname", descriptor_->name());
- printer->Indent();
-
- // Call clear for all of the fields.
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = descriptor_->field(i);
-
- printer->Print(
- "clear$name$();\n",
- "name", UnderscoresToCapitalizedCamelCase(field));
- }
-
- printer->Outdent();
- printer->Print(
- " cachedSize = -1;\n"
- " return this;\n"
- "}\n"
- "\n");
-}
-
-
-void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
- printer->Print(
- "public final boolean isInitialized() {\n");
- printer->Indent();
-
- // Check that all required fields in this message are set.
- // TODO(kenton): We can optimize this when we switch to putting all the
- // "has" fields into a single bitfield.
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = descriptor_->field(i);
-
- if (field->is_required()) {
- printer->Print(
- "if (!has$name$) return false;\n",
- "name", UnderscoresToCapitalizedCamelCase(field));
- }
- }
-
- // 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 &&
- HasRequiredFields(field->message_type())) {
- switch (field->label()) {
- case FieldDescriptor::LABEL_REQUIRED:
- printer->Print(
- "if (!get$name$().isInitialized()) return false;\n",
- "type", ClassName(params_, field->message_type()),
- "name", UnderscoresToCapitalizedCamelCase(field));
- break;
- case FieldDescriptor::LABEL_OPTIONAL:
- printer->Print(
- "if (has$name$()) {\n"
- " if (!get$name$().isInitialized()) return false;\n"
- "}\n",
- "type", ClassName(params_, field->message_type()),
- "name", UnderscoresToCapitalizedCamelCase(field));
- break;
- case FieldDescriptor::LABEL_REPEATED:
- if (params_.java_use_vector()) {
- printer->Print(
- "for (int i = 0; i < get$name$List().size(); i++) {\n"
- " if (get$name$(i).isInitialized()) return false;\n"
- "}\n",
- "type", ClassName(params_, field->message_type()),
- "name", UnderscoresToCapitalizedCamelCase(field));
- } else {
- printer->Print(
- "for ($type$ element : get$name$List()) {\n"
- " if (!element.isInitialized()) return false;\n"
- "}\n",
- "type", ClassName(params_, field->message_type()),
- "name", UnderscoresToCapitalizedCamelCase(field));
- }
- break;
- }
- }
- }
-
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- "if (!extensionsAreInitialized()) return false;\n");
- }
-
- printer->Outdent();
- printer->Print(
- " return true;\n"
- "}\n"
- "\n");
-}
-
-// ===================================================================
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_message.h b/src/google/protobuf/compiler/javamicro/javamicro_message.h
deleted file mode 100644
index f44c7a7..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_message.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
-
-#include <string>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javamicro/javamicro_params.h>
-#include <google/protobuf/compiler/javamicro/javamicro_field.h>
-
-namespace google {
-namespace protobuf {
- namespace io {
- class Printer; // printer.h
- }
-}
-
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-class MessageGenerator {
- public:
- explicit MessageGenerator(const Descriptor* descriptor, const Params& params);
- ~MessageGenerator();
-
- // All static variables have to be declared at the top-level of the file
- // so that we can control initialization order, which is important for
- // DescriptorProto bootstrapping to work.
- void GenerateStaticVariables(io::Printer* printer);
-
- // Output code which initializes the static variables generated by
- // GenerateStaticVariables().
- void GenerateStaticVariableInitializers(io::Printer* printer);
-
- // Generate the class itself.
- void Generate(io::Printer* printer);
-
- private:
- void GenerateMessageSerializationMethods(io::Printer* printer);
- void GenerateMergeFromMethods(io::Printer* printer);
- void GenerateParseFromMethods(io::Printer* printer);
- void GenerateSerializeOneField(io::Printer* printer,
- const FieldDescriptor* field);
-
- void GenerateClear(io::Printer* printer);
- void GenerateIsInitialized(io::Printer* printer);
-
- const Params& params_;
- const Descriptor* descriptor_;
- FieldGeneratorMap field_generators_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
-};
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_message_field.cc b/src/google/protobuf/compiler/javamicro/javamicro_message_field.cc
deleted file mode 100644
index 103c302..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_message_field.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <map>
-#include <string>
-
-#include <google/protobuf/compiler/javamicro/javamicro_message_field.h>
-#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-namespace {
-
-// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
-// repeat code between this and the other field types.
-void SetMessageVariables(const Params& params,
- const FieldDescriptor* descriptor, map<string, string>* variables) {
- (*variables)["name"] =
- UnderscoresToCamelCase(descriptor);
- (*variables)["capitalized_name"] =
- UnderscoresToCapitalizedCamelCase(descriptor);
- (*variables)["number"] = SimpleItoa(descriptor->number());
- (*variables)["type"] = ClassName(params, descriptor->message_type());
- (*variables)["group_or_message"] =
- (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
- "Group" : "Message";
- (*variables)["message_name"] = descriptor->containing_type()->name();
- //(*variables)["message_type"] = descriptor->message_type()->name();
-}
-
-} // namespace
-
-// ===================================================================
-
-MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
- : FieldGenerator(params), descriptor_(descriptor) {
- SetMessageVariables(params, descriptor, &variables_);
-}
-
-MessageFieldGenerator::~MessageFieldGenerator() {}
-
-void MessageFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
- printer->Print(variables_,
- "private boolean has$capitalized_name$;\n"
-// "private $type$ $name$_ = null;\n"
-// "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
-// "public $type$ get$capitalized_name$() { return $name$_; }\n"
- "private $type$ $name$_ = null;\n"
- "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
- "public $type$ get$capitalized_name$() { return $name$_; }\n"
- "public $message_name$ set$capitalized_name$($type$ value) {\n"
- " if (value == null) {\n"
- " throw new NullPointerException();\n"
- " }\n"
- " has$capitalized_name$ = true;\n"
- " $name$_ = value;\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " has$capitalized_name$ = false;\n"
- " $name$_ = null;\n"
- " return this;\n"
- "}\n");
-}
-
-void MessageFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (other.has$capitalized_name$()) {\n"
- " merge$capitalized_name$(other.get$capitalized_name$());\n"
- "}\n");
-}
-
-void MessageFieldGenerator::
-GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "$type$ value = new $type$();\n");
-
- if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
- printer->Print(variables_,
- "input.readGroup(value, $number$);\n");
- } else {
- printer->Print(variables_,
- "input.readMessage(value);\n");
- }
-
- printer->Print(variables_,
- "set$capitalized_name$(value);\n");
-}
-
-void MessageFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (has$capitalized_name$()) {\n"
- " output.write$group_or_message$($number$, get$capitalized_name$());\n"
- "}\n");
-}
-
-void MessageFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (has$capitalized_name$()) {\n"
- " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
- "}\n");
-}
-
-string MessageFieldGenerator::GetBoxedType() const {
- return ClassName(params_, descriptor_->message_type());
-}
-
-// ===================================================================
-
-RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
- : FieldGenerator(params), descriptor_(descriptor) {
- SetMessageVariables(params, descriptor, &variables_);
-}
-
-RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
-
-void RepeatedMessageFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "private java.util.Vector $name$_ = new java.util.Vector();\n"
- "public java.util.Vector get$capitalized_name$List() {\n"
- " return $name$_;\n"
- "}\n"
- "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
- "public $type$ get$capitalized_name$(int index) {\n"
- " return ($type$) $name$_.elementAt(index);\n"
- "}\n"
- "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
- " if (value == null) {\n"
- " throw new NullPointerException();\n"
- " }\n"
- " $name$_.setElementAt(value, index);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ add$capitalized_name$($type$ value) {\n"
- " if (value == null) {\n"
- " throw new NullPointerException();\n"
- " }\n"
- " $name$_.addElement(value);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " $name$_.removeAllElements();\n"
- " return this;\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "private java.util.List<$type$> $name$_ =\n"
- " java.util.Collections.emptyList();\n"
- "public java.util.List<$type$> get$capitalized_name$List() {\n"
- " return $name$_;\n"
- "}\n"
- "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
- "public $type$ get$capitalized_name$(int index) {\n"
- " return $name$_.get(index);\n"
- "}\n"
- "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
- " if (value == null) {\n"
- " throw new NullPointerException();\n"
- " }\n"
- " $name$_.set(index, value);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ add$capitalized_name$($type$ value) {\n"
- " if (value == null) {\n"
- " throw new NullPointerException();\n"
- " }\n"
- " if ($name$_.isEmpty()) {\n"
- " $name$_ = new java.util.ArrayList<$type$>();\n"
- " }\n"
- " $name$_.add(value);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " $name$_ = java.util.Collections.emptyList();\n"
- " return this;\n"
- "}\n");
- }
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "if (other.$name$_.size() != 0) {\n"
- " for (int i = 0; i < other.$name$_.size(); i++) {\n"
- " result.$name$_.addElement(other.$name$_.elementAt(i));\n"
- " }\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "if (!other.$name$_.isEmpty()) {\n"
- " if (result.$name$_.isEmpty()) {\n"
- " result.$name$_ = new java.util.ArrayList<$type$>();\n"
- " }\n"
- " result.$name$_.addAll(other.$name$_);\n"
- "}\n");
- }
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "$type$ value = new $type$();\n");
-
- if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
- printer->Print(variables_,
- "input.readGroup(value, $number$);\n");
- } else {
- printer->Print(variables_,
- "input.readMessage(value);\n");
- }
-
- printer->Print(variables_,
- "add$capitalized_name$(value);\n");
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
- " output.write$group_or_message$($number$, get$capitalized_name$(i));\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " output.write$group_or_message$($number$, element);\n"
- "}\n");
- }
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
- " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .compute$group_or_message$Size($number$, get$capitalized_name$(i));\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .compute$group_or_message$Size($number$, element);\n"
- "}\n");
- }
-}
-
-string RepeatedMessageFieldGenerator::GetBoxedType() const {
- return ClassName(params_, descriptor_->message_type());
-}
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_message_field.h b/src/google/protobuf/compiler/javamicro/javamicro_message_field.h
deleted file mode 100644
index a32aa4e..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_message_field.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
-
-#include <map>
-#include <string>
-#include <google/protobuf/compiler/javamicro/javamicro_field.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-class MessageFieldGenerator : public FieldGenerator {
- public:
- explicit MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
- ~MessageFieldGenerator();
-
- // implements FieldGenerator ---------------------------------------
- void GenerateMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
- void GenerateParsingCode(io::Printer* printer) const;
- void GenerateSerializationCode(io::Printer* printer) const;
- void GenerateSerializedSizeCode(io::Printer* printer) const;
-
- string GetBoxedType() const;
-
- private:
- const FieldDescriptor* descriptor_;
- map<string, string> variables_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
-};
-
-class RepeatedMessageFieldGenerator : public FieldGenerator {
- public:
- explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
- const Params& params);
- ~RepeatedMessageFieldGenerator();
-
- // implements FieldGenerator ---------------------------------------
- void GenerateMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
- void GenerateParsingCode(io::Printer* printer) const;
- void GenerateSerializationCode(io::Printer* printer) const;
- void GenerateSerializedSizeCode(io::Printer* printer) const;
-
- string GetBoxedType() const;
-
- private:
- const FieldDescriptor* descriptor_;
- map<string, string> variables_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
-};
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_params.h b/src/google/protobuf/compiler/javamicro/javamicro_params.h
deleted file mode 100644
index a4a72b7..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_params.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2010 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: wink@google.com (Wink Saville)
-
-#ifndef PROTOBUF_COMPILER_JAVAMICRO_JAVAMICRO_PARAMS_H_
-#define PROTOBUF_COMPILER_JAVAMICRO_JAVAMICRO_PARAMS_H_
-
-#include <map>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-enum eOptimization { JAVAMICRO_OPT_SPEED, JAVAMICRO_OPT_SPACE, JAVAMICRO_OPT_DEFAULT = JAVAMICRO_OPT_SPACE };
-
-// Parameters for used by the generators
-class Params {
- public:
- typedef map<string, string> NameMap;
- private:
- string empty_;
- string base_name_;
- eOptimization optimization_;
- bool java_multiple_files_;
- bool java_use_vector_;
- NameMap java_packages_;
- NameMap java_outer_classnames_;
-
- public:
- Params(const string & base_name) :
- empty_(""),
- base_name_(base_name),
- optimization_(JAVAMICRO_OPT_DEFAULT),
- java_multiple_files_(false),
- java_use_vector_(false) {
- }
-
- const string& base_name() const {
- return base_name_;
- }
-
- bool has_java_package(const string& file_name) const {
- return java_packages_.find(file_name)
- != java_packages_.end();
- }
- void set_java_package(const string& file_name,
- const string& java_package) {
- java_packages_[file_name] = java_package;
- }
- const string& java_package(const string& file_name) const {
- NameMap::const_iterator itr;
-
- itr = java_packages_.find(file_name);
- if (itr == java_packages_.end()) {
- return empty_;
- } else {
- return itr->second;
- }
- }
- const NameMap& java_packages() {
- return java_packages_;
- }
-
- bool has_java_outer_classname(const string& file_name) const {
- return java_outer_classnames_.find(file_name)
- != java_outer_classnames_.end();
- }
- void set_java_outer_classname(const string& file_name,
- const string& java_outer_classname) {
- java_outer_classnames_[file_name] = java_outer_classname;
- }
- const string& java_outer_classname(const string& file_name) const {
- NameMap::const_iterator itr;
-
- itr = java_outer_classnames_.find(file_name);
- if (itr == java_outer_classnames_.end()) {
- return empty_;
- } else {
- return itr->second;
- }
- }
- const NameMap& java_outer_classnames() {
- return java_outer_classnames_;
- }
-
- void set_optimization(eOptimization optimization) {
- optimization_ = optimization;
- }
- eOptimization optimization() const {
- return optimization_;
- }
-
- void set_java_multiple_files(bool value) {
- java_multiple_files_ = value;
- }
- bool java_multiple_files() const {
- return java_multiple_files_;
- }
-
- void set_java_use_vector(bool value) {
- java_use_vector_ = value;
- }
- bool java_use_vector() const {
- return java_use_vector_;
- }
-
-};
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
-#endif // PROTOBUF_COMPILER_JAVAMICRO_JAVAMICRO_PARAMS_H_
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc b/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc
deleted file mode 100644
index d6daa44..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc
+++ /dev/null
@@ -1,660 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#include <map>
-#include <string>
-
-#include <google/protobuf/compiler/javamicro/javamicro_primitive_field.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-using internal::WireFormat;
-using internal::WireFormatLite;
-
-namespace {
-
-const char* PrimitiveTypeName(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return "int";
- case JAVATYPE_LONG : return "long";
- case JAVATYPE_FLOAT : return "float";
- case JAVATYPE_DOUBLE : return "double";
- case JAVATYPE_BOOLEAN: return "boolean";
- case JAVATYPE_STRING : return "java.lang.String";
- case JAVATYPE_BYTES : return "com.google.protobuf.micro.ByteStringMicro";
- case JAVATYPE_ENUM : return NULL;
- case JAVATYPE_MESSAGE: return NULL;
-
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return NULL;
-}
-
-bool IsReferenceType(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return false;
- case JAVATYPE_LONG : return false;
- case JAVATYPE_FLOAT : return false;
- case JAVATYPE_DOUBLE : return false;
- case JAVATYPE_BOOLEAN: return false;
- case JAVATYPE_STRING : return true;
- case JAVATYPE_BYTES : return true;
- case JAVATYPE_ENUM : return false;
- case JAVATYPE_MESSAGE: return true;
-
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return false;
-}
-
-const char* GetCapitalizedType(const FieldDescriptor* field) {
- switch (field->type()) {
- case FieldDescriptor::TYPE_INT32 : return "Int32" ;
- case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
- case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
- case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
- case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
- case FieldDescriptor::TYPE_INT64 : return "Int64" ;
- case FieldDescriptor::TYPE_UINT64 : return "UInt64" ;
- case FieldDescriptor::TYPE_SINT64 : return "SInt64" ;
- case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
- case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
- case FieldDescriptor::TYPE_FLOAT : return "Float" ;
- case FieldDescriptor::TYPE_DOUBLE : return "Double" ;
- case FieldDescriptor::TYPE_BOOL : return "Bool" ;
- case FieldDescriptor::TYPE_STRING : return "String" ;
- case FieldDescriptor::TYPE_BYTES : return "Bytes" ;
- case FieldDescriptor::TYPE_ENUM : return "Enum" ;
- case FieldDescriptor::TYPE_GROUP : return "Group" ;
- case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
-
- // No default because we want the compiler to complain if any new
- // types are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return NULL;
-}
-
-// For encodings with fixed sizes, returns that size in bytes. Otherwise
-// returns -1.
-int FixedSize(FieldDescriptor::Type type) {
- switch (type) {
- case FieldDescriptor::TYPE_INT32 : return -1;
- case FieldDescriptor::TYPE_INT64 : return -1;
- case FieldDescriptor::TYPE_UINT32 : return -1;
- case FieldDescriptor::TYPE_UINT64 : return -1;
- case FieldDescriptor::TYPE_SINT32 : return -1;
- case FieldDescriptor::TYPE_SINT64 : return -1;
- case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
- case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
- case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
- case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
- case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
- case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
-
- case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
- case FieldDescriptor::TYPE_ENUM : return -1;
-
- case FieldDescriptor::TYPE_STRING : return -1;
- case FieldDescriptor::TYPE_BYTES : return -1;
- case FieldDescriptor::TYPE_GROUP : return -1;
- case FieldDescriptor::TYPE_MESSAGE : return -1;
-
- // No default because we want the compiler to complain if any new
- // types are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return -1;
-}
-
-// Return true if the type is a that has variable length
-// for instance String's.
-bool IsVariableLenType(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return false;
- case JAVATYPE_LONG : return false;
- case JAVATYPE_FLOAT : return false;
- case JAVATYPE_DOUBLE : return false;
- case JAVATYPE_BOOLEAN: return false;
- case JAVATYPE_STRING : return true;
- case JAVATYPE_BYTES : return true;
- case JAVATYPE_ENUM : return false;
- case JAVATYPE_MESSAGE: return true;
-
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return false;
-}
-
-bool IsStringUtf8Handling(const FieldDescriptor* descriptor,
- const Params params) {
- return ((params.optimization() == JAVAMICRO_OPT_SPEED)
- && (GetJavaType(descriptor) == JAVATYPE_STRING));
-}
-
-void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
- map<string, string>* variables) {
- (*variables)["name"] =
- UnderscoresToCamelCase(descriptor);
- (*variables)["capitalized_name"] =
- UnderscoresToCapitalizedCamelCase(descriptor);
- (*variables)["number"] = SimpleItoa(descriptor->number());
- if (IsStringUtf8Handling(descriptor, params)) {
- (*variables)["type"] = "com.google.protobuf.micro.StringUtf8Micro";
- string defaultValue = DefaultValue(params, descriptor);
- if (defaultValue == "\"\"") {
- (*variables)["default"] =
- "com.google.protobuf.micro.StringUtf8Micro.EMPTY";
- } else {
- (*variables)["default"] = "new com.google.protobuf.micro.StringUtf8Micro("
- + defaultValue + ")";
- }
- } else {
- (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
- (*variables)["default"] = DefaultValue(params, descriptor);
- }
- (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
- (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
- (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
- (*variables)["tag_size"] = SimpleItoa(
- WireFormat::TagSize(descriptor->number(), descriptor->type()));
- if (IsReferenceType(GetJavaType(descriptor))) {
- (*variables)["null_check"] =
- " if (value == null) {\n"
- " throw new NullPointerException();\n"
- " }\n";
- } else {
- (*variables)["null_check"] = "";
- }
- int fixed_size = FixedSize(descriptor->type());
- if (fixed_size != -1) {
- (*variables)["fixed_size"] = SimpleItoa(fixed_size);
- }
- (*variables)["message_name"] = descriptor->containing_type()->name();
-}
-} // namespace
-
-// ===================================================================
-
-PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
- : FieldGenerator(params), descriptor_(descriptor) {
- SetPrimitiveVariables(descriptor, params, &variables_);
-}
-
-PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
-
-void PrimitiveFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
- printer->Print(variables_,
- "private boolean has$capitalized_name$;\n"
- "private $type$ $name$_ = $default$;\n"
- "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n");
- if (IsStringUtf8Handling(descriptor_, params_)) {
- printer->Print(variables_,
- "public String get$capitalized_name$() { return $name$_.getString(); }\n"
- "public $type$ get$capitalized_name$StringUtf8() { return $name$_; }\n"
- "public $message_name$ set$capitalized_name$(String value) {\n"
- " has$capitalized_name$ = true;\n"
- " if ($name$_ == $default$) {\n"
- " $name$_ = new $type$(value);\n"
- " } else {\n"
- " $name$_.setString(value);\n"
- " }\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " has$capitalized_name$ = false;\n"
- " $name$_ = $default$;\n"
- " return this;\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "public $type$ get$capitalized_name$() { return $name$_; }\n");
- if (IsVariableLenType(GetJavaType(descriptor_))) {
- printer->Print(variables_,
- "public $message_name$ set$capitalized_name$($type$ value) {\n"
- " has$capitalized_name$ = true;\n"
- " $name$_ = value;\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " has$capitalized_name$ = false;\n"
- " $name$_ = $default$;\n"
- " return this;\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "public $message_name$ set$capitalized_name$($type$ value) {\n"
- " has$capitalized_name$ = true;\n"
- " $name$_ = value;\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " has$capitalized_name$ = false;\n"
- " $name$_ = $default$;\n"
- " return this;\n"
- "}\n");
- }
- }
-}
-
-void PrimitiveFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (other.has$capitalized_name$()) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
- "}\n");
-}
-
-void PrimitiveFieldGenerator::
-GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "set$capitalized_name$(input.read$capitalized_type$());\n");
-}
-
-void PrimitiveFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
- if (IsStringUtf8Handling(descriptor_, params_)) {
- printer->Print(variables_,
- "if (has$capitalized_name$()) {\n"
- " output.writeStringUtf8($number$, get$capitalized_name$StringUtf8());\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "if (has$capitalized_name$()) {\n"
- " output.write$capitalized_type$($number$, get$capitalized_name$());\n"
- "}\n");
- }
-}
-
-void PrimitiveFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
- if (IsStringUtf8Handling(descriptor_, params_)) {
- printer->Print(variables_,
- "if (has$capitalized_name$()) {\n"
- " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .computeStringUtf8Size($number$, get$capitalized_name$StringUtf8());\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "if (has$capitalized_name$()) {\n"
- " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .compute$capitalized_type$Size($number$, get$capitalized_name$());\n"
- "}\n");
- }
-}
-
-string PrimitiveFieldGenerator::GetBoxedType() const {
- return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
-}
-
-// ===================================================================
-
-RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
- : FieldGenerator(params), descriptor_(descriptor) {
- SetPrimitiveVariables(descriptor, params, &variables_);
- if (descriptor_->options().packed()) {
- GOOGLE_LOG(FATAL) << "MicroRuntime does not support packed";
- }
-}
-
-RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
- if (IsStringUtf8Handling(descriptor_, params_)) {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "private java.util.Vector $name$_ = new java.util.Vector();\n"
- "public java.util.Vector get$capitalized_name$List() {\n"
- " return $name$_;\n"
- "}\n"
- "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
- "public String get$capitalized_name$(int index) {\n"
- " return (($type$)$name$_.elementAt(index)).getString();\n"
- "}\n"
- "public $type$ get$capitalized_name$StringUtf8(int index) {\n"
- " return ($type$)$name$_.elementAt(index);\n"
- "}\n"
- "public $message_name$ set$capitalized_name$(int index, String value) {\n"
- "$null_check$"
- " $name$_.setElementAt(new $type$(value), index);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ add$capitalized_name$(String value) {\n"
- "$null_check$"
- " $name$_.addElement(new $type$(value));\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " $name$_.removeAllElements();\n"
- " return this;\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "private java.util.List<$type$> $name$_ =\n"
- " java.util.Collections.emptyList();\n"
- "public java.util.List<$type$> get$capitalized_name$List() {\n"
- " return $name$_;\n" // note: unmodifiable list
- "}\n"
- "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
- "public String get$capitalized_name$(int index) {\n"
- " return $name$_.get(index).getString();\n"
- "}\n"
- "public $message_name$ set$capitalized_name$(int index, String value) {\n"
- "$null_check$"
- " $name$_.set(index, new $type$(value));\n"
- " return this;\n"
- "}\n"
- "public $message_name$ add$capitalized_name$(String value) {\n"
- "$null_check$"
- " if ($name$_.isEmpty()) {\n"
- " $name$_ = new java.util.ArrayList<$type$>();\n"
- " }\n"
- " $name$_.add(new $type$(value));\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " $name$_ = java.util.Collections.emptyList();\n"
- " return this;\n"
- "}\n");
- }
- } else if (params_.java_use_vector()) {
- if (IsReferenceType(GetJavaType(descriptor_))) {
- printer->Print(variables_,
- "private java.util.Vector $name$_ = new java.util.Vector();\n"
- "public java.util.Vector get$capitalized_name$List() {\n"
- " return $name$_;\n"
- "}\n"
- "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
- "public $type$ get$capitalized_name$(int index) {\n"
- " return ($type$) $name$_.elementAt(index);\n"
- "}\n"
- "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
- "$null_check$"
- " $name$_.setElementAt(value, index);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ add$capitalized_name$($type$ value) {\n"
- "$null_check$"
- " $name$_.addElement(value);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " $name$_.removeAllElements();\n"
- " return this;\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "private java.util.Vector $name$_ = new java.util.Vector();\n"
- "public java.util.Vector get$capitalized_name$List() {\n"
- " return $name$_;\n"
- "}\n"
- "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
- "public $type$ get$capitalized_name$(int index) {\n"
- " return (($boxed_type$)$name$_.elementAt(index)).$type$Value();\n"
- "}\n"
- "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
- "$null_check$"
- " $name$_.setElementAt(new $boxed_type$(value), index);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ add$capitalized_name$($type$ value) {\n"
- "$null_check$"
- " $name$_.addElement(new $boxed_type$(value));\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " $name$_.removeAllElements();\n"
- " return this;\n"
- "}\n");
- }
- } else {
- printer->Print(variables_,
- "private java.util.List<$boxed_type$> $name$_ =\n"
- " java.util.Collections.emptyList();\n"
- "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n"
- " return $name$_;\n" // note: unmodifiable list
- "}\n"
- "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
- "public $type$ get$capitalized_name$(int index) {\n"
- " return $name$_.get(index);\n"
- "}\n"
- "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
- "$null_check$"
- " $name$_.set(index, value);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ add$capitalized_name$($type$ value) {\n"
- "$null_check$"
- " if ($name$_.isEmpty()) {\n"
- " $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
- " }\n"
- " $name$_.add(value);\n"
- " return this;\n"
- "}\n"
- "public $message_name$ clear$capitalized_name$() {\n"
- " $name$_ = java.util.Collections.emptyList();\n"
- " return this;\n"
- "}\n");
- }
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "private int $name$MemoizedSerializedSize;\n");
- }
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateMergingCode(io::Printer* printer) const {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "if (other.$name$_.size() != 0) {\n"
- " for (int i = 0; i < other.$name$_.size(); i++)) {\n"
- " result.$name$_.addElement(other.$name$_.elementAt(i));\n"
- " }\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "if (!other.$name$_.isEmpty()) {\n"
- " if (result.$name$_.isEmpty()) {\n"
- " result.$name$_ = new java.util.ArrayList<$type$>();\n"
- " }\n"
- " result.$name$_.addAll(other.$name$_);\n"
- "}\n");
- }
-}
-
-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");
- }
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateSerializationCode(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "if (get$capitalized_name$List().size() > 0) {\n"
- " output.writeRawVarint32($tag$);\n"
- " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
- "}\n");
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
- " output.write$capitalized_type$NoTag(get$capitalized_name$(i));\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " output.write$capitalized_type$NoTag(element);\n"
- "}\n");
- }
- } else {
- if (params_.java_use_vector()) {
- if (IsStringUtf8Handling(descriptor_, params_)) {
- printer->Print(variables_,
- "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
- " output.writeStringUtf8($number$, get$capitalized_name$StringUtf8(i));\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
- " output.write$capitalized_type$($number$, get$capitalized_name$(i));\n"
- "}\n");
- }
- } else {
- if (IsStringUtf8Handling(descriptor_, params_)) {
- printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " output.writeStringUtf8($number$, element);\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " output.write$capitalized_type$($number$, element);\n"
- "}\n");
- }
- }
- }
-}
-
-void RepeatedPrimitiveFieldGenerator::
-GenerateSerializedSizeCode(io::Printer* printer) const {
- printer->Print(variables_,
- "{\n"
- " int dataSize = 0;\n");
- printer->Indent();
-
- if (FixedSize(descriptor_->type()) == -1) {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
- " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n");
- if (IsStringUtf8Handling(descriptor_, params_)) {
- printer->Print(variables_,
- " .computeStringUtf8SizeNoTag(get$capitalized_name$StringUtf8(i));\n"
- "}\n");
- } else {
- printer->Print(variables_,
- " .compute$capitalized_type$SizeNoTag(($type$)get$capitalized_name$(i));\n"
- "}\n");
- }
- } else {
- printer->Print(variables_,
- "for ($type$ element : get$capitalized_name$List()) {\n"
- " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n");
- if (IsStringUtf8Handling(descriptor_, params_)) {
- printer->Print(variables_,
- " .computeStringUtf8SizeNoTag(element);\n"
- "}\n");
- } else {
- printer->Print(variables_,
- " .compute$capitalized_type$SizeNoTag(element);\n"
- "}\n");
- }
- }
- } else {
- printer->Print(variables_,
- "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
- }
-
- printer->Print(
- "size += dataSize;\n");
-
- if (descriptor_->options().packed()) {
- if (params_.java_use_vector()) {
- printer->Print(variables_,
- "if (get$capitalized_name$List().size() != 0) {\n");
- } else {
- printer->Print(variables_,
- "if (!get$capitalized_name$List().isEmpty()) {\n");
- }
- printer->Print(variables_,
- " size += $tag_size$;\n"
- " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
- " .computeInt32SizeNoTag(dataSize);\n"
- "}\n");
- } else {
- printer->Print(variables_,
- "size += $tag_size$ * get$capitalized_name$List().size();\n");
- }
-
- // cache the data size for packed fields.
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "$name$MemoizedSerializedSize = dataSize;\n");
- }
-
- printer->Outdent();
- printer->Print("}\n");
-}
-
-string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
- return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
-}
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.h b/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.h
deleted file mode 100644
index 88d8eec..0000000
--- a/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVAMICRO_PRIMITIVE_FIELD_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVAMICRO_PRIMITIVE_FIELD_H__
-
-#include <map>
-#include <string>
-#include <google/protobuf/compiler/javamicro/javamicro_field.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-class PrimitiveFieldGenerator : public FieldGenerator {
- public:
- explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params &params);
- ~PrimitiveFieldGenerator();
-
- // implements FieldGenerator ---------------------------------------
- void GenerateMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
- void GenerateParsingCode(io::Printer* printer) const;
- void GenerateSerializationCode(io::Printer* printer) const;
- void GenerateSerializedSizeCode(io::Printer* printer) const;
-
- string GetBoxedType() const;
-
- private:
- const FieldDescriptor* descriptor_;
- map<string, string> variables_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
-};
-
-class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
- public:
- explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
- ~RepeatedPrimitiveFieldGenerator();
-
- // implements FieldGenerator ---------------------------------------
- void GenerateMembers(io::Printer* printer) const;
- void GenerateMergingCode(io::Printer* printer) const;
- void GenerateParsingCode(io::Printer* printer) const;
- void GenerateSerializationCode(io::Printer* printer) const;
- void GenerateSerializedSizeCode(io::Printer* printer) const;
-
- string GetBoxedType() const;
-
- private:
- const FieldDescriptor* descriptor_;
- map<string, string> variables_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
-};
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_COMPILER_JAVAMICRO_PRIMITIVE_FIELD_H__
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 41dc5b9..d9b0c3f 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -34,12 +34,12 @@
#include <google/protobuf/compiler/cpp/cpp_generator.h>
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/compiler/java/java_generator.h>
-#include <google/protobuf/compiler/javamicro/javamicro_generator.h>
int main(int argc, char* argv[]) {
google::protobuf::compiler::CommandLineInterface cli;
+ cli.AllowPlugins("protoc-");
// Proto2 C++
google::protobuf::compiler::cpp::CppGenerator cpp_generator;
@@ -57,10 +57,5 @@ int main(int argc, char* argv[]) {
cli.RegisterGenerator("--python_out", &py_generator,
"Generate Python source file.");
- // Proto2 JavaMicro
- google::protobuf::compiler::javamicro::JavaMicroGenerator javamicro_generator;
- cli.RegisterGenerator("--javamicro_out", &javamicro_generator,
- "Generate Java source file micro runtime.");
-
return cli.Run(argc, argv);
}
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
new file mode 100644
index 0000000..83d5a4e
--- /dev/null
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -0,0 +1,209 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/mock_code_generator.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+static const char* kFirstInsertionPointName = "first_mock_insertion_point";
+static const char* kSecondInsertionPointName = "second_mock_insertion_point";
+static const char* kFirstInsertionPoint =
+ "# @@protoc_insertion_point(first_mock_insertion_point) is here\n";
+static const char* kSecondInsertionPoint =
+ " # @@protoc_insertion_point(second_mock_insertion_point) is here\n";
+
+MockCodeGenerator::MockCodeGenerator(const string& name)
+ : name_(name) {}
+
+MockCodeGenerator::~MockCodeGenerator() {}
+
+void MockCodeGenerator::ExpectGenerated(
+ const string& name,
+ const string& parameter,
+ const string& insertions,
+ const string& file,
+ const string& first_message_name,
+ const string& output_directory) {
+ string content;
+ ASSERT_TRUE(File::ReadFileToString(
+ output_directory + "/" + GetOutputFileName(name, file), &content));
+
+ vector<string> lines;
+ SplitStringUsing(content, "\n", &lines);
+
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+ for (int i = 0; i < lines.size(); i++) {
+ lines[i] += "\n";
+ }
+
+ vector<string> insertion_list;
+ if (!insertions.empty()) {
+ SplitStringUsing(insertions, ",", &insertion_list);
+ }
+
+ ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2);
+ EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_message_name),
+ lines[0]);
+
+ EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
+ EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]);
+
+ for (int i = 0; i < insertion_list.size(); i++) {
+ EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
+ file, first_message_name),
+ lines[1 + i]);
+ // Second insertion point is indented, so the inserted text should
+ // automatically be indented too.
+ EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert",
+ file, first_message_name),
+ lines[2 + insertion_list.size() + i]);
+ }
+}
+
+bool MockCodeGenerator::Generate(
+ const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const {
+ for (int i = 0; i < file->message_type_count(); i++) {
+ if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
+ string command = StripPrefixString(file->message_type(i)->name(),
+ "MockCodeGenerator_");
+ if (command == "Error") {
+ *error = "Saw message type MockCodeGenerator_Error.";
+ return false;
+ } else if (command == "Exit") {
+ cerr << "Saw message type MockCodeGenerator_Exit." << endl;
+ exit(123);
+ } else if (command == "Abort") {
+ cerr << "Saw message type MockCodeGenerator_Abort." << endl;
+ abort();
+ } else {
+ GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
+ }
+ }
+ }
+
+ if (HasPrefixString(parameter, "insert=")) {
+ vector<string> insert_into;
+ SplitStringUsing(StripPrefixString(parameter, "insert="),
+ ",", &insert_into);
+
+ for (int i = 0; i < insert_into.size(); i++) {
+ {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->OpenForInsert(
+ GetOutputFileName(insert_into[i], file),
+ kFirstInsertionPointName));
+ io::Printer printer(output.get(), '$');
+ printer.PrintRaw(GetOutputFileContent(name_, "first_insert", file));
+ if (printer.failed()) {
+ *error = "MockCodeGenerator detected write error.";
+ return false;
+ }
+ }
+
+ {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->OpenForInsert(
+ GetOutputFileName(insert_into[i], file),
+ kSecondInsertionPointName));
+ io::Printer printer(output.get(), '$');
+ printer.PrintRaw(GetOutputFileContent(name_, "second_insert", file));
+ if (printer.failed()) {
+ *error = "MockCodeGenerator detected write error.";
+ return false;
+ }
+ }
+ }
+ } else {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->Open(GetOutputFileName(name_, file)));
+
+ io::Printer printer(output.get(), '$');
+ printer.PrintRaw(GetOutputFileContent(name_, parameter, file));
+ printer.PrintRaw(kFirstInsertionPoint);
+ printer.PrintRaw(kSecondInsertionPoint);
+
+ if (printer.failed()) {
+ *error = "MockCodeGenerator detected write error.";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+string MockCodeGenerator::GetOutputFileName(const string& generator_name,
+ const FileDescriptor* file) {
+ return GetOutputFileName(generator_name, file->name());
+}
+
+string MockCodeGenerator::GetOutputFileName(const string& generator_name,
+ const string& file) {
+ return file + ".MockCodeGenerator." + generator_name;
+}
+
+string MockCodeGenerator::GetOutputFileContent(const string& generator_name,
+ const string& parameter,
+ const FileDescriptor* file) {
+ return GetOutputFileContent(
+ generator_name, parameter, file->name(),
+ file->message_type_count() > 0 ?
+ file->message_type(0)->name() : "(none)");
+}
+
+string MockCodeGenerator::GetOutputFileContent(
+ const string& generator_name,
+ const string& parameter,
+ const string& file,
+ const string& first_message_name) {
+ return strings::Substitute("$0: $1, $2, $3\n",
+ generator_name, parameter, file, first_message_name);
+}
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
new file mode 100644
index 0000000..01d69dd
--- /dev/null
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -0,0 +1,108 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// A mock CodeGenerator, used by command_line_interface_unittest. This is in
+// its own file so that it can be used both directly and as a plugin.
+//
+// Generate() produces some output which can be checked by ExpectCalled(). The
+// generator can run in a different process (e.g. a plugin).
+//
+// If the parameter is "insert=NAMES", the MockCodeGenerator will insert lines
+// into the files generated by other MockCodeGenerators instead of creating
+// its own file. NAMES is a comma-separated list of the names of those other
+// MockCodeGenerators.
+//
+// MockCodeGenerator will also modify its behavior slightly if the input file
+// contains a message type with one of the following names:
+// MockCodeGenerator_Error: Causes Generate() to return false and set the
+// error message to "Saw message type MockCodeGenerator_Error."
+// MockCodeGenerator_Exit: Generate() prints "Saw message type
+// MockCodeGenerator_Exit." to stderr and then calls exit(123).
+// MockCodeGenerator_Abort: Generate() prints "Saw message type
+// MockCodeGenerator_Abort." to stderr and then calls abort().
+class MockCodeGenerator : public CodeGenerator {
+ public:
+ MockCodeGenerator(const string& name);
+ virtual ~MockCodeGenerator();
+
+ // Expect (via gTest) that a MockCodeGenerator with the given name was called
+ // with the given parameters by inspecting the output location.
+ //
+ // |insertions| is a comma-separated list of names of MockCodeGenerators which
+ // should have inserted lines into this file.
+ static void ExpectGenerated(const string& name,
+ const string& parameter,
+ const string& insertions,
+ const string& file,
+ const string& first_message_name,
+ const string& output_directory);
+
+ // Get the name of the file which would be written by the given generator.
+ static string GetOutputFileName(const string& generator_name,
+ const FileDescriptor* file);
+ static string GetOutputFileName(const string& generator_name,
+ const string& file);
+
+ // implements CodeGenerator ----------------------------------------
+
+ virtual bool Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const;
+
+ private:
+ string name_;
+
+ static string GetOutputFileContent(const string& generator_name,
+ const string& parameter,
+ const FileDescriptor* file);
+ static string GetOutputFileContent(const string& generator_name,
+ const string& parameter,
+ const string& file,
+ const string& first_message_name);
+};
+
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 02304d6..758f70d 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 c4f08e7..e2262b8 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/plugin.cc b/src/google/protobuf/compiler/plugin.cc
new file mode 100644
index 0000000..a4aedaf
--- /dev/null
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -0,0 +1,152 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/plugin.h>
+
+#include <iostream>
+#include <set>
+
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#else
+#include <unistd.h>
+#endif
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+class GeneratorResponseOutputDirectory : public OutputDirectory {
+ public:
+ GeneratorResponseOutputDirectory(CodeGeneratorResponse* response)
+ : response_(response) {}
+ virtual ~GeneratorResponseOutputDirectory() {}
+
+ // implements OutputDirectory --------------------------------------
+
+ virtual io::ZeroCopyOutputStream* Open(const string& filename) {
+ CodeGeneratorResponse::File* file = response_->add_file();
+ file->set_name(filename);
+ return new io::StringOutputStream(file->mutable_content());
+ }
+
+ virtual io::ZeroCopyOutputStream* OpenForInsert(
+ const string& filename, const string& insertion_point) {
+ CodeGeneratorResponse::File* file = response_->add_file();
+ file->set_name(filename);
+ file->set_insertion_point(insertion_point);
+ return new io::StringOutputStream(file->mutable_content());
+ }
+
+ private:
+ CodeGeneratorResponse* response_;
+};
+
+int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
+
+ if (argc > 1) {
+ cerr << argv[0] << ": Unknown option: " << argv[1] << endl;
+ return 1;
+ }
+
+#ifdef _WIN32
+ _setmode(STDIN_FILENO, _O_BINARY);
+ _setmode(STDOUT_FILENO, _O_BINARY);
+#endif
+
+ CodeGeneratorRequest request;
+ if (!request.ParseFromFileDescriptor(STDIN_FILENO)) {
+ cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl;
+ return 1;
+ }
+
+ DescriptorPool pool;
+ for (int i = 0; i < request.proto_file_size(); i++) {
+ const FileDescriptor* file = pool.BuildFile(request.proto_file(i));
+ if (file == NULL) {
+ // BuildFile() already wrote an error message.
+ return 1;
+ }
+ }
+
+ CodeGeneratorResponse response;
+ GeneratorResponseOutputDirectory output_directory(&response);
+
+ for (int i = 0; i < request.file_to_generate_size(); i++) {
+ const FileDescriptor* file =
+ pool.FindFileByName(request.file_to_generate(i));
+ if (file == NULL) {
+ cerr << argv[0] << ": protoc asked plugin to generate a file but "
+ "did not provide a descriptor for the file: "
+ << request.file_to_generate(i) << endl;
+ return 1;
+ }
+
+ string error;
+ bool succeeded = generator->Generate(
+ file, request.parameter(), &output_directory, &error);
+
+ if (!succeeded && error.empty()) {
+ error = "Code generator returned false but provided no error "
+ "description.";
+ }
+ if (!error.empty()) {
+ response.set_error(file->name() + ": " + error);
+ break;
+ }
+ }
+
+ if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
+ cerr << argv[0] << ": Error writing to stdout." << endl;
+ return 1;
+ }
+
+ return 0;
+}
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_file.h b/src/google/protobuf/compiler/plugin.h
index 430172a..7c40333 100644
--- a/src/google/protobuf/compiler/javamicro/javamicro_file.h
+++ b/src/google/protobuf/compiler/plugin.h
@@ -29,66 +29,45 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Front-end for protoc code generator plugins written in C++.
+//
+// To implement a protoc plugin in C++, simply write an implementation of
+// CodeGenerator, then create a main() function like:
+// int main(int argc, char* argv[]) {
+// MyCodeGenerator generator;
+// return google::protobuf::compiler::PluginMain(argc, argv, &generator);
+// }
+// You must link your plugin against libprotobuf and libprotoc.
+//
+// To get protoc to use the plugin, do one of the following:
+// * Place the plugin binary somewhere in the PATH and give it the name
+// "protoc-gen-NAME" (replacing "NAME" with the name of your plugin). If you
+// then invoke protoc with the parameter --NAME_out=OUT_DIR (again, replace
+// "NAME" with your plugin's name), protoc will invoke your plugin to generate
+// the output, which will be placed in OUT_DIR.
+// * Place the plugin binary anywhere, with any name, and pass the --plugin
+// parameter to protoc to direct it to your plugin like so:
+// protoc --plugin=protoc-gen-NAME=path/to/mybinary --NAME_out=OUT_DIR
+// On Windows, make sure to include the .exe suffix:
+// protoc --plugin=protoc-gen-NAME=path/to/mybinary.exe --NAME_out=OUT_DIR
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
+#ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
+#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
-#include <string>
-#include <vector>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/javamicro/javamicro_params.h>
namespace google {
namespace protobuf {
- class FileDescriptor; // descriptor.h
- namespace io {
- class Printer; // printer.h
- }
- namespace compiler {
- class OutputDirectory; // code_generator.h
- }
-}
-
-namespace protobuf {
namespace compiler {
-namespace javamicro {
-
-class FileGenerator {
- public:
- explicit FileGenerator(const FileDescriptor* file, const Params& params);
- ~FileGenerator();
-
- // Checks for problems that would otherwise lead to cryptic compile errors.
- // Returns true if there are no problems, or writes an error description to
- // the given string and returns false otherwise.
- bool Validate(string* error);
-
- void Generate(io::Printer* printer);
-
- // If we aren't putting everything into one file, this will write all the
- // files other than the outer file (i.e. one for each message, enum, and
- // service type).
- void GenerateSiblings(const string& package_dir,
- OutputDirectory* output_directory,
- vector<string>* file_list);
-
- const string& java_package() { return java_package_; }
- const string& classname() { return classname_; }
- private:
- const FileDescriptor* file_;
- const Params& params_;
- string java_package_;
- string classname_;
+class CodeGenerator; // code_generator.h
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
-};
+// Implements main() for a protoc plugin exposing the given code generator.
+LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
-} // namespace javamicro
} // namespace compiler
} // namespace protobuf
} // namespace google
-#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
+#endif // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
new file mode 100644
index 0000000..6b0dd55
--- /dev/null
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -0,0 +1,1084 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/compiler/plugin.pb.h"
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#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 {
+namespace compiler {
+
+namespace {
+
+const ::google::protobuf::Descriptor* CodeGeneratorRequest_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ CodeGeneratorRequest_reflection_ = NULL;
+const ::google::protobuf::Descriptor* CodeGeneratorResponse_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ CodeGeneratorResponse_reflection_ = NULL;
+const ::google::protobuf::Descriptor* CodeGeneratorResponse_File_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ CodeGeneratorResponse_File_reflection_ = NULL;
+
+} // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/compiler/plugin.proto");
+ GOOGLE_CHECK(file != NULL);
+ CodeGeneratorRequest_descriptor_ = file->message_type(0);
+ static const int CodeGeneratorRequest_offsets_[3] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, file_to_generate_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, parameter_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_),
+ };
+ CodeGeneratorRequest_reflection_ =
+ new ::google::protobuf::internal::GeneratedMessageReflection(
+ CodeGeneratorRequest_descriptor_,
+ CodeGeneratorRequest::default_instance_,
+ CodeGeneratorRequest_offsets_,
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _unknown_fields_),
+ -1,
+ ::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
+ sizeof(CodeGeneratorRequest));
+ CodeGeneratorResponse_descriptor_ = file->message_type(1);
+ static const int CodeGeneratorResponse_offsets_[2] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_),
+ };
+ CodeGeneratorResponse_reflection_ =
+ new ::google::protobuf::internal::GeneratedMessageReflection(
+ CodeGeneratorResponse_descriptor_,
+ CodeGeneratorResponse::default_instance_,
+ CodeGeneratorResponse_offsets_,
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _unknown_fields_),
+ -1,
+ ::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
+ sizeof(CodeGeneratorResponse));
+ CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
+ static const int CodeGeneratorResponse_File_offsets_[3] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, insertion_point_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_),
+ };
+ CodeGeneratorResponse_File_reflection_ =
+ new ::google::protobuf::internal::GeneratedMessageReflection(
+ CodeGeneratorResponse_File_descriptor_,
+ CodeGeneratorResponse_File::default_instance_,
+ CodeGeneratorResponse_File_offsets_,
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _unknown_fields_),
+ -1,
+ ::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
+ sizeof(CodeGeneratorResponse_File));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
+}
+
+} // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+ delete CodeGeneratorRequest::default_instance_;
+ delete CodeGeneratorRequest_reflection_;
+ delete CodeGeneratorResponse::default_instance_;
+ delete CodeGeneratorResponse_reflection_;
+ delete CodeGeneratorResponse_File::default_instance_;
+ delete CodeGeneratorResponse_File_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+ "\n%google/protobuf/compiler/plugin.proto\022"
+ "\030google.protobuf.compiler\032 google/protob"
+ "uf/descriptor.proto\"}\n\024CodeGeneratorRequ"
+ "est\022\030\n\020file_to_generate\030\001 \003(\t\022\021\n\tparamet"
+ "er\030\002 \001(\t\0228\n\nproto_file\030\017 \003(\0132$.google.pr"
+ "otobuf.FileDescriptorProto\"\252\001\n\025CodeGener"
+ "atorResponse\022\r\n\005error\030\001 \001(\t\022B\n\004file\030\017 \003("
+ "\01324.google.protobuf.compiler.CodeGenerat"
+ "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n"
+ "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\t", 399);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
+ CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
+ CodeGeneratorResponse::default_instance_ = new CodeGeneratorResponse();
+ CodeGeneratorResponse_File::default_instance_ = new CodeGeneratorResponse_File();
+ CodeGeneratorRequest::default_instance_->InitAsDefaultInstance();
+ CodeGeneratorResponse::default_instance_->InitAsDefaultInstance();
+ CodeGeneratorResponse_File::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
+ StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ }
+} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
+
+
+// ===================================================================
+
+const ::std::string CodeGeneratorRequest::_default_parameter_;
+#ifndef _MSC_VER
+const int CodeGeneratorRequest::kFileToGenerateFieldNumber;
+const int CodeGeneratorRequest::kParameterFieldNumber;
+const int CodeGeneratorRequest::kProtoFileFieldNumber;
+#endif // !_MSC_VER
+
+CodeGeneratorRequest::CodeGeneratorRequest()
+ : ::google::protobuf::Message() {
+ SharedCtor();
+}
+
+void CodeGeneratorRequest::InitAsDefaultInstance() {
+}
+
+CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
+ : ::google::protobuf::Message() {
+ SharedCtor();
+ MergeFrom(from);
+}
+
+void CodeGeneratorRequest::SharedCtor() {
+ _cached_size_ = 0;
+ parameter_ = const_cast< ::std::string*>(&_default_parameter_);
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CodeGeneratorRequest::~CodeGeneratorRequest() {
+ SharedDtor();
+}
+
+void CodeGeneratorRequest::SharedDtor() {
+ if (parameter_ != &_default_parameter_) {
+ delete parameter_;
+ }
+ if (this != default_instance_) {
+ }
+}
+
+void CodeGeneratorRequest::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return CodeGeneratorRequest_descriptor_;
+}
+
+const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_;
+}
+
+CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
+
+CodeGeneratorRequest* CodeGeneratorRequest::New() const {
+ return new CodeGeneratorRequest;
+}
+
+void CodeGeneratorRequest::Clear() {
+ if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+ if (_has_bit(1)) {
+ if (parameter_ != &_default_parameter_) {
+ parameter_->clear();
+ }
+ }
+ }
+ file_to_generate_.Clear();
+ proto_file_.Clear();
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ mutable_unknown_fields()->Clear();
+}
+
+bool CodeGeneratorRequest::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::google::protobuf::uint32 tag;
+ while ((tag = input->ReadTag()) != 0) {
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // repeated string file_to_generate = 1;
+ case 1: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_file_to_generate:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->add_file_to_generate()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->file_to_generate(0).data(), this->file_to_generate(0).length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(10)) goto parse_file_to_generate;
+ if (input->ExpectTag(18)) goto parse_parameter;
+ break;
+ }
+
+ // optional string parameter = 2;
+ case 2: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_parameter:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_parameter()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->parameter().data(), this->parameter().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(122)) goto parse_proto_file;
+ break;
+ }
+
+ // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ case 15: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_proto_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_proto_file()));
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(122)) goto parse_proto_file;
+ if (input->ExpectAtEnd()) return true;
+ break;
+ }
+
+ default: {
+ handle_uninterpreted:
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ return true;
+ }
+ DO_(::google::protobuf::internal::WireFormat::SkipField(
+ input, tag, mutable_unknown_fields()));
+ break;
+ }
+ }
+ }
+ return true;
+#undef DO_
+}
+
+void CodeGeneratorRequest::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // repeated string file_to_generate = 1;
+ for (int i = 0; i < this->file_to_generate_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 1, this->file_to_generate(i), output);
+ }
+
+ // optional string parameter = 2;
+ if (_has_bit(1)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->parameter().data(), this->parameter().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 2, this->parameter(), output);
+ }
+
+ // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ for (int i = 0; i < this->proto_file_size(); i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 15, this->proto_file(i), output);
+ }
+
+ if (!unknown_fields().empty()) {
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
+ }
+}
+
+::google::protobuf::uint8* CodeGeneratorRequest::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // repeated string file_to_generate = 1;
+ for (int i = 0; i < this->file_to_generate_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteStringToArray(1, this->file_to_generate(i), target);
+ }
+
+ // optional string parameter = 2;
+ if (_has_bit(1)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->parameter().data(), this->parameter().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 2, this->parameter(), target);
+ }
+
+ // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ for (int i = 0; i < this->proto_file_size(); i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 15, this->proto_file(i), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
+}
+
+int CodeGeneratorRequest::ByteSize() const {
+ int total_size = 0;
+
+ if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+ // optional string parameter = 2;
+ if (has_parameter()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->parameter());
+ }
+
+ }
+ // repeated string file_to_generate = 1;
+ total_size += 1 * this->file_to_generate_size();
+ for (int i = 0; i < this->file_to_generate_size(); i++) {
+ total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->file_to_generate(i));
+ }
+
+ // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ total_size += 1 * this->proto_file_size();
+ for (int i = 0; i < this->proto_file_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->proto_file(i));
+ }
+
+ if (!unknown_fields().empty()) {
+ total_size +=
+ ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+ unknown_fields());
+ }
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
+ GOOGLE_CHECK_NE(&from, this);
+ const CodeGeneratorRequest* source =
+ ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorRequest*>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
+ GOOGLE_CHECK_NE(&from, this);
+ file_to_generate_.MergeFrom(from.file_to_generate_);
+ proto_file_.MergeFrom(from.proto_file_);
+ if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+ if (from._has_bit(1)) {
+ set_parameter(from.parameter());
+ }
+ }
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool CodeGeneratorRequest::IsInitialized() const {
+
+ for (int i = 0; i < proto_file_size(); i++) {
+ if (!this->proto_file(i).IsInitialized()) return false;
+ }
+ return true;
+}
+
+void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
+ if (other != this) {
+ file_to_generate_.Swap(&other->file_to_generate_);
+ std::swap(parameter_, other->parameter_);
+ proto_file_.Swap(&other->proto_file_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _unknown_fields_.Swap(&other->_unknown_fields_);
+ std::swap(_cached_size_, other->_cached_size_);
+ }
+}
+
+::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = CodeGeneratorRequest_descriptor_;
+ metadata.reflection = CodeGeneratorRequest_reflection_;
+ return metadata;
+}
+
+
+// ===================================================================
+
+const ::std::string CodeGeneratorResponse_File::_default_name_;
+const ::std::string CodeGeneratorResponse_File::_default_insertion_point_;
+const ::std::string CodeGeneratorResponse_File::_default_content_;
+#ifndef _MSC_VER
+const int CodeGeneratorResponse_File::kNameFieldNumber;
+const int CodeGeneratorResponse_File::kInsertionPointFieldNumber;
+const int CodeGeneratorResponse_File::kContentFieldNumber;
+#endif // !_MSC_VER
+
+CodeGeneratorResponse_File::CodeGeneratorResponse_File()
+ : ::google::protobuf::Message() {
+ SharedCtor();
+}
+
+void CodeGeneratorResponse_File::InitAsDefaultInstance() {
+}
+
+CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from)
+ : ::google::protobuf::Message() {
+ SharedCtor();
+ MergeFrom(from);
+}
+
+void CodeGeneratorResponse_File::SharedCtor() {
+ _cached_size_ = 0;
+ name_ = const_cast< ::std::string*>(&_default_name_);
+ insertion_point_ = const_cast< ::std::string*>(&_default_insertion_point_);
+ content_ = const_cast< ::std::string*>(&_default_content_);
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
+ SharedDtor();
+}
+
+void CodeGeneratorResponse_File::SharedDtor() {
+ if (name_ != &_default_name_) {
+ delete name_;
+ }
+ if (insertion_point_ != &_default_insertion_point_) {
+ delete insertion_point_;
+ }
+ if (content_ != &_default_content_) {
+ delete content_;
+ }
+ if (this != default_instance_) {
+ }
+}
+
+void CodeGeneratorResponse_File::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return CodeGeneratorResponse_File_descriptor_;
+}
+
+const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_;
+}
+
+CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
+
+CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const {
+ return new CodeGeneratorResponse_File;
+}
+
+void CodeGeneratorResponse_File::Clear() {
+ if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bit(0)) {
+ if (name_ != &_default_name_) {
+ name_->clear();
+ }
+ }
+ if (_has_bit(1)) {
+ if (insertion_point_ != &_default_insertion_point_) {
+ insertion_point_->clear();
+ }
+ }
+ if (_has_bit(2)) {
+ if (content_ != &_default_content_) {
+ content_->clear();
+ }
+ }
+ }
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ mutable_unknown_fields()->Clear();
+}
+
+bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::google::protobuf::uint32 tag;
+ while ((tag = input->ReadTag()) != 0) {
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string name = 1;
+ case 1: {
+ 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;
+ }
+ if (input->ExpectTag(18)) goto parse_insertion_point;
+ break;
+ }
+
+ // optional string insertion_point = 2;
+ case 2: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_insertion_point:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_insertion_point()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->insertion_point().data(), this->insertion_point().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(122)) goto parse_content;
+ break;
+ }
+
+ // optional string content = 15;
+ case 15: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_content:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_content()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->content().data(), this->content().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectAtEnd()) return true;
+ break;
+ }
+
+ default: {
+ handle_uninterpreted:
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ return true;
+ }
+ DO_(::google::protobuf::internal::WireFormat::SkipField(
+ input, tag, mutable_unknown_fields()));
+ break;
+ }
+ }
+ }
+ return true;
+#undef DO_
+}
+
+void CodeGeneratorResponse_File::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // optional string name = 1;
+ if (_has_bit(0)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 1, this->name(), output);
+ }
+
+ // optional string insertion_point = 2;
+ if (_has_bit(1)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->insertion_point().data(), this->insertion_point().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 2, this->insertion_point(), output);
+ }
+
+ // optional string content = 15;
+ if (_has_bit(2)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->content().data(), this->content().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 15, this->content(), output);
+ }
+
+ if (!unknown_fields().empty()) {
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
+ }
+}
+
+::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string name = 1;
+ if (_has_bit(0)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->name().data(), this->name().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->name(), target);
+ }
+
+ // optional string insertion_point = 2;
+ if (_has_bit(1)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->insertion_point().data(), this->insertion_point().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 2, this->insertion_point(), target);
+ }
+
+ // optional string content = 15;
+ if (_has_bit(2)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->content().data(), this->content().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 15, this->content(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
+}
+
+int CodeGeneratorResponse_File::ByteSize() const {
+ int total_size = 0;
+
+ if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ // optional string name = 1;
+ if (has_name()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
+ }
+
+ // optional string insertion_point = 2;
+ if (has_insertion_point()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->insertion_point());
+ }
+
+ // optional string content = 15;
+ if (has_content()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->content());
+ }
+
+ }
+ if (!unknown_fields().empty()) {
+ total_size +=
+ ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+ unknown_fields());
+ }
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
+ GOOGLE_CHECK_NE(&from, this);
+ const CodeGeneratorResponse_File* source =
+ ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse_File*>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
+ GOOGLE_CHECK_NE(&from, this);
+ if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (from._has_bit(0)) {
+ set_name(from.name());
+ }
+ if (from._has_bit(1)) {
+ set_insertion_point(from.insertion_point());
+ }
+ if (from._has_bit(2)) {
+ set_content(from.content());
+ }
+ }
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool CodeGeneratorResponse_File::IsInitialized() const {
+
+ return true;
+}
+
+void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) {
+ if (other != this) {
+ std::swap(name_, other->name_);
+ std::swap(insertion_point_, other->insertion_point_);
+ std::swap(content_, other->content_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _unknown_fields_.Swap(&other->_unknown_fields_);
+ std::swap(_cached_size_, other->_cached_size_);
+ }
+}
+
+::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = CodeGeneratorResponse_File_descriptor_;
+ metadata.reflection = CodeGeneratorResponse_File_reflection_;
+ return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+const ::std::string CodeGeneratorResponse::_default_error_;
+#ifndef _MSC_VER
+const int CodeGeneratorResponse::kErrorFieldNumber;
+const int CodeGeneratorResponse::kFileFieldNumber;
+#endif // !_MSC_VER
+
+CodeGeneratorResponse::CodeGeneratorResponse()
+ : ::google::protobuf::Message() {
+ SharedCtor();
+}
+
+void CodeGeneratorResponse::InitAsDefaultInstance() {
+}
+
+CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
+ : ::google::protobuf::Message() {
+ SharedCtor();
+ MergeFrom(from);
+}
+
+void CodeGeneratorResponse::SharedCtor() {
+ _cached_size_ = 0;
+ error_ = const_cast< ::std::string*>(&_default_error_);
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CodeGeneratorResponse::~CodeGeneratorResponse() {
+ SharedDtor();
+}
+
+void CodeGeneratorResponse::SharedDtor() {
+ if (error_ != &_default_error_) {
+ delete error_;
+ }
+ if (this != default_instance_) {
+ }
+}
+
+void CodeGeneratorResponse::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return CodeGeneratorResponse_descriptor_;
+}
+
+const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return *default_instance_;
+}
+
+CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
+
+CodeGeneratorResponse* CodeGeneratorResponse::New() const {
+ return new CodeGeneratorResponse;
+}
+
+void CodeGeneratorResponse::Clear() {
+ if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bit(0)) {
+ if (error_ != &_default_error_) {
+ error_->clear();
+ }
+ }
+ }
+ file_.Clear();
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ mutable_unknown_fields()->Clear();
+}
+
+bool CodeGeneratorResponse::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::google::protobuf::uint32 tag;
+ while ((tag = input->ReadTag()) != 0) {
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional string error = 1;
+ case 1: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_error()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->error().data(), this->error().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(122)) goto parse_file;
+ break;
+ }
+
+ // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ case 15: {
+ 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;
+ }
+ if (input->ExpectTag(122)) goto parse_file;
+ if (input->ExpectAtEnd()) return true;
+ break;
+ }
+
+ default: {
+ handle_uninterpreted:
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ return true;
+ }
+ DO_(::google::protobuf::internal::WireFormat::SkipField(
+ input, tag, mutable_unknown_fields()));
+ break;
+ }
+ }
+ }
+ return true;
+#undef DO_
+}
+
+void CodeGeneratorResponse::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // optional string error = 1;
+ if (_has_bit(0)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->error().data(), this->error().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 1, this->error(), output);
+ }
+
+ // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ for (int i = 0; i < this->file_size(); i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 15, this->file(i), output);
+ }
+
+ if (!unknown_fields().empty()) {
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
+ }
+}
+
+::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string error = 1;
+ if (_has_bit(0)) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->error().data(), this->error().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 1, this->error(), target);
+ }
+
+ // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ for (int i = 0; i < this->file_size(); i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 15, this->file(i), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
+}
+
+int CodeGeneratorResponse::ByteSize() const {
+ int total_size = 0;
+
+ if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ // optional string error = 1;
+ if (has_error()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->error());
+ }
+
+ }
+ // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ total_size += 1 * this->file_size();
+ for (int i = 0; i < this->file_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->file(i));
+ }
+
+ if (!unknown_fields().empty()) {
+ total_size +=
+ ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+ unknown_fields());
+ }
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
+ GOOGLE_CHECK_NE(&from, this);
+ const CodeGeneratorResponse* source =
+ ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse*>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
+ GOOGLE_CHECK_NE(&from, this);
+ file_.MergeFrom(from.file_);
+ if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (from._has_bit(0)) {
+ set_error(from.error());
+ }
+ }
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool CodeGeneratorResponse::IsInitialized() const {
+
+ return true;
+}
+
+void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) {
+ if (other != this) {
+ std::swap(error_, other->error_);
+ file_.Swap(&other->file_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _unknown_fields_.Swap(&other->_unknown_fields_);
+ std::swap(_cached_size_, other->_cached_size_);
+ }
+}
+
+::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = CodeGeneratorResponse_descriptor_;
+ metadata.reflection = CodeGeneratorResponse_reflection_;
+ return metadata;
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
new file mode 100644
index 0000000..f8f8053
--- /dev/null
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -0,0 +1,727 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/compiler/plugin.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 2003000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include "google/protobuf/descriptor.pb.h"
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+
+class CodeGeneratorRequest;
+class CodeGeneratorResponse;
+class CodeGeneratorResponse_File;
+
+// ===================================================================
+
+class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message {
+ public:
+ CodeGeneratorRequest();
+ virtual ~CodeGeneratorRequest();
+
+ CodeGeneratorRequest(const CodeGeneratorRequest& from);
+
+ inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+ return _unknown_fields_;
+ }
+
+ inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+ return &_unknown_fields_;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const CodeGeneratorRequest& default_instance();
+
+ void Swap(CodeGeneratorRequest* other);
+
+ // implements Message ----------------------------------------------
+
+ CodeGeneratorRequest* New() const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const CodeGeneratorRequest& from);
+ void MergeFrom(const CodeGeneratorRequest& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // repeated string file_to_generate = 1;
+ inline int file_to_generate_size() const;
+ inline void clear_file_to_generate();
+ static const int kFileToGenerateFieldNumber = 1;
+ inline const ::std::string& file_to_generate(int index) const;
+ inline ::std::string* mutable_file_to_generate(int index);
+ inline void set_file_to_generate(int index, const ::std::string& value);
+ inline void set_file_to_generate(int index, const char* value);
+ inline void set_file_to_generate(int index, const char* value, size_t size);
+ inline ::std::string* add_file_to_generate();
+ inline void add_file_to_generate(const ::std::string& value);
+ inline void add_file_to_generate(const char* value);
+ inline void add_file_to_generate(const char* value, size_t size);
+ inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
+ inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
+
+ // optional string parameter = 2;
+ inline bool has_parameter() const;
+ inline void clear_parameter();
+ static const int kParameterFieldNumber = 2;
+ inline const ::std::string& parameter() const;
+ inline void set_parameter(const ::std::string& value);
+ inline void set_parameter(const char* value);
+ inline void set_parameter(const char* value, size_t size);
+ inline ::std::string* mutable_parameter();
+
+ // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ inline int proto_file_size() const;
+ inline void clear_proto_file();
+ static const int kProtoFileFieldNumber = 15;
+ inline const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
+ inline ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
+ inline ::google::protobuf::FileDescriptorProto* add_proto_file();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ proto_file() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+ mutable_proto_file();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
+ private:
+ ::google::protobuf::UnknownFieldSet _unknown_fields_;
+ mutable int _cached_size_;
+
+ ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
+ ::std::string* parameter_;
+ static const ::std::string _default_parameter_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
+ friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+
+ ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+
+ // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+ inline bool _has_bit(int index) const {
+ return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+ }
+ inline void _set_bit(int index) {
+ _has_bits_[index / 32] |= (1u << (index % 32));
+ }
+ inline void _clear_bit(int index) {
+ _has_bits_[index / 32] &= ~(1u << (index % 32));
+ }
+
+ void InitAsDefaultInstance();
+ static CodeGeneratorRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message {
+ public:
+ CodeGeneratorResponse_File();
+ virtual ~CodeGeneratorResponse_File();
+
+ CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
+
+ inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+ return _unknown_fields_;
+ }
+
+ inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+ return &_unknown_fields_;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const CodeGeneratorResponse_File& default_instance();
+
+ void Swap(CodeGeneratorResponse_File* other);
+
+ // implements Message ----------------------------------------------
+
+ CodeGeneratorResponse_File* New() const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const CodeGeneratorResponse_File& from);
+ void MergeFrom(const CodeGeneratorResponse_File& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional string name = 1;
+ inline bool has_name() const;
+ inline void clear_name();
+ static const int kNameFieldNumber = 1;
+ inline const ::std::string& name() const;
+ inline void set_name(const ::std::string& value);
+ inline void set_name(const char* value);
+ inline void set_name(const char* value, size_t size);
+ inline ::std::string* mutable_name();
+
+ // optional string insertion_point = 2;
+ inline bool has_insertion_point() const;
+ inline void clear_insertion_point();
+ static const int kInsertionPointFieldNumber = 2;
+ inline const ::std::string& insertion_point() const;
+ inline void set_insertion_point(const ::std::string& value);
+ inline void set_insertion_point(const char* value);
+ inline void set_insertion_point(const char* value, size_t size);
+ inline ::std::string* mutable_insertion_point();
+
+ // optional string content = 15;
+ inline bool has_content() const;
+ inline void clear_content();
+ static const int kContentFieldNumber = 15;
+ inline const ::std::string& content() const;
+ inline void set_content(const ::std::string& value);
+ inline void set_content(const char* value);
+ inline void set_content(const char* value, size_t size);
+ inline ::std::string* mutable_content();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
+ private:
+ ::google::protobuf::UnknownFieldSet _unknown_fields_;
+ mutable int _cached_size_;
+
+ ::std::string* name_;
+ static const ::std::string _default_name_;
+ ::std::string* insertion_point_;
+ static const ::std::string _default_insertion_point_;
+ ::std::string* content_;
+ static const ::std::string _default_content_;
+ friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+
+ ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+
+ // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+ inline bool _has_bit(int index) const {
+ return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+ }
+ inline void _set_bit(int index) {
+ _has_bits_[index / 32] |= (1u << (index % 32));
+ }
+ inline void _clear_bit(int index) {
+ _has_bits_[index / 32] &= ~(1u << (index % 32));
+ }
+
+ void InitAsDefaultInstance();
+ static CodeGeneratorResponse_File* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message {
+ public:
+ CodeGeneratorResponse();
+ virtual ~CodeGeneratorResponse();
+
+ CodeGeneratorResponse(const CodeGeneratorResponse& from);
+
+ inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+ return _unknown_fields_;
+ }
+
+ inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+ return &_unknown_fields_;
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const CodeGeneratorResponse& default_instance();
+
+ void Swap(CodeGeneratorResponse* other);
+
+ // implements Message ----------------------------------------------
+
+ CodeGeneratorResponse* New() const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const CodeGeneratorResponse& from);
+ void MergeFrom(const CodeGeneratorResponse& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ public:
+
+ ::google::protobuf::Metadata GetMetadata() const;
+
+ // nested types ----------------------------------------------------
+
+ typedef CodeGeneratorResponse_File File;
+
+ // accessors -------------------------------------------------------
+
+ // optional string error = 1;
+ inline bool has_error() const;
+ inline void clear_error();
+ static const int kErrorFieldNumber = 1;
+ inline const ::std::string& error() const;
+ inline void set_error(const ::std::string& value);
+ inline void set_error(const char* value);
+ inline void set_error(const char* value, size_t size);
+ inline ::std::string* mutable_error();
+
+ // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ inline int file_size() const;
+ inline void clear_file();
+ static const int kFileFieldNumber = 15;
+ inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
+ inline ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
+ inline ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+ file() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+ mutable_file();
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
+ private:
+ ::google::protobuf::UnknownFieldSet _unknown_fields_;
+ mutable int _cached_size_;
+
+ ::std::string* error_;
+ static const ::std::string _default_error_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
+ friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+
+ ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+
+ // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+ inline bool _has_bit(int index) const {
+ return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+ }
+ inline void _set_bit(int index) {
+ _has_bits_[index / 32] |= (1u << (index % 32));
+ }
+ inline void _clear_bit(int index) {
+ _has_bits_[index / 32] &= ~(1u << (index % 32));
+ }
+
+ void InitAsDefaultInstance();
+ static CodeGeneratorResponse* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+// CodeGeneratorRequest
+
+// repeated string file_to_generate = 1;
+inline int CodeGeneratorRequest::file_to_generate_size() const {
+ return file_to_generate_.size();
+}
+inline void CodeGeneratorRequest::clear_file_to_generate() {
+ file_to_generate_.Clear();
+}
+inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
+ return file_to_generate_.Get(index);
+}
+inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
+ return file_to_generate_.Mutable(index);
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
+ file_to_generate_.Mutable(index)->assign(value);
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+ file_to_generate_.Mutable(index)->assign(value);
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
+ file_to_generate_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+ return file_to_generate_.Add();
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
+ file_to_generate_.Add()->assign(value);
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+ file_to_generate_.Add()->assign(value);
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+ file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+CodeGeneratorRequest::file_to_generate() const {
+ return file_to_generate_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+CodeGeneratorRequest::mutable_file_to_generate() {
+ return &file_to_generate_;
+}
+
+// optional string parameter = 2;
+inline bool CodeGeneratorRequest::has_parameter() const {
+ return _has_bit(1);
+}
+inline void CodeGeneratorRequest::clear_parameter() {
+ if (parameter_ != &_default_parameter_) {
+ parameter_->clear();
+ }
+ _clear_bit(1);
+}
+inline const ::std::string& CodeGeneratorRequest::parameter() const {
+ return *parameter_;
+}
+inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
+ _set_bit(1);
+ if (parameter_ == &_default_parameter_) {
+ parameter_ = new ::std::string;
+ }
+ parameter_->assign(value);
+}
+inline void CodeGeneratorRequest::set_parameter(const char* value) {
+ _set_bit(1);
+ if (parameter_ == &_default_parameter_) {
+ parameter_ = new ::std::string;
+ }
+ parameter_->assign(value);
+}
+inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+ _set_bit(1);
+ if (parameter_ == &_default_parameter_) {
+ parameter_ = new ::std::string;
+ }
+ parameter_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
+ _set_bit(1);
+ if (parameter_ == &_default_parameter_) {
+ parameter_ = new ::std::string;
+ }
+ return parameter_;
+}
+
+// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+inline int CodeGeneratorRequest::proto_file_size() const {
+ return proto_file_.size();
+}
+inline void CodeGeneratorRequest::clear_proto_file() {
+ proto_file_.Clear();
+}
+inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+ return proto_file_.Get(index);
+}
+inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
+ return proto_file_.Mutable(index);
+}
+inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+ return proto_file_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+ return proto_file_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+CodeGeneratorRequest::mutable_proto_file() {
+ return &proto_file_;
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse_File
+
+// optional string name = 1;
+inline bool CodeGeneratorResponse_File::has_name() const {
+ return _has_bit(0);
+}
+inline void CodeGeneratorResponse_File::clear_name() {
+ if (name_ != &_default_name_) {
+ name_->clear();
+ }
+ _clear_bit(0);
+}
+inline const ::std::string& CodeGeneratorResponse_File::name() const {
+ return *name_;
+}
+inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_name(const char* value) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ return name_;
+}
+
+// optional string insertion_point = 2;
+inline bool CodeGeneratorResponse_File::has_insertion_point() const {
+ return _has_bit(1);
+}
+inline void CodeGeneratorResponse_File::clear_insertion_point() {
+ if (insertion_point_ != &_default_insertion_point_) {
+ insertion_point_->clear();
+ }
+ _clear_bit(1);
+}
+inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
+ return *insertion_point_;
+}
+inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
+ _set_bit(1);
+ if (insertion_point_ == &_default_insertion_point_) {
+ insertion_point_ = new ::std::string;
+ }
+ insertion_point_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
+ _set_bit(1);
+ if (insertion_point_ == &_default_insertion_point_) {
+ insertion_point_ = new ::std::string;
+ }
+ insertion_point_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
+ _set_bit(1);
+ if (insertion_point_ == &_default_insertion_point_) {
+ insertion_point_ = new ::std::string;
+ }
+ insertion_point_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+ _set_bit(1);
+ if (insertion_point_ == &_default_insertion_point_) {
+ insertion_point_ = new ::std::string;
+ }
+ return insertion_point_;
+}
+
+// optional string content = 15;
+inline bool CodeGeneratorResponse_File::has_content() const {
+ return _has_bit(2);
+}
+inline void CodeGeneratorResponse_File::clear_content() {
+ if (content_ != &_default_content_) {
+ content_->clear();
+ }
+ _clear_bit(2);
+}
+inline const ::std::string& CodeGeneratorResponse_File::content() const {
+ return *content_;
+}
+inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
+ _set_bit(2);
+ if (content_ == &_default_content_) {
+ content_ = new ::std::string;
+ }
+ content_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_content(const char* value) {
+ _set_bit(2);
+ if (content_ == &_default_content_) {
+ content_ = new ::std::string;
+ }
+ content_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+ _set_bit(2);
+ if (content_ == &_default_content_) {
+ content_ = new ::std::string;
+ }
+ content_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
+ _set_bit(2);
+ if (content_ == &_default_content_) {
+ content_ = new ::std::string;
+ }
+ return content_;
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse
+
+// optional string error = 1;
+inline bool CodeGeneratorResponse::has_error() const {
+ return _has_bit(0);
+}
+inline void CodeGeneratorResponse::clear_error() {
+ if (error_ != &_default_error_) {
+ error_->clear();
+ }
+ _clear_bit(0);
+}
+inline const ::std::string& CodeGeneratorResponse::error() const {
+ return *error_;
+}
+inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
+ _set_bit(0);
+ if (error_ == &_default_error_) {
+ error_ = new ::std::string;
+ }
+ error_->assign(value);
+}
+inline void CodeGeneratorResponse::set_error(const char* value) {
+ _set_bit(0);
+ if (error_ == &_default_error_) {
+ error_ = new ::std::string;
+ }
+ error_->assign(value);
+}
+inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+ _set_bit(0);
+ if (error_ == &_default_error_) {
+ error_ = new ::std::string;
+ }
+ error_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorResponse::mutable_error() {
+ _set_bit(0);
+ if (error_ == &_default_error_) {
+ error_ = new ::std::string;
+ }
+ return error_;
+}
+
+// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+inline int CodeGeneratorResponse::file_size() const {
+ return file_.size();
+}
+inline void CodeGeneratorResponse::clear_file() {
+ file_.Clear();
+}
+inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+ return file_.Get(index);
+}
+inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
+ return file_.Mutable(index);
+}
+inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+ return file_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+ return file_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+CodeGeneratorResponse::mutable_file() {
+ return &file_;
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#ifndef SWIG
+namespace google {
+namespace protobuf {
+
+
+} // namespace google
+} // namespace protobuf
+#endif // SWIG
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
new file mode 100644
index 0000000..4e928b0
--- /dev/null
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -0,0 +1,145 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to
+// change.
+//
+// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is
+// just a program that reads a CodeGeneratorRequest from stdin and writes a
+// CodeGeneratorResponse to stdout.
+//
+// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
+// of dealing with the raw protocol defined here.
+//
+// A plugin executable needs only to be placed somewhere in the path. The
+// plugin should be named "protoc-gen-$NAME", and will then be used when the
+// flag "--${NAME}_out" is passed to protoc.
+
+package google.protobuf.compiler;
+
+import "google/protobuf/descriptor.proto";
+
+// An encoded CodeGeneratorRequest is written to the plugin's stdin.
+message CodeGeneratorRequest {
+ // The .proto files that were explicitly listed on the command-line. The
+ // code generator should generate code only for these files. Each file's
+ // descriptor will be included in proto_file, below.
+ repeated string file_to_generate = 1;
+
+ // The generator parameter passed on the command-line.
+ optional string parameter = 2;
+
+ // FileDescriptorProtos for all files in files_to_generate and everything
+ // they import. The files will appear in topological order, so each file
+ // appears before any file that imports it.
+ //
+ // protoc guarantees that all proto_files will be written after
+ // the fields above, even though this is not technically guaranteed by the
+ // protobuf wire format. This theoretically could allow a plugin to stream
+ // in the FileDescriptorProtos and handle them one by one rather than read
+ // the entire set into memory at once. However, as of this writing, this
+ // is not similarly optimized on protoc's end -- it will store all fields in
+ // memory at once before sending them to the plugin.
+ repeated FileDescriptorProto proto_file = 15;
+}
+
+// The plugin writes an encoded CodeGeneratorResponse to stdout.
+message CodeGeneratorResponse {
+ // Error message. If non-empty, code generation failed. The plugin process
+ // should exit with status code zero even if it reports an error in this way.
+ //
+ // This should be used to indicate errors in .proto files which prevent the
+ // code generator from generating correct code. Errors which indicate a
+ // problem in protoc itself -- such as the input CodeGeneratorRequest being
+ // unparseable -- should be reported by writing a message to stderr and
+ // exiting with a non-zero status code.
+ optional string error = 1;
+
+ // Represents a single generated file.
+ message File {
+ // The file name, relative to the output directory. The name must not
+ // contain "." or ".." components and must be relative, not be absolute (so,
+ // the file cannot lie outside the output directory). "/" must be used as
+ // the path separator, not "\".
+ //
+ // If the name is omitted, the content will be appended to the previous
+ // file. This allows the generator to break large files into small chunks,
+ // and allows the generated text to be streamed back to protoc so that large
+ // files need not reside completely in memory at one time. Note that as of
+ // this writing protoc does not optimize for this -- it will read the entire
+ // CodeGeneratorResponse before writing files to disk.
+ optional string name = 1;
+
+ // If non-empty, indicates that the named file should already exist, and the
+ // content here is to be inserted into that file at a defined insertion
+ // point. This feature allows a code generator to extend the output
+ // produced by another code generator. The original generator may provide
+ // insertion points by placing special annotations in the file that look
+ // like:
+ // @@protoc_insertion_point(NAME)
+ // The annotation can have arbitrary text before and after it on the line,
+ // which allows it to be placed in a comment. NAME should be replaced with
+ // an identifier naming the point -- this is what other generators will use
+ // as the insertion_point. Code inserted at this point will be placed
+ // immediately above the line containing the insertion point (thus multiple
+ // insertions to the same point will come out in the order they were added).
+ // The double-@ is intended to make it unlikely that the generated code
+ // could contain things that look like insertion points by accident.
+ //
+ // For example, the C++ code generator places the following line in the
+ // .pb.h files that it generates:
+ // // @@protoc_insertion_point(namespace_scope)
+ // This line appears within the scope of the file's package namespace, but
+ // outside of any particular class. Another plugin can then specify the
+ // insertion_point "namespace_scope" to generate additional classes or
+ // other declarations that should be placed in this scope.
+ //
+ // Note that if the line containing the insertion point begins with
+ // whitespace, the same whitespace will be added to every line of the
+ // inserted text. This is useful for languages like Python, where
+ // indentation matters. In these languages, the insertion point comment
+ // should be indented the same amount as any inserted code will need to be
+ // in order to work correctly in that context.
+ //
+ // The code generator that generates the initial file and the one which
+ // inserts into it must both run as part of a single invocatino of protoc.
+ // Code generators are executed in the order in which they appear on the
+ // command line.
+ //
+ // If |insertion_point| is present, |name| must also be present.
+ optional string insertion_point = 2;
+
+ // The file contents.
+ optional string content = 15;
+ }
+ repeated File file = 15;
+}
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index d301f01..fae83a3 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,38 @@ 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()) {
+ // Python pre-2.6 on Windows does not parse "inf" correctly. However,
+ // a numeric literal that is too big for a double will become infinity.
+ return "1e10000";
+ } else if (value == -numeric_limits<double>::infinity()) {
+ // See above.
+ return "-1e10000";
+ } else if (value != value) {
+ // infinity * 0 = nan
+ return "(1e10000 * 0)";
+ } else {
+ return SimpleDtoa(value);
+ }
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = field.default_value_float();
+ if (value == numeric_limits<float>::infinity()) {
+ // Python pre-2.6 on Windows does not parse "inf" correctly. However,
+ // a numeric literal that is too big for a double will become infinity.
+ return "1e10000";
+ } else if (value == -numeric_limits<float>::infinity()) {
+ // See above.
+ return "-1e10000";
+ } else if (value != value) {
+ // infinity - infinity = nan
+ return "(1e10000 * 0)";
+ } else {
+ return SimpleFtoa(value);
+ }
+ }
case FieldDescriptor::CPPTYPE_BOOL:
return field.default_value_bool() ? "True" : "False";
case FieldDescriptor::CPPTYPE_ENUM:
@@ -204,6 +247,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 +258,7 @@ bool Generator::Generate(const FileDescriptor* file,
printer_ = &printer;
PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
+ PrintFileDescriptor();
PrintTopLevelEnums();
PrintTopLevelExtensions();
PrintAllNestedEnumsInFile();
@@ -224,7 +272,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 +292,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 +355,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 +374,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 +444,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 +532,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 +566,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 +629,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 +651,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 +728,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 +847,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 +855,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 +963,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 8b99d62..43c2087 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/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
new file mode 100644
index 0000000..fde8876
--- /dev/null
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -0,0 +1,116 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// TODO(kenton): Share code with the versions of this test in other languages?
+// It seemed like parameterizing it would add more complexity than it is
+// worth.
+
+#include <google/protobuf/compiler/python/python_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace python {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+ TestGenerator() {}
+ ~TestGenerator() {}
+
+ virtual bool Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const {
+ TryInsert("test_pb2.py", "imports", output_directory);
+ TryInsert("test_pb2.py", "module_scope", output_directory);
+ TryInsert("test_pb2.py", "class_scope:foo.Bar", output_directory);
+ TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", output_directory);
+ return true;
+ }
+
+ void TryInsert(const string& filename, const string& insertion_point,
+ OutputDirectory* output_directory) const {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->OpenForInsert(filename, insertion_point));
+ io::Printer printer(output.get(), '$');
+ printer.Print("// inserted $name$\n", "name", insertion_point);
+ }
+};
+
+// This test verifies that all the expected insertion points exist. It does
+// not verify that they are correctly-placed; that would require actually
+// compiling the output which is a bit more than I care to do for this test.
+TEST(PythonPluginTest, PluginTest) {
+ File::WriteStringToFileOrDie(
+ "syntax = \"proto2\";\n"
+ "package foo;\n"
+ "message Bar {\n"
+ " message Baz {}\n"
+ "}\n",
+ TestTempDir() + "/test.proto");
+
+ google::protobuf::compiler::CommandLineInterface cli;
+ cli.SetInputsAreProtoPathRelative(true);
+
+ python::Generator python_generator;
+ TestGenerator test_generator;
+ cli.RegisterGenerator("--python_out", &python_generator, "");
+ cli.RegisterGenerator("--test_out", &test_generator, "");
+
+ string proto_path = "-I" + TestTempDir();
+ string python_out = "--python_out=" + TestTempDir();
+ string test_out = "--test_out=" + TestTempDir();
+
+ const char* argv[] = {
+ "protoc",
+ proto_path.c_str(),
+ python_out.c_str(),
+ test_out.c_str(),
+ "test.proto"
+ };
+
+ EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+} // namespace
+} // namespace python
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
new file mode 100644
index 0000000..de46a3e
--- /dev/null
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -0,0 +1,458 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/subprocess.h>
+
+#ifndef _WIN32
+#include <errno.h>
+#include <sys/wait.h>
+#include <signal.h>
+#endif
+
+#include <algorithm>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+#ifdef _WIN32
+
+static void CloseHandleOrDie(HANDLE handle) {
+ if (!CloseHandle(handle)) {
+ GOOGLE_LOG(FATAL) << "CloseHandle: "
+ << Subprocess::Win32ErrorMessage(GetLastError());
+ }
+}
+
+Subprocess::Subprocess()
+ : process_start_error_(ERROR_SUCCESS),
+ child_handle_(NULL), child_stdin_(NULL), child_stdout_(NULL) {}
+
+Subprocess::~Subprocess() {
+ if (child_stdin_ != NULL) {
+ CloseHandleOrDie(child_stdin_);
+ }
+ if (child_stdout_ != NULL) {
+ CloseHandleOrDie(child_stdout_);
+ }
+}
+
+void Subprocess::Start(const string& program, SearchMode search_mode) {
+ // Create the pipes.
+ HANDLE stdin_pipe_read;
+ HANDLE stdin_pipe_write;
+ HANDLE stdout_pipe_read;
+ HANDLE stdout_pipe_write;
+
+ if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, NULL, 0)) {
+ GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError());
+ }
+ if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, NULL, 0)) {
+ GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError());
+ }
+
+ // Make child side of the pipes inheritable.
+ if (!SetHandleInformation(stdin_pipe_read,
+ HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
+ GOOGLE_LOG(FATAL) << "SetHandleInformation: "
+ << Win32ErrorMessage(GetLastError());
+ }
+ if (!SetHandleInformation(stdout_pipe_write,
+ HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
+ GOOGLE_LOG(FATAL) << "SetHandleInformation: "
+ << Win32ErrorMessage(GetLastError());
+ }
+
+ // Setup STARTUPINFO to redirect handles.
+ STARTUPINFO startup_info;
+ ZeroMemory(&startup_info, sizeof(startup_info));
+ startup_info.cb = sizeof(startup_info);
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+ startup_info.hStdInput = stdin_pipe_read;
+ startup_info.hStdOutput = stdout_pipe_write;
+ startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+
+ if (startup_info.hStdError == INVALID_HANDLE_VALUE) {
+ GOOGLE_LOG(FATAL) << "GetStdHandle: "
+ << Win32ErrorMessage(GetLastError());
+ }
+
+ // CreateProcess() mutates its second parameter. WTF?
+ char* name_copy = strdup(program.c_str());
+
+ // Create the process.
+ PROCESS_INFORMATION process_info;
+
+ if (CreateProcess((search_mode == SEARCH_PATH) ? NULL : program.c_str(),
+ (search_mode == SEARCH_PATH) ? name_copy : NULL,
+ NULL, // process security attributes
+ NULL, // thread security attributes
+ TRUE, // inherit handles?
+ 0, // obscure creation flags
+ NULL, // environment (inherit from parent)
+ NULL, // current directory (inherit from parent)
+ &startup_info,
+ &process_info)) {
+ child_handle_ = process_info.hProcess;
+ CloseHandleOrDie(process_info.hThread);
+ child_stdin_ = stdin_pipe_write;
+ child_stdout_ = stdout_pipe_read;
+ } else {
+ process_start_error_ = GetLastError();
+ CloseHandleOrDie(stdin_pipe_write);
+ CloseHandleOrDie(stdout_pipe_read);
+ }
+
+ CloseHandleOrDie(stdin_pipe_read);
+ CloseHandleOrDie(stdout_pipe_write);
+ free(name_copy);
+}
+
+bool Subprocess::Communicate(const Message& input, Message* output,
+ string* error) {
+ if (process_start_error_ != ERROR_SUCCESS) {
+ *error = Win32ErrorMessage(process_start_error_);
+ return false;
+ }
+
+ GOOGLE_CHECK(child_handle_ != NULL) << "Must call Start() first.";
+
+ string input_data = input.SerializeAsString();
+ string output_data;
+
+ int input_pos = 0;
+
+ while (child_stdout_ != NULL) {
+ HANDLE handles[2];
+ int handle_count = 0;
+
+ if (child_stdin_ != NULL) {
+ handles[handle_count++] = child_stdin_;
+ }
+ if (child_stdout_ != NULL) {
+ handles[handle_count++] = child_stdout_;
+ }
+
+ DWORD wait_result =
+ WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE);
+
+ HANDLE signaled_handle;
+ if (wait_result >= WAIT_OBJECT_0 &&
+ wait_result < WAIT_OBJECT_0 + handle_count) {
+ signaled_handle = handles[wait_result - WAIT_OBJECT_0];
+ } else if (wait_result == WAIT_FAILED) {
+ GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: "
+ << Win32ErrorMessage(GetLastError());
+ } else {
+ GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: "
+ << wait_result;
+ }
+
+ if (signaled_handle == child_stdin_) {
+ DWORD n;
+ if (!WriteFile(child_stdin_,
+ input_data.data() + input_pos,
+ input_data.size() - input_pos,
+ &n, NULL)) {
+ // Child closed pipe. Presumably it will report an error later.
+ // Pretend we're done for now.
+ input_pos = input_data.size();
+ } else {
+ input_pos += n;
+ }
+
+ if (input_pos == input_data.size()) {
+ // We're done writing. Close.
+ CloseHandleOrDie(child_stdin_);
+ child_stdin_ = NULL;
+ }
+ } else if (signaled_handle == child_stdout_) {
+ char buffer[4096];
+ DWORD n;
+
+ if (!ReadFile(child_stdout_, buffer, sizeof(buffer), &n, NULL)) {
+ // We're done reading. Close.
+ CloseHandleOrDie(child_stdout_);
+ child_stdout_ = NULL;
+ } else {
+ output_data.append(buffer, n);
+ }
+ }
+ }
+
+ if (child_stdin_ != NULL) {
+ // Child did not finish reading input before it closed the output.
+ // Presumably it exited with an error.
+ CloseHandleOrDie(child_stdin_);
+ child_stdin_ = NULL;
+ }
+
+ DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE);
+
+ if (wait_result == WAIT_FAILED) {
+ GOOGLE_LOG(FATAL) << "WaitForSingleObject: "
+ << Win32ErrorMessage(GetLastError());
+ } else if (wait_result != WAIT_OBJECT_0) {
+ GOOGLE_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: "
+ << wait_result;
+ }
+
+ DWORD exit_code;
+ if (!GetExitCodeProcess(child_handle_, &exit_code)) {
+ GOOGLE_LOG(FATAL) << "GetExitCodeProcess: "
+ << Win32ErrorMessage(GetLastError());
+ }
+
+ CloseHandleOrDie(child_handle_);
+ child_handle_ = NULL;
+
+ if (exit_code != 0) {
+ *error = strings::Substitute(
+ "Plugin failed with status code $0.", exit_code);
+ return false;
+ }
+
+ if (!output->ParseFromString(output_data)) {
+ *error = "Plugin output is unparseable: " + CEscape(output_data);
+ return false;
+ }
+
+ return true;
+}
+
+string Subprocess::Win32ErrorMessage(DWORD error_code) {
+ char* message;
+
+ // WTF?
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, error_code, 0,
+ (LPTSTR)&message, // NOT A BUG!
+ 0, NULL);
+
+ string result = message;
+ LocalFree(message);
+ return result;
+}
+
+// ===================================================================
+
+#else // _WIN32
+
+Subprocess::Subprocess()
+ : child_pid_(-1), child_stdin_(-1), child_stdout_(-1) {}
+
+Subprocess::~Subprocess() {
+ if (child_stdin_ != -1) {
+ close(child_stdin_);
+ }
+ if (child_stdout_ != -1) {
+ close(child_stdout_);
+ }
+}
+
+void Subprocess::Start(const string& program, SearchMode search_mode) {
+ // Note that we assume that there are no other threads, thus we don't have to
+ // do crazy stuff like using socket pairs or avoiding libc locks.
+
+ // [0] is read end, [1] is write end.
+ int stdin_pipe[2];
+ int stdout_pipe[2];
+
+ pipe(stdin_pipe);
+ pipe(stdout_pipe);
+
+ char* argv[2] = { strdup(program.c_str()), NULL };
+
+ child_pid_ = fork();
+ if (child_pid_ == -1) {
+ GOOGLE_LOG(FATAL) << "fork: " << strerror(errno);
+ } else if (child_pid_ == 0) {
+ // We are the child.
+ dup2(stdin_pipe[0], STDIN_FILENO);
+ dup2(stdout_pipe[1], STDOUT_FILENO);
+
+ close(stdin_pipe[0]);
+ close(stdin_pipe[1]);
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+
+ switch (search_mode) {
+ case SEARCH_PATH:
+ execvp(argv[0], argv);
+ break;
+ case EXACT_NAME:
+ execv(argv[0], argv);
+ break;
+ }
+
+ // Write directly to STDERR_FILENO to avoid stdio code paths that may do
+ // stuff that is unsafe here.
+ write(STDERR_FILENO, argv[0], strlen(argv[0]));
+ const char* message = ": program not found or is not executable\n";
+ write(STDERR_FILENO, message, strlen(message));
+
+ // Must use _exit() rather than exit() to avoid flushing output buffers
+ // that will also be flushed by the parent.
+ _exit(1);
+ } else {
+ free(argv[0]);
+
+ close(stdin_pipe[0]);
+ close(stdout_pipe[1]);
+
+ child_stdin_ = stdin_pipe[1];
+ child_stdout_ = stdout_pipe[0];
+ }
+}
+
+bool Subprocess::Communicate(const Message& input, Message* output,
+ string* error) {
+
+ GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first.";
+
+ // The "sighandler_t" typedef is GNU-specific, so define our own.
+ typedef void SignalHandler(int);
+
+ // Make sure SIGPIPE is disabled so that if the child dies it doesn't kill us.
+ SignalHandler* old_pipe_handler = signal(SIGPIPE, SIG_IGN);
+
+ string input_data = input.SerializeAsString();
+ string output_data;
+
+ int input_pos = 0;
+ int max_fd = max(child_stdin_, child_stdout_);
+
+ while (child_stdout_ != -1) {
+ fd_set read_fds;
+ fd_set write_fds;
+ FD_ZERO(&read_fds);
+ FD_ZERO(&write_fds);
+ if (child_stdout_ != -1) {
+ FD_SET(child_stdout_, &read_fds);
+ }
+ if (child_stdin_ != -1) {
+ FD_SET(child_stdin_, &write_fds);
+ }
+
+ if (select(max_fd + 1, &read_fds, &write_fds, NULL, NULL) < 0) {
+ if (errno == EINTR) {
+ // Interrupted by signal. Try again.
+ continue;
+ } else {
+ GOOGLE_LOG(FATAL) << "select: " << strerror(errno);
+ }
+ }
+
+ if (child_stdin_ != -1 && FD_ISSET(child_stdin_, &write_fds)) {
+ int n = write(child_stdin_, input_data.data() + input_pos,
+ input_data.size() - input_pos);
+ if (n < 0) {
+ // Child closed pipe. Presumably it will report an error later.
+ // Pretend we're done for now.
+ input_pos = input_data.size();
+ } else {
+ input_pos += n;
+ }
+
+ if (input_pos == input_data.size()) {
+ // We're done writing. Close.
+ close(child_stdin_);
+ child_stdin_ = -1;
+ }
+ }
+
+ if (child_stdout_ != -1 && FD_ISSET(child_stdout_, &read_fds)) {
+ char buffer[4096];
+ int n = read(child_stdout_, buffer, sizeof(buffer));
+
+ if (n > 0) {
+ output_data.append(buffer, n);
+ } else {
+ // We're done reading. Close.
+ close(child_stdout_);
+ child_stdout_ = -1;
+ }
+ }
+ }
+
+ if (child_stdin_ != -1) {
+ // Child did not finish reading input before it closed the output.
+ // Presumably it exited with an error.
+ close(child_stdin_);
+ child_stdin_ = -1;
+ }
+
+ int status;
+ while (waitpid(child_pid_, &status, 0) == -1) {
+ if (errno != EINTR) {
+ GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno);
+ }
+ }
+
+ // Restore SIGPIPE handling.
+ signal(SIGPIPE, old_pipe_handler);
+
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) != 0) {
+ int error_code = WEXITSTATUS(status);
+ *error = strings::Substitute(
+ "Plugin failed with status code $0.", error_code);
+ return false;
+ }
+ } else if (WIFSIGNALED(status)) {
+ int signal = WTERMSIG(status);
+ *error = strings::Substitute(
+ "Plugin killed by signal $0.", signal);
+ return false;
+ } else {
+ *error = "Neither WEXITSTATUS nor WTERMSIG is true?";
+ return false;
+ }
+
+ if (!output->ParseFromString(output_data)) {
+ *error = "Plugin output is unparseable.";
+ return false;
+ }
+
+ return true;
+}
+
+#endif // !_WIN32
+
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_field.h b/src/google/protobuf/compiler/subprocess.h
index 1530778..f9e8ae8 100644
--- a/src/google/protobuf/compiler/javamicro/javamicro_field.h
+++ b/src/google/protobuf/compiler/subprocess.h
@@ -29,70 +29,79 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
+#ifndef GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
+#define GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN // right...
+#include <windows.h>
+#else // _WIN32
+#include <sys/types.h>
+#include <unistd.h>
+#endif // !_WIN32
#include <string>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/javamicro/javamicro_params.h>
namespace google {
namespace protobuf {
- namespace io {
- class Printer; // printer.h
- }
-}
-namespace protobuf {
+class Message;
+
namespace compiler {
-namespace javamicro {
-class FieldGenerator {
+// Utility class for launching sub-processes.
+class Subprocess {
public:
- //FieldGenerator() {}
- FieldGenerator(const Params& params) : params_(params) {}
- virtual ~FieldGenerator();
-
- virtual void GenerateMembers(io::Printer* printer) const = 0;
- virtual void GenerateMergingCode(io::Printer* printer) const = 0;
- virtual void GenerateParsingCode(io::Printer* printer) const = 0;
- virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
- virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
-
- virtual string GetBoxedType() const = 0;
+ Subprocess();
+ ~Subprocess();
+
+ enum SearchMode {
+ SEARCH_PATH, // Use PATH environment variable.
+ EXACT_NAME // Program is an exact file name; don't use the PATH.
+ };
+
+ // Start the subprocess. Currently we don't provide a way to specify
+ // arguments as protoc plugins don't have any.
+ void Start(const string& program, SearchMode search_mode);
+
+ // Serialize the input message and pipe it to the subprocess's stdin, then
+ // close the pipe. Meanwhile, read from the subprocess's stdout and parse
+ // the data into *output. All this is done carefully to avoid deadlocks.
+ // Returns true if successful. On any sort of error, returns false and sets
+ // *error to a description of the problem.
+ bool Communicate(const Message& input, Message* output, string* error);
+
+#ifdef _WIN32
+ // Given an error code, returns a human-readable error message. This is
+ // defined here so that CommandLineInterface can share it.
+ static string Subprocess::Win32ErrorMessage(DWORD error_code);
+#endif
- protected:
- const Params& params_;
private:
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
-};
-
-// Convenience class which constructs FieldGenerators for a Descriptor.
-class FieldGeneratorMap {
- public:
- explicit FieldGeneratorMap(const Descriptor* descriptor, const Params &params);
- ~FieldGeneratorMap();
+#ifdef _WIN32
+ DWORD process_start_error_;
+ HANDLE child_handle_;
- const FieldGenerator& get(const FieldDescriptor* field) const;
- const FieldGenerator& get_extension(int index) const;
+ // The file handles for our end of the child's pipes. We close each and
+ // set it to NULL when no longer needed.
+ HANDLE child_stdin_;
+ HANDLE child_stdout_;
- private:
- const Descriptor* descriptor_;
- scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
- scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
+#else // _WIN32
+ pid_t child_pid_;
- static FieldGenerator* MakeGenerator(const FieldDescriptor* field, const Params &params);
+ // The file descriptors for our end of the child's pipes. We close each and
+ // set it to -1 when no longer needed.
+ int child_stdin_;
+ int child_stdout_;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+#endif // !_WIN32
};
-} // namespace javamicro
} // namespace compiler
} // namespace protobuf
} // namespace google
-#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
+#endif // GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_enum.h b/src/google/protobuf/compiler/test_plugin.cc
index 9cf226f..5cbbf3d 100644
--- a/src/google/protobuf/compiler/javamicro/javamicro_enum.h
+++ b/src/google/protobuf/compiler/test_plugin.cc
@@ -29,59 +29,23 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
+//
+// This is a dummy code generator plugin used by
+// command_line_interface_unittest.
#include <string>
-#include <vector>
-
-#include <google/protobuf/compiler/javamicro/javamicro_params.h>
-#include <google/protobuf/descriptor.h>
-
-namespace google {
-namespace protobuf {
- namespace io {
- class Printer; // printer.h
- }
+#include <stdlib.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/compiler/mock_code_generator.h>
+#include <google/protobuf/stubs/strutil.h>
+
+int main(int argc, char* argv[]) {
+#ifdef _MSC_VER
+ // Don't print a silly message or stick a modal dialog box in my face,
+ // please.
+ _set_abort_behavior(0, ~0);
+#endif // !_MSC_VER
+
+ google::protobuf::compiler::MockCodeGenerator generator("test_plugin");
+ return google::protobuf::compiler::PluginMain(argc, argv, &generator);
}
-
-namespace protobuf {
-namespace compiler {
-namespace javamicro {
-
-class EnumGenerator {
- public:
- explicit EnumGenerator(const EnumDescriptor* descriptor, const Params& params);
- ~EnumGenerator();
-
- void Generate(io::Printer* printer);
-
- private:
- const Params& params_;
- const EnumDescriptor* descriptor_;
-
- // The proto language allows multiple enum constants to have the same numeric
- // value. Java, however, does not allow multiple enum constants to be
- // considered equivalent. We treat the first defined constant for any
- // given numeric value as "canonical" and the rest as aliases of that
- // canonical value.
- vector<const EnumValueDescriptor*> canonical_values_;
-
- struct Alias {
- const EnumValueDescriptor* value;
- const EnumValueDescriptor* canonical_value;
- };
- vector<Alias> aliases_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
-};
-
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
diff --git a/src/google/protobuf/compiler/zip_output_unittest.sh b/src/google/protobuf/compiler/zip_output_unittest.sh
new file mode 100755
index 0000000..259d5d2
--- /dev/null
+++ b/src/google/protobuf/compiler/zip_output_unittest.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2009 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Author: kenton@google.com (Kenton Varda)
+#
+# Test protoc's zip output mode.
+
+fail() {
+ echo "$@" >&2
+ exit 1
+}
+
+echo '
+ option java_multiple_files = true;
+ option java_package = "test.jar";
+ option java_outer_classname = "Outer";
+ message Foo {}
+ message Bar {}
+' > testzip.proto
+
+./protoc --cpp_out=testzip.zip --python_out=testzip.zip --java_out=testzip.jar \
+ testzip.proto || fail 'protoc failed.'
+
+echo "Testing output to zip..."
+if unzip -h > /dev/null; then
+ unzip -t testzip.zip > testzip.list || fail 'unzip failed.'
+
+ grep 'testing: testzip\.pb\.cc *OK$' testzip.list > /dev/null \
+ || fail 'testzip.pb.cc not found in output zip.'
+ grep 'testing: testzip\.pb\.h *OK$' testzip.list > /dev/null \
+ || fail 'testzip.pb.h not found in output zip.'
+ grep 'testing: testzip_pb2\.py *OK$' testzip.list > /dev/null \
+ || fail 'testzip_pb2.py not found in output zip.'
+ grep -i 'manifest' testzip.list > /dev/null \
+ && fail 'Zip file contained manifest.'
+else
+ echo "Warning: 'unzip' command not available. Skipping test."
+fi
+
+echo "Testing output to jar..."
+if jar c testzip.proto > /dev/null; then
+ jar tf testzip.jar > testzip.list || fail 'jar failed.'
+
+ grep '^test/jar/Foo\.java$' testzip.list > /dev/null \
+ || fail 'Foo.java not found in output jar.'
+ grep '^test/jar/Bar\.java$' testzip.list > /dev/null \
+ || fail 'Bar.java not found in output jar.'
+ grep '^test/jar/Outer\.java$' testzip.list > /dev/null \
+ || fail 'Outer.java not found in output jar.'
+ grep '^META-INF/MANIFEST\.MF$' testzip.list > /dev/null \
+ || fail 'Manifest not ofund in output jar.'
+else
+ echo "Warning: 'jar' command not available. Skipping test."
+fi
+
+echo PASS
diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc
new file mode 100644
index 0000000..53c1877
--- /dev/null
+++ b/src/google/protobuf/compiler/zip_writer.cc
@@ -0,0 +1,188 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: ambrose@google.com (Ambrose Feinstein),
+// kenton@google.com (Kenton Varda)
+//
+// Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+
+#include <google/protobuf/compiler/zip_writer.h>
+#include <google/protobuf/io/coded_stream.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+static const uint32 kCRC32Table[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+static uint32 ComputeCRC32(const string &buf) {
+ uint32 x = ~0U;
+ for (int i = 0; i < buf.size(); ++i) {
+ unsigned char c = buf[i];
+ x = kCRC32Table[(x ^ c) & 0xff] ^ (x >> 8);
+ }
+ return ~x;
+}
+
+static void WriteShort(io::CodedOutputStream *out, uint16 val) {
+ uint8 p[2];
+ p[0] = static_cast<uint8>(val);
+ p[1] = static_cast<uint8>(val >> 8);
+ out->WriteRaw(p, 2);
+}
+
+ZipWriter::ZipWriter(io::ZeroCopyOutputStream* raw_output)
+ : raw_output_(raw_output) {}
+ZipWriter::~ZipWriter() {}
+
+bool ZipWriter::Write(const string& filename, const string& contents) {
+ FileInfo info;
+
+ info.name = filename;
+ uint16 filename_size = filename.size();
+ info.offset = raw_output_->ByteCount();
+ info.size = contents.size();
+ info.crc32 = ComputeCRC32(contents);
+
+ files_.push_back(info);
+
+ // write file header
+ io::CodedOutputStream output(raw_output_);
+ output.WriteLittleEndian32(0x04034b50); // magic
+ WriteShort(&output, 10); // version needed to extract
+ WriteShort(&output, 0); // flags
+ WriteShort(&output, 0); // compression method: stored
+ WriteShort(&output, 0); // last modified time
+ WriteShort(&output, 0); // last modified date
+ output.WriteLittleEndian32(info.crc32); // crc-32
+ output.WriteLittleEndian32(info.size); // compressed size
+ output.WriteLittleEndian32(info.size); // uncompressed size
+ WriteShort(&output, filename_size); // file name length
+ WriteShort(&output, 0); // extra field length
+ output.WriteString(filename); // file name
+ output.WriteString(contents); // file data
+
+ return !output.HadError();
+}
+
+bool ZipWriter::WriteDirectory() {
+ uint16 num_entries = files_.size();
+ uint32 dir_ofs = raw_output_->ByteCount();
+
+ // write central directory
+ io::CodedOutputStream output(raw_output_);
+ for (int i = 0; i < num_entries; ++i) {
+ const string &filename = files_[i].name;
+ uint16 filename_size = filename.size();
+ uint32 crc32 = files_[i].crc32;
+ uint32 size = files_[i].size;
+ uint32 offset = files_[i].offset;
+
+ output.WriteLittleEndian32(0x02014b50); // magic
+ WriteShort(&output, 10); // version made by
+ WriteShort(&output, 10); // version needed to extract
+ WriteShort(&output, 0); // flags
+ WriteShort(&output, 0); // compression method: stored
+ WriteShort(&output, 0); // last modified time
+ WriteShort(&output, 0); // last modified date
+ output.WriteLittleEndian32(crc32); // crc-32
+ output.WriteLittleEndian32(size); // compressed size
+ output.WriteLittleEndian32(size); // uncompressed size
+ WriteShort(&output, filename_size); // file name length
+ WriteShort(&output, 0); // extra field length
+ WriteShort(&output, 0); // file comment length
+ WriteShort(&output, 0); // starting disk number
+ WriteShort(&output, 0); // internal file attributes
+ output.WriteLittleEndian32(0); // external file attributes
+ output.WriteLittleEndian32(offset); // local header offset
+ output.WriteString(filename); // file name
+ }
+ uint32 dir_len = output.ByteCount();
+
+ // write end of central directory marker
+ output.WriteLittleEndian32(0x06054b50); // magic
+ WriteShort(&output, 0); // disk number
+ WriteShort(&output, 0); // disk with start of central directory
+ WriteShort(&output, num_entries); // central directory entries (this disk)
+ WriteShort(&output, num_entries); // central directory entries (total)
+ output.WriteLittleEndian32(dir_len); // central directory byte size
+ output.WriteLittleEndian32(dir_ofs); // central directory offset
+ WriteShort(&output, 0); // comment length
+
+ return output.HadError();
+}
+
+} // namespace google
+} // namespace protobuf
+} // namespace compiler
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_generator.h b/src/google/protobuf/compiler/zip_writer.h
index a1c33b7..4289553 100644
--- a/src/google/protobuf/compiler/javamicro/javamicro_generator.h
+++ b/src/google/protobuf/compiler/zip_writer.h
@@ -29,44 +29,35 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
-// Based on original Protocol Buffers design by
-// Sanjay Ghemawat, Jeff Dean, and others.
-//
-// Generates Java micro code for a given .proto file.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MICRO_GENERATOR_H__
-#define GOOGLE_PROTOBUF_COMPILER_JAVA_MICRO_GENERATOR_H__
-#include <string>
-#include <google/protobuf/compiler/code_generator.h>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/zero_copy_stream.h>
namespace google {
namespace protobuf {
namespace compiler {
-namespace javamicro {
-// CodeGenerator implementation which generates Java micro code. If you create your
-// own protocol compiler binary and you want it to support Java output for the
-// micro runtime, you can do so by registering an instance of this CodeGenerator with
-// the CommandLineInterface in your main() function.
-class LIBPROTOC_EXPORT JavaMicroGenerator : public CodeGenerator {
+class ZipWriter {
public:
- JavaMicroGenerator();
- ~JavaMicroGenerator();
+ ZipWriter(io::ZeroCopyOutputStream* raw_output);
+ ~ZipWriter();
- // implements CodeGenerator ----------------------------------------
- bool Generate(const FileDescriptor* file,
- const string& parameter,
- OutputDirectory* output_directory,
- string* error) const;
+ bool Write(const string& filename, const string& contents);
+ bool WriteDirectory();
private:
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaMicroGenerator);
+ struct FileInfo {
+ string name;
+ uint32 offset;
+ uint32 size;
+ uint32 crc32;
+ };
+
+ io::ZeroCopyOutputStream* raw_output_;
+ vector<FileInfo> files_;
};
-} // namespace javamicro
-} // namespace compiler
-} // namespace protobuf
-
} // namespace google
-#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MICRO_GENERATOR_H__
+} // namespace protobuf
+} // namespace compiler