aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Feng Xiao <xfxyjwf@gmail.com>2014-11-19 17:14:29 -0800
committerGravatar Feng Xiao <xfxyjwf@gmail.com>2014-11-19 17:14:29 -0800
commit95c25918aa1550fcba50e1f76b9db6ebded25a80 (patch)
tree7a15bcee55b4dc9b85e84ec907ce8269b0ed1c02 /src
parent6a51460b985bc715b32d43b8e8f284e36b051f36 (diff)
parentcd980d1c13c736b0f9fc453843f696a93c2c2a71 (diff)
Merge nano proto into protobuf repository.
Diffstat (limited to 'src')
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum.cc111
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum.h87
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.cc520
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.h125
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_extension.cc150
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_extension.h74
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.cc143
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.h119
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_file.cc263
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_file.h94
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_generator.cc219
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_generator.h72
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.cc566
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.h189
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.cc555
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.h95
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.cc259
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.h96
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_params.h240
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.cc910
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.h126
21 files changed, 5013 insertions, 0 deletions
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc
new file mode 100644
index 00000000..f934b05f
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc
@@ -0,0 +1,111 @@
+// 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/javanano/javanano_params.h>
+#include <google/protobuf/compiler/javanano/javanano_enum.h>
+#include <google/protobuf/compiler/javanano/javanano_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 javanano {
+
+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(
+ "\n"
+ "// enum $classname$\n",
+ "classname", descriptor_->name());
+
+ // Start of container interface
+ bool use_shell_class = params_.java_enum_style();
+ if (use_shell_class) {
+ printer->Print(
+ "public interface $classname$ {\n",
+ "classname", RenameJavaKeywords(descriptor_->name()));
+ printer->Indent();
+ }
+
+ // Canonical values
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ printer->Print(
+ "public static final int $name$ = $canonical_value$;\n",
+ "name", RenameJavaKeywords(canonical_values_[i]->name()),
+ "canonical_value", SimpleItoa(canonical_values_[i]->number()));
+ }
+
+ // Aliases
+ for (int i = 0; i < aliases_.size(); i++) {
+ printer->Print(
+ "public static final int $name$ = $canonical_name$;\n",
+ "name", RenameJavaKeywords(aliases_[i].value->name()),
+ "canonical_name", RenameJavaKeywords(aliases_[i].canonical_value->name()));
+ }
+
+ // End of container interface
+ if (use_shell_class) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.h b/src/google/protobuf/compiler/javanano/javanano_enum.h
new file mode 100644
index 00000000..10dd3648
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_enum.h
@@ -0,0 +1,87 @@
+// 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_JAVANANO_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+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 javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
new file mode 100644
index 00000000..8a59d323
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
@@ -0,0 +1,520 @@
+// 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/javanano/javanano_enum_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_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 javanano {
+
+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"] =
+ RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+ (*variables)["capitalized_name"] =
+ RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
+ (*variables)["number"] = SimpleItoa(descriptor->number());
+ if (params.use_reference_types_for_primitives()
+ && !params.reftypes_primitive_enums()
+ && !descriptor->is_repeated()) {
+ (*variables)["type"] = "java.lang.Integer";
+ (*variables)["default"] = "null";
+ } else {
+ (*variables)["type"] = "int";
+ (*variables)["default"] = DefaultValue(params, descriptor);
+ }
+ (*variables)["repeated_default"] =
+ "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
+ (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+ (*variables)["tag_size"] = SimpleItoa(
+ internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ (*variables)["non_packed_tag"] = SimpleItoa(
+ internal::WireFormatLite::MakeTag(descriptor->number(),
+ internal::WireFormat::WireTypeForFieldType(descriptor->type())));
+ (*variables)["message_name"] = descriptor->containing_type()->name();
+}
+
+void LoadEnumValues(const Params& params,
+ const EnumDescriptor* enum_descriptor, vector<string>* canonical_values) {
+ string enum_class_name = ClassName(params, enum_descriptor);
+ for (int i = 0; i < enum_descriptor->value_count(); i++) {
+ const EnumValueDescriptor* value = enum_descriptor->value(i);
+ const EnumValueDescriptor* canonical_value =
+ enum_descriptor->FindValueByNumber(value->number());
+ if (value == canonical_value) {
+ canonical_values->push_back(
+ enum_class_name + "." + RenameJavaKeywords(value->name()));
+ }
+ }
+}
+
+void PrintCaseLabels(
+ io::Printer* printer, const vector<string>& canonical_values) {
+ for (int i = 0; i < canonical_values.size(); i++) {
+ printer->Print(
+ " case $value$:\n",
+ "value", canonical_values[i]);
+ }
+}
+
+} // namespace
+
+// ===================================================================
+
+EnumFieldGenerator::
+EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetEnumVariables(params, descriptor, &variables_);
+ LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_,
+ "public $type$ $name$;\n");
+
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "public boolean has$capitalized_name$;\n");
+ }
+}
+
+void EnumFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = $default$;\n");
+
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "has$capitalized_name$ = false;\n");
+ }
+}
+
+void EnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int value = input.readInt32();\n"
+ "switch (value) {\n");
+ PrintCaseLabels(printer, canonical_values_);
+ printer->Print(variables_,
+ " this.$name$ = value;\n");
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ " has$capitalized_name$ = true;\n");
+ }
+ printer->Print(
+ " break;\n"
+ "}\n");
+ // No default case: in case of invalid value from the wire, preserve old
+ // field value. Also we are not storing the invalid value into the unknown
+ // fields, because there is no way to get the value out.
+}
+
+void EnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->is_required() && !params_.generate_has()) {
+ // Always serialize a required field if we don't have the 'has' signal.
+ printer->Print(variables_,
+ "output.writeInt32($number$, this.$name$);\n");
+ } else {
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
+ } else {
+ printer->Print(variables_,
+ "if (this.$name$ != $default$) {\n");
+ }
+ printer->Print(variables_,
+ " output.writeInt32($number$, this.$name$);\n"
+ "}\n");
+ }
+}
+
+void EnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ if (descriptor_->is_required() && !params_.generate_has()) {
+ printer->Print(variables_,
+ "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeInt32Size($number$, this.$name$);\n");
+ } else {
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
+ } else {
+ printer->Print(variables_,
+ "if (this.$name$ != $default$) {\n");
+ }
+ printer->Print(variables_,
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeInt32Size($number$, this.$name$);\n"
+ "}\n");
+ }
+}
+
+void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const {
+ if (params_.use_reference_types_for_primitives()
+ && !params_.reftypes_primitive_enums()) {
+ printer->Print(variables_,
+ "if (this.$name$ == null) {\n"
+ " if (other.$name$ != null) {\n"
+ " return false;\n"
+ " }\n"
+ "} else if (!this.$name$.equals(other.$name$)) {\n"
+ " return false;"
+ "}\n");
+ } else {
+ // We define equality as serialized form equality. If generate_has(),
+ // then if the field value equals the default value in both messages,
+ // but one's 'has' field is set and the other's is not, the serialized
+ // forms are different and we should return false.
+ printer->Print(variables_,
+ "if (this.$name$ != other.$name$");
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "\n"
+ " || (this.$name$ == $default$\n"
+ " && this.has$capitalized_name$ != other.has$capitalized_name$)");
+ }
+ printer->Print(") {\n"
+ " return false;\n"
+ "}\n");
+ }
+}
+
+void EnumFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const {
+ printer->Print(
+ "result = 31 * result + ");
+ if (params_.use_reference_types_for_primitives()
+ && !params_.reftypes_primitive_enums()) {
+ printer->Print(variables_,
+ "(this.$name$ == null ? 0 : this.$name$)");
+ } else {
+ printer->Print(variables_,
+ "this.$name$");
+ }
+ printer->Print(";\n");
+}
+
+// ===================================================================
+
+AccessorEnumFieldGenerator::
+AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params, int has_bit_index)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetEnumVariables(params, descriptor, &variables_);
+ LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
+ SetBitOperationVariables("has", has_bit_index, &variables_);
+}
+
+AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
+
+void AccessorEnumFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_,
+ "private int $name$_;\n"
+ "public int get$capitalized_name$() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int value) {\n"
+ " $name$_ = value;\n"
+ " $set_has$;\n"
+ " return this;\n"
+ "}\n"
+ "public boolean has$capitalized_name$() {\n"
+ " return $get_has$;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_ = $default$;\n"
+ " $clear_has$;\n"
+ " return this;\n"
+ "}\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_ = $default$;\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int value = input.readInt32();\n"
+ "switch (value) {\n");
+ PrintCaseLabels(printer, canonical_values_);
+ printer->Print(variables_,
+ " $name$_ = value;\n"
+ " $set_has$;\n"
+ " break;\n"
+ "}\n");
+ // No default case: in case of invalid value from the wire, preserve old
+ // field value. Also we are not storing the invalid value into the unknown
+ // fields, because there is no way to get the value out.
+}
+
+void AccessorEnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_has$) {\n"
+ " output.writeInt32($number$, $name$_);\n"
+ "}\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_has$) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeInt32Size($number$, $name$_);\n"
+ "}\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($different_has$\n"
+ " || $name$_ != other.$name$_) {\n"
+ " return false;\n"
+ "}\n");
+}
+
+void AccessorEnumFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = 31 * result + $name$_;\n");
+}
+
+// ===================================================================
+
+RepeatedEnumFieldGenerator::
+RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetEnumVariables(params, descriptor, &variables_);
+ LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_,
+ "public $type$[] $name$;\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = $repeated_default$;\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ // First, figure out the maximum length of the array, then parse,
+ // and finally copy the valid values to the field.
+ printer->Print(variables_,
+ "int length = com.google.protobuf.nano.WireFormatNano\n"
+ " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
+ "int[] validValues = new int[length];\n"
+ "int validCount = 0;\n"
+ "for (int i = 0; i < length; i++) {\n"
+ " if (i != 0) { // tag for first value already consumed.\n"
+ " input.readTag();\n"
+ " }\n"
+ " int value = input.readInt32();\n"
+ " switch (value) {\n");
+ printer->Indent();
+ PrintCaseLabels(printer, canonical_values_);
+ printer->Outdent();
+ printer->Print(variables_,
+ " validValues[validCount++] = value;\n"
+ " break;\n"
+ " }\n"
+ "}\n"
+ "if (validCount != 0) {\n"
+ " int i = this.$name$ == null ? 0 : this.$name$.length;\n"
+ " if (i == 0 && validCount == validValues.length) {\n"
+ " this.$name$ = validValues;\n"
+ " } else {\n"
+ " int[] newArray = new int[i + validCount];\n"
+ " if (i != 0) {\n"
+ " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+ " }\n"
+ " java.lang.System.arraycopy(validValues, 0, newArray, i, validCount);\n"
+ " this.$name$ = newArray;\n"
+ " }\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergingCodeFromPacked(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int bytes = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(bytes);\n"
+ "// First pass to compute array length.\n"
+ "int arrayLength = 0;\n"
+ "int startPos = input.getPosition();\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " switch (input.readInt32()) {\n");
+ printer->Indent();
+ PrintCaseLabels(printer, canonical_values_);
+ printer->Outdent();
+ printer->Print(variables_,
+ " arrayLength++;\n"
+ " break;\n"
+ " }\n"
+ "}\n"
+ "if (arrayLength != 0) {\n"
+ " input.rewindToPosition(startPos);\n"
+ " int i = this.$name$ == null ? 0 : this.$name$.length;\n"
+ " int[] newArray = new int[i + arrayLength];\n"
+ " if (i != 0) {\n"
+ " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+ " }\n"
+ " while (input.getBytesUntilLimit() > 0) {\n"
+ " int value = input.readInt32();\n"
+ " switch (value) {\n");
+ printer->Indent();
+ printer->Indent();
+ PrintCaseLabels(printer, canonical_values_);
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(variables_,
+ " newArray[i++] = value;\n"
+ " break;\n"
+ " }\n"
+ " }\n"
+ " this.$name$ = newArray;\n"
+ "}\n"
+ "input.popLimit(limit);\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateRepeatedDataSizeCode(io::Printer* printer) const {
+ // Creates a variable dataSize and puts the serialized size in there.
+ printer->Print(variables_,
+ "int dataSize = 0;\n"
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " int element = this.$name$[i];\n"
+ " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeInt32SizeNoTag(element);\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n");
+ printer->Indent();
+
+ if (descriptor_->options().packed()) {
+ GenerateRepeatedDataSizeCode(printer);
+ printer->Print(variables_,
+ "output.writeRawVarint32($tag$);\n"
+ "output.writeRawVarint32(dataSize);\n"
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " output.writeRawVarint32(this.$name$[i]);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " output.writeInt32($number$, this.$name$[i]);\n"
+ "}\n");
+ }
+
+ printer->Outdent();
+ printer->Print(variables_,
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n");
+ printer->Indent();
+
+ GenerateRepeatedDataSizeCode(printer);
+
+ printer->Print(
+ "size += dataSize;\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "size += $tag_size$;\n"
+ "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeRawVarint32Size(dataSize);\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * this.$name$.length;\n");
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+ " this.$name$, other.$name$)) {\n"
+ " return false;\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = 31 * result\n"
+ " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
new file mode 100644
index 00000000..00adc61f
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
@@ -0,0 +1,125 @@
+// 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_JAVANANO_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <vector>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class EnumFieldGenerator : public FieldGenerator {
+ public:
+ explicit EnumFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
+ ~EnumFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ vector<string> canonical_values_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class AccessorEnumFieldGenerator : public FieldGenerator {
+ public:
+ explicit AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params, int has_bit_index);
+ ~AccessorEnumFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ vector<string> canonical_values_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorEnumFieldGenerator);
+};
+
+class RepeatedEnumFieldGenerator : public FieldGenerator {
+ public:
+ explicit RepeatedEnumFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
+ ~RepeatedEnumFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateMergingCodeFromPacked(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
+
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ vector<string> canonical_values_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc
new file mode 100644
index 00000000..754ed550
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_extension.cc
@@ -0,0 +1,150 @@
+// 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: bduff@google.com (Brian Duff)
+
+#include <google/protobuf/compiler/javanano/javanano_extension.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/wire_format.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+const char* GetTypeConstantName(const FieldDescriptor::Type type) {
+ switch (type) {
+ case FieldDescriptor::TYPE_INT32 : return "TYPE_INT32" ;
+ case FieldDescriptor::TYPE_UINT32 : return "TYPE_UINT32" ;
+ case FieldDescriptor::TYPE_SINT32 : return "TYPE_SINT32" ;
+ case FieldDescriptor::TYPE_FIXED32 : return "TYPE_FIXED32" ;
+ case FieldDescriptor::TYPE_SFIXED32: return "TYPE_SFIXED32";
+ case FieldDescriptor::TYPE_INT64 : return "TYPE_INT64" ;
+ case FieldDescriptor::TYPE_UINT64 : return "TYPE_UINT64" ;
+ case FieldDescriptor::TYPE_SINT64 : return "TYPE_SINT64" ;
+ case FieldDescriptor::TYPE_FIXED64 : return "TYPE_FIXED64" ;
+ case FieldDescriptor::TYPE_SFIXED64: return "TYPE_SFIXED64";
+ case FieldDescriptor::TYPE_FLOAT : return "TYPE_FLOAT" ;
+ case FieldDescriptor::TYPE_DOUBLE : return "TYPE_DOUBLE" ;
+ case FieldDescriptor::TYPE_BOOL : return "TYPE_BOOL" ;
+ case FieldDescriptor::TYPE_STRING : return "TYPE_STRING" ;
+ case FieldDescriptor::TYPE_BYTES : return "TYPE_BYTES" ;
+ case FieldDescriptor::TYPE_ENUM : return "TYPE_ENUM" ;
+ case FieldDescriptor::TYPE_GROUP : return "TYPE_GROUP" ;
+ case FieldDescriptor::TYPE_MESSAGE : return "TYPE_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;
+}
+
+} // namespace
+
+void SetVariables(const FieldDescriptor* descriptor, const Params params,
+ map<string, string>* variables) {
+ (*variables)["extends"] = ClassName(params, descriptor->containing_type());
+ (*variables)["name"] = RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+ bool repeated = descriptor->is_repeated();
+ (*variables)["repeated"] = repeated ? "Repeated" : "";
+ (*variables)["type"] = GetTypeConstantName(descriptor->type());
+ JavaType java_type = GetJavaType(descriptor->type());
+ string tag = SimpleItoa(WireFormat::MakeTag(descriptor));
+ if (java_type == JAVATYPE_MESSAGE) {
+ (*variables)["ext_type"] = "MessageTyped";
+ string message_type = ClassName(params, descriptor->message_type());
+ if (repeated) {
+ message_type += "[]";
+ }
+ (*variables)["class"] = message_type;
+ // For message typed extensions, tags_params contains a single tag
+ // for both singular and repeated cases.
+ (*variables)["tag_params"] = tag;
+ } else {
+ (*variables)["ext_type"] = "PrimitiveTyped";
+ if (!repeated) {
+ (*variables)["class"] = BoxedPrimitiveTypeName(java_type);
+ (*variables)["tag_params"] = tag;
+ } else {
+ (*variables)["class"] = PrimitiveTypeName(java_type) + "[]";
+ if (!descriptor->is_packable()) {
+ // Non-packable: nonPackedTag == tag, packedTag == 0
+ (*variables)["tag_params"] = tag + ", " + tag + ", 0";
+ } else if (descriptor->options().packed()) {
+ // Packable and packed: tag == packedTag
+ string non_packed_tag = SimpleItoa(WireFormatLite::MakeTag(
+ descriptor->number(),
+ WireFormat::WireTypeForFieldType(descriptor->type())));
+ (*variables)["tag_params"] = tag + ", " + non_packed_tag + ", " + tag;
+ } else {
+ // Packable and not packed: tag == nonPackedTag
+ string packed_tag = SimpleItoa(WireFormatLite::MakeTag(
+ descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+ (*variables)["tag_params"] = tag + ", " + tag + ", " + packed_tag;
+ }
+ }
+ }
+}
+
+ExtensionGenerator::
+ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : params_(params), descriptor_(descriptor) {
+ SetVariables(descriptor, params, &variables_);
+}
+
+ExtensionGenerator::~ExtensionGenerator() {}
+
+void ExtensionGenerator::Generate(io::Printer* printer) const {
+ printer->Print("\n");
+ PrintFieldComment(printer, descriptor_);
+ printer->Print(variables_,
+ "public static final com.google.protobuf.nano.Extension<\n"
+ " $extends$,\n"
+ " $class$> $name$ =\n"
+ " com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n"
+ " com.google.protobuf.nano.Extension.$type$,\n"
+ " $class$.class,\n"
+ " $tag_params$);\n");
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.h b/src/google/protobuf/compiler/javanano/javanano_extension.h
new file mode 100644
index 00000000..4843e296
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_extension.h
@@ -0,0 +1,74 @@
+// 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: bduff@google.com (Brian Duff)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.pb.h>
+
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class ExtensionGenerator {
+ public:
+ explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params);
+ ~ExtensionGenerator();
+
+ void Generate(io::Printer* printer) const;
+
+ private:
+ const Params& params_;
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc
new file mode 100644
index 00000000..e3e4cefe
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_field.cc
@@ -0,0 +1,143 @@
+// 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/javanano/javanano_field.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
+#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
+#include <google/protobuf/compiler/javanano/javanano_message_field.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+FieldGenerator::~FieldGenerator() {}
+
+bool FieldGenerator::SavedDefaultNeeded() const {
+ // No saved default for this field by default.
+ // Subclasses whose instances may need saved defaults will override this
+ // and return the appropriate value.
+ return false;
+}
+
+void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
+ // No saved default for this field by default.
+ // Subclasses whose instances may need saved defaults will override this
+ // and generate the appropriate init code to the printer.
+}
+
+void FieldGenerator::GenerateMergingCodeFromPacked(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, const Params &params)
+ : descriptor_(descriptor),
+ field_generators_(
+ new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
+
+ int next_has_bit_index = 0;
+ bool saved_defaults_needed = false;
+ // Construct all the FieldGenerators.
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ FieldGenerator* field_generator = MakeGenerator(
+ descriptor->field(i), params, &next_has_bit_index);
+ saved_defaults_needed = saved_defaults_needed
+ || field_generator->SavedDefaultNeeded();
+ field_generators_[i].reset(field_generator);
+ }
+ total_bits_ = next_has_bit_index;
+ saved_defaults_needed_ = saved_defaults_needed;
+}
+
+FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
+ const Params &params, int* next_has_bit_index) {
+ JavaType java_type = GetJavaType(field);
+ if (field->is_repeated()) {
+ switch (java_type) {
+ case JAVATYPE_MESSAGE:
+ return new RepeatedMessageFieldGenerator(field, params);
+ case JAVATYPE_ENUM:
+ return new RepeatedEnumFieldGenerator(field, params);
+ default:
+ return new RepeatedPrimitiveFieldGenerator(field, params);
+ }
+ } else if (params.optional_field_accessors() && field->is_optional()
+ && java_type != JAVATYPE_MESSAGE) {
+ // We need a has-bit for each primitive/enum field because their default
+ // values could be same as explicitly set values. But we don't need it
+ // for a message field because they have no defaults and Nano uses 'null'
+ // for unset messages, which cannot be set explicitly.
+ switch (java_type) {
+ case JAVATYPE_ENUM:
+ return new AccessorEnumFieldGenerator(
+ field, params, (*next_has_bit_index)++);
+ default:
+ return new AccessorPrimitiveFieldGenerator(
+ field, params, (*next_has_bit_index)++);
+ }
+ } else {
+ switch (java_type) {
+ 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()];
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
new file mode 100644
index 00000000..6170c2c0
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_field.h
@@ -0,0 +1,119 @@
+// 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_JAVANANO_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class FieldGenerator {
+ public:
+ FieldGenerator(const Params& params) : params_(params) {}
+ virtual ~FieldGenerator();
+
+ virtual bool SavedDefaultNeeded() const;
+ virtual void GenerateInitSavedDefaultCode(io::Printer* printer) const;
+
+ // Generates code for Java fields and methods supporting this field.
+ // If this field needs a saved default (SavedDefaultNeeded() is true),
+ // then @lazy_init controls how the static field for that default value
+ // and its initialization code should be generated. If @lazy_init is
+ // true, the static field is not declared final and the initialization
+ // code is generated only when GenerateInitSavedDefaultCode is called;
+ // otherwise, the static field is declared final and initialized inline.
+ // GenerateInitSavedDefaultCode will not be called in the latter case.
+ virtual void GenerateMembers(
+ io::Printer* printer, bool lazy_init) const = 0;
+
+ virtual void GenerateClearCode(io::Printer* printer) const = 0;
+ virtual void GenerateMergingCode(io::Printer* printer) const = 0;
+
+ // Generates code to merge from packed serialized form. The default
+ // implementation will fail; subclasses which can handle packed serialized
+ // forms will override this and print appropriate code to the printer.
+ virtual void GenerateMergingCodeFromPacked(io::Printer* printer) const;
+
+ virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+ virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
+ virtual void GenerateHashCodeCode(io::Printer* printer) const = 0;
+
+ 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();
+
+ const FieldGenerator& get(const FieldDescriptor* field) const;
+ int total_bits() const { return total_bits_; }
+ bool saved_defaults_needed() const { return saved_defaults_needed_; }
+
+ private:
+ const Descriptor* descriptor_;
+ scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
+ int total_bits_;
+ bool saved_defaults_needed_;
+
+ static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+ const Params &params, int* next_has_bit_index);
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc
new file mode 100644
index 00000000..3676ab9d
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_file.cc
@@ -0,0 +1,263 @@
+// 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 <iostream>
+
+#include <google/protobuf/compiler/javanano/javanano_file.h>
+#include <google/protobuf/compiler/javanano/javanano_enum.h>
+#include <google/protobuf/compiler/javanano/javanano_extension.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_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 javanano {
+
+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) && !params_.store_unknown_fields()) {
+ error->assign(file_->name());
+ error->append(
+ ": Java NANO_RUNTIME only supports extensions when the "
+ "'store_unknown_fields' generator option is 'true'.");
+ return false;
+ }
+
+ if (file_->service_count() != 0 && !params_.ignore_services()) {
+ error->assign(file_->name());
+ error->append(
+ ": Java NANO_RUNTIME does not support services\"");
+ return false;
+ }
+
+ if (!IsOuterClassNeeded(params_, file_)) {
+ return true;
+ }
+
+ // Check whether legacy javanano generator would omit the outer class.
+ if (!params_.has_java_outer_classname(file_->name())
+ && file_->message_type_count() == 1
+ && file_->enum_type_count() == 0 && file_->extension_count() == 0) {
+ cout << "INFO: " << file_->name() << ":" << endl;
+ cout << "Javanano generator has changed to align with java generator. "
+ "An outer class will be created for this file and the single message "
+ "in the file will become a nested class. Use java_multiple_files to "
+ "skip generating the outer class, or set an explicit "
+ "java_outer_classname to suppress this message." << endl;
+ }
+
+ // 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.
+ bool found_conflict = false;
+ for (int i = 0; !found_conflict && i < file_->message_type_count(); i++) {
+ if (file_->message_type(i)->name() == classname_) {
+ found_conflict = true;
+ }
+ }
+ if (params_.java_enum_style()) {
+ for (int i = 0; !found_conflict && i < file_->enum_type_count(); i++) {
+ if (file_->enum_type(i)->name() == classname_) {
+ found_conflict = true;
+ }
+ }
+ }
+ if (found_conflict) {
+ error->assign(file_->name());
+ error->append(
+ ": Cannot generate Java output because the file's outer 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.");
+ 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");
+ if (!java_package_.empty()) {
+ printer->Print(
+ "\n"
+ "package $package$;\n",
+ "package", java_package_);
+ }
+
+ // Note: constants (from enums, emitted in the loop below) may have the same names as constants
+ // in the nested classes. This causes Java warnings, but is not fatal, so we suppress those
+ // warnings here in the top-most class declaration.
+ printer->Print(
+ "\n"
+ "@SuppressWarnings(\"hiding\")\n"
+ "public interface $classname$ {\n",
+ "classname", classname_);
+ printer->Indent();
+
+ // -----------------------------------------------------------------
+
+ // Extensions.
+ for (int i = 0; i < file_->extension_count(); i++) {
+ ExtensionGenerator(file_->extension(i), params_).Generate(printer);
+ }
+
+ // Enums.
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator(file_->enum_type(i), params_).Generate(printer);
+ }
+
+ // Messages.
+ if (!params_.java_multiple_files(file_->name())) {
+ 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);
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+}
+
+template<typename GeneratorClass, typename DescriptorClass>
+static void GenerateSibling(const string& package_dir,
+ const string& java_package,
+ const DescriptorClass* descriptor,
+ GeneratorContext* 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");
+ if (!java_package.empty()) {
+ printer.Print(
+ "\n"
+ "package $package$;\n",
+ "package", java_package);
+ }
+
+ GeneratorClass(descriptor, params).Generate(&printer);
+}
+
+void FileGenerator::GenerateSiblings(const string& package_dir,
+ GeneratorContext* output_directory,
+ vector<string>* file_list) {
+ if (params_.java_multiple_files(file_->name())) {
+ 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_);
+ }
+
+ if (params_.java_enum_style()) {
+ 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_);
+ }
+ }
+ }
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_file.h b/src/google/protobuf/compiler/javanano/javanano_file.h
new file mode 100644
index 00000000..217eafe2
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_file.h
@@ -0,0 +1,94 @@
+// 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_JAVANANO_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
+
+#include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+
+namespace google {
+namespace protobuf {
+ class FileDescriptor; // descriptor.h
+ namespace io {
+ class Printer; // printer.h
+ }
+ namespace compiler {
+ class GeneratorContext; // code_generator.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+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,
+ GeneratorContext* 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_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
new file mode 100644
index 00000000..b5fbcd5f
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -0,0 +1,219 @@
+// 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/javanano/javanano_params.h>
+#include <google/protobuf/compiler/javanano/javanano_generator.h>
+#include <google/protobuf/compiler/javanano/javanano_file.h>
+#include <google/protobuf/compiler/javanano/javanano_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 javanano {
+
+namespace {
+
+string TrimString(const string& s) {
+ string::size_type start = s.find_first_not_of(" \n\r\t");
+ if (start == string::npos) {
+ return "";
+ }
+ string::size_type end = s.find_last_not_of(" \n\r\t") + 1;
+ return s.substr(start, end - start);
+}
+
+} // namespace
+
+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());
+ }
+ if (file->options().has_java_multiple_files()) {
+ params.set_java_multiple_files(
+ file->name(), file->options().java_multiple_files());
+ }
+
+ // Loop through all dependent files recursively
+ // adding dep
+ for (int i = 0; i < file->dependency_count(); i++) {
+ UpdateParamsRecursively(params, file->dependency(i));
+ }
+}
+
+JavaNanoGenerator::JavaNanoGenerator() {}
+JavaNanoGenerator::~JavaNanoGenerator() {}
+
+bool JavaNanoGenerator::Generate(const FileDescriptor* file,
+ const string& parameter,
+ GeneratorContext* output_directory,
+ string* error) const {
+ vector<pair<string, string> > options;
+
+ 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());
+
+ // Update per file params
+ UpdateParamsRecursively(params, file);
+
+ // Replace any existing options with ones from command line
+ for (int i = 0; i < options.size(); i++) {
+ string option_name = TrimString(options[i].first);
+ string option_value = TrimString(options[i].second);
+ if (option_name == "output_list_file") {
+ output_list_file = option_value;
+ } else if (option_name == "java_package") {
+ vector<string> parts;
+ SplitStringUsing(option_value, "|", &parts);
+ if (parts.size() != 2) {
+ *error = "Bad java_package, expecting filename|PackageName found '"
+ + option_value + "'";
+ return false;
+ }
+ params.set_java_package(parts[0], parts[1]);
+ } else if (option_name == "java_outer_classname") {
+ vector<string> parts;
+ SplitStringUsing(option_value, "|", &parts);
+ if (parts.size() != 2) {
+ *error = "Bad java_outer_classname, "
+ "expecting filename|ClassName found '"
+ + option_value + "'";
+ return false;
+ }
+ params.set_java_outer_classname(parts[0], parts[1]);
+ } else if (option_name == "store_unknown_fields") {
+ params.set_store_unknown_fields(option_value == "true");
+ } else if (option_name == "java_multiple_files") {
+ params.set_override_java_multiple_files(option_value == "true");
+ } else if (option_name == "java_nano_generate_has") {
+ params.set_generate_has(option_value == "true");
+ } else if (option_name == "enum_style") {
+ params.set_java_enum_style(option_value == "java");
+ } else if (option_name == "optional_field_style") {
+ params.set_optional_field_accessors(option_value == "accessors");
+ params.set_use_reference_types_for_primitives(option_value == "reftypes"
+ || option_value == "reftypes_compat_mode");
+ params.set_reftypes_primitive_enums(
+ option_value == "reftypes_compat_mode");
+ if (option_value == "reftypes_compat_mode") {
+ params.set_generate_clear(false);
+ }
+ } else if (option_name == "generate_equals") {
+ params.set_generate_equals(option_value == "true");
+ } else if (option_name == "ignore_services") {
+ params.set_ignore_services(option_value == "true");
+ } else if (option_name == "parcelable_messages") {
+ params.set_parcelable_messages(option_value == "true");
+ } else {
+ *error = "Ignore unknown javanano generator option: " + option_name;
+ }
+ }
+
+ // Check illegal parameter combinations
+ // Note: the enum-like optional_field_style generator param ensures
+ // that we can never have illegal combinations of field styles
+ // (e.g. reftypes and accessors can't be on at the same time).
+ if (params.generate_has()
+ && (params.optional_field_accessors()
+ || params.use_reference_types_for_primitives())) {
+ error->assign("java_nano_generate_has=true cannot be used in conjunction"
+ " with optional_field_style=accessors or optional_field_style=reftypes");
+ return false;
+ }
+
+ // -----------------------------------------------------------------
+
+ 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;
+
+ if (IsOuterClassNeeded(params, file)) {
+ 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/javanano/javanano_generator.h b/src/google/protobuf/compiler/javanano/javanano_generator.h
new file mode 100644
index 00000000..6f9f7f2a
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.h
@@ -0,0 +1,72 @@
+// 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.
+//
+// Generates Java nano code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+// CodeGenerator implementation which generates Java nano code. If you create your
+// own protocol compiler binary and you want it to support Java output for the
+// nano runtime, you can do so by registering an instance of this CodeGenerator with
+// the CommandLineInterface in your main() function.
+class LIBPROTOC_EXPORT JavaNanoGenerator : public CodeGenerator {
+ public:
+ JavaNanoGenerator();
+ ~JavaNanoGenerator();
+
+ // implements CodeGenerator ----------------------------------------
+ bool Generate(const FileDescriptor* file,
+ const string& parameter,
+ GeneratorContext* output_directory,
+ string* error) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaNanoGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
new file mode 100644
index 00000000..2149418a
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -0,0 +1,566 @@
+// 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 <limits>
+#include <vector>
+
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+const char kThickSeparator[] =
+ "// ===================================================================\n";
+const char kThinSeparator[] =
+ "// -------------------------------------------------------------------\n";
+
+class RenameKeywords {
+ private:
+ hash_set<string> java_keywords_set_;
+
+ public:
+ RenameKeywords() {
+ static const char* kJavaKeywordsList[] = {
+ // Reserved Java Keywords
+ "abstract", "assert", "boolean", "break", "byte", "case", "catch",
+ "char", "class", "const", "continue", "default", "do", "double", "else",
+ "enum", "extends", "final", "finally", "float", "for", "goto", "if",
+ "implements", "import", "instanceof", "int", "interface", "long",
+ "native", "new", "package", "private", "protected", "public", "return",
+ "short", "static", "strictfp", "super", "switch", "synchronized",
+ "this", "throw", "throws", "transient", "try", "void", "volatile", "while",
+
+ // Reserved Keywords for Literals
+ "false", "null", "true"
+ };
+
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(kJavaKeywordsList); i++) {
+ java_keywords_set_.insert(kJavaKeywordsList[i]);
+ }
+ }
+
+ // Used to rename the a field name if it's a java keyword. Specifically
+ // this is used to rename the ["name"] or ["capitalized_name"] field params.
+ // (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html)
+ string RenameJavaKeywordsImpl(const string& input) {
+ string result = input;
+
+ if (java_keywords_set_.find(result) != java_keywords_set_.end()) {
+ result += "_";
+ }
+
+ return result;
+ }
+
+};
+
+static RenameKeywords sRenameKeywords;
+
+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 RenameJavaKeywords(const string& input) {
+ return sRenameKeywords.RenameJavaKeywordsImpl(input);
+}
+
+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) {
+ if (params.has_java_outer_classname(file->name())) {
+ return params.java_outer_classname(file->name());
+ } else {
+ // Use the filename itself 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);
+ }
+ return UnderscoresToCamelCaseImpl(StripProto(basename), true);
+ }
+}
+
+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;
+ }
+}
+
+bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) {
+ // If java_multiple_files is false, the outer class is always needed.
+ if (!params.java_multiple_files(file->name())) {
+ return true;
+ }
+
+ // File-scope extensions need the outer class as the scope.
+ if (file->extension_count() != 0) {
+ return true;
+ }
+
+ // If container interfaces are not generated, file-scope enums need the
+ // outer class as the scope.
+ if (file->enum_type_count() != 0 && !params.java_enum_style()) {
+ return true;
+ }
+
+ return false;
+}
+
+string ToJavaName(const Params& params, const string& name, bool is_class,
+ const Descriptor* parent, const FileDescriptor* file) {
+ string result;
+ if (parent != NULL) {
+ result.append(ClassName(params, parent));
+ } else if (is_class && params.java_multiple_files(file->name())) {
+ result.append(FileJavaPackage(params, file));
+ } else {
+ result.append(ClassName(params, file));
+ }
+ if (!result.empty()) result.append(1, '.');
+ result.append(RenameJavaKeywords(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) {
+ const Descriptor* parent = descriptor->containing_type();
+ // When using Java enum style, an enum's class name contains the enum name.
+ // Use the standard ToJavaName translation.
+ if (params.java_enum_style()) {
+ return ToJavaName(params, descriptor->name(), true, parent,
+ descriptor->file());
+ }
+ // Otherwise the enum members are accessed from the enclosing class.
+ if (parent != NULL) {
+ return ClassName(params, parent);
+ } else {
+ return ClassName(params, descriptor->file());
+ }
+}
+
+string FieldConstantName(const FieldDescriptor *field) {
+ string name = field->name() + "_FIELD_NUMBER";
+ UpperString(&name);
+ return name;
+}
+
+string FieldDefaultConstantName(const FieldDescriptor *field) {
+ return "_" + RenameJavaKeywords(UnderscoresToCamelCase(field)) + "Default";
+}
+
+void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
+ // We don't want to print group bodies so we cut off after the first line
+ // (the second line for extensions).
+ string def = field->DebugString();
+ string::size_type first_line_end = def.find_first_of('\n');
+ printer->Print("// $def$\n",
+ "def", def.substr(0, first_line_end));
+ if (field->is_extension()) {
+ string::size_type second_line_start = first_line_end + 1;
+ string::size_type second_line_length =
+ def.find('\n', second_line_start) - second_line_start;
+ printer->Print("// $def$\n",
+ "def", def.substr(second_line_start, second_line_length));
+ }
+}
+
+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;
+}
+
+string 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 "byte[]";
+ case JAVATYPE_ENUM : return "int";
+ case JAVATYPE_MESSAGE: return "";
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+string 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 "byte[]";
+ case JAVATYPE_ENUM : return "java.lang.Integer";
+ case JAVATYPE_MESSAGE: return "";
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+string EmptyArrayName(const Params& params, const FieldDescriptor* field) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_INT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
+ case JAVATYPE_LONG : return "com.google.protobuf.nano.WireFormatNano.EMPTY_LONG_ARRAY";
+ case JAVATYPE_FLOAT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_FLOAT_ARRAY";
+ case JAVATYPE_DOUBLE : return "com.google.protobuf.nano.WireFormatNano.EMPTY_DOUBLE_ARRAY";
+ case JAVATYPE_BOOLEAN: return "com.google.protobuf.nano.WireFormatNano.EMPTY_BOOLEAN_ARRAY";
+ case JAVATYPE_STRING : return "com.google.protobuf.nano.WireFormatNano.EMPTY_STRING_ARRAY";
+ case JAVATYPE_BYTES : return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES_ARRAY";
+ case JAVATYPE_ENUM : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
+ case JAVATYPE_MESSAGE: return ClassName(params, field->message_type()) + ".EMPTY_ARRAY";
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+string DefaultValue(const Params& params, const FieldDescriptor* field) {
+ if (field->label() == FieldDescriptor::LABEL_REPEATED) {
+ return EmptyArrayName(params, field);
+ }
+
+ if (params.use_reference_types_for_primitives()) {
+ if (params.reftypes_primitive_enums()
+ && field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ return "Integer.MIN_VALUE";
+ }
+ return "null";
+ }
+
+ // 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: {
+ 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->default_value_string().empty()) {
+ // Point it to the static final in the generated code.
+ return FieldDefaultConstantName(field);
+ } else {
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES";
+ } else {
+ return "\"\"";
+ }
+ }
+
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return ClassName(params, field->enum_type()) + "." +
+ RenameJavaKeywords(field->default_value_enum()->name());
+
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "null";
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+
+static const char* kBitMasks[] = {
+ "0x00000001",
+ "0x00000002",
+ "0x00000004",
+ "0x00000008",
+ "0x00000010",
+ "0x00000020",
+ "0x00000040",
+ "0x00000080",
+
+ "0x00000100",
+ "0x00000200",
+ "0x00000400",
+ "0x00000800",
+ "0x00001000",
+ "0x00002000",
+ "0x00004000",
+ "0x00008000",
+
+ "0x00010000",
+ "0x00020000",
+ "0x00040000",
+ "0x00080000",
+ "0x00100000",
+ "0x00200000",
+ "0x00400000",
+ "0x00800000",
+
+ "0x01000000",
+ "0x02000000",
+ "0x04000000",
+ "0x08000000",
+ "0x10000000",
+ "0x20000000",
+ "0x40000000",
+ "0x80000000",
+};
+
+string GetBitFieldName(int index) {
+ string var_name = "bitField";
+ var_name += SimpleItoa(index);
+ var_name += "_";
+ return var_name;
+}
+
+string GetBitFieldNameForBit(int bit_index) {
+ return GetBitFieldName(bit_index / 32);
+}
+
+string GenerateGetBit(int bit_index) {
+ string var_name = GetBitFieldNameForBit(bit_index);
+ int bit_in_var_index = bit_index % 32;
+
+ string mask = kBitMasks[bit_in_var_index];
+ string result = "((" + var_name + " & " + mask + ") != 0)";
+ return result;
+}
+
+string GenerateSetBit(int bit_index) {
+ string var_name = GetBitFieldNameForBit(bit_index);
+ int bit_in_var_index = bit_index % 32;
+
+ string mask = kBitMasks[bit_in_var_index];
+ string result = var_name + " |= " + mask;
+ return result;
+}
+
+string GenerateClearBit(int bit_index) {
+ string var_name = GetBitFieldNameForBit(bit_index);
+ int bit_in_var_index = bit_index % 32;
+
+ string mask = kBitMasks[bit_in_var_index];
+ string result = var_name + " = (" + var_name + " & ~" + mask + ")";
+ return result;
+}
+
+string GenerateDifferentBit(int bit_index) {
+ string var_name = GetBitFieldNameForBit(bit_index);
+ int bit_in_var_index = bit_index % 32;
+
+ string mask = kBitMasks[bit_in_var_index];
+ string result = "((" + var_name + " & " + mask
+ + ") != (other." + var_name + " & " + mask + "))";
+ return result;
+}
+
+void SetBitOperationVariables(const string name,
+ int bitIndex, map<string, string>* variables) {
+ (*variables)["get_" + name] = GenerateGetBit(bitIndex);
+ (*variables)["set_" + name] = GenerateSetBit(bitIndex);
+ (*variables)["clear_" + name] = GenerateClearBit(bitIndex);
+ (*variables)["different_" + name] = GenerateDifferentBit(bitIndex);
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h
new file mode 100644
index 00000000..29310743
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h
@@ -0,0 +1,189 @@
+// 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_JAVANANO_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
+
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+// 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);
+
+// Appends an "_" to the end of a field where the name is a reserved java
+// keyword. For example int32 public = 1 will generate int public_.
+string RenameJavaKeywords(const string& input);
+
+// 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);
+
+// Returns whether the Java outer class is needed, i.e. whether the option
+// java_multiple_files is false, or the proto file contains any file-scope
+// enums/extensions.
+bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file);
+
+// Converts the given simple name of a proto entity to its fully-qualified name
+// in the Java namespace, given that it is in the given file enclosed in the
+// given parent message (or NULL for file-scope entities). Whether the file's
+// outer class name should be included in the return value depends on factors
+// inferrable from the given arguments, including is_class which indicates
+// whether the entity translates to a Java class.
+string ToJavaName(const Params& params, const string& name, bool is_class,
+ const Descriptor* parent, 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->name(), true,
+ descriptor->containing_type(), descriptor->file());
+}
+string ClassName(const Params& params, const EnumDescriptor* descriptor);
+inline string ClassName(const Params& params,
+ const ServiceDescriptor* descriptor) {
+ return ToJavaName(params, descriptor->name(), true, NULL, descriptor->file());
+}
+inline string ExtensionIdentifierName(const Params& params,
+ const FieldDescriptor* descriptor) {
+ return ToJavaName(params, descriptor->name(), false,
+ descriptor->extension_scope(), 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);
+
+string FieldDefaultConstantName(const FieldDescriptor *field);
+
+// Print the field's proto-syntax definition as a comment.
+void PrintFieldComment(io::Printer* printer, 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());
+}
+
+string PrimitiveTypeName(JavaType 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.
+string BoxedPrimitiveTypeName(JavaType type);
+
+string EmptyArrayName(const Params& params, const FieldDescriptor* field);
+
+string DefaultValue(const Params& params, const FieldDescriptor* field);
+
+
+// Methods for shared bitfields.
+
+// Gets the name of the shared bitfield for the given field index.
+string GetBitFieldName(int index);
+
+// Gets the name of the shared bitfield for the given bit index.
+// Effectively, GetBitFieldName(bit_index / 32)
+string GetBitFieldNameForBit(int bit_index);
+
+// Generates the java code for the expression that returns whether the bit at
+// the given bit index is set.
+// Example: "((bitField1_ & 0x04000000) != 0)"
+string GenerateGetBit(int bit_index);
+
+// Generates the java code for the expression that sets the bit at the given
+// bit index.
+// Example: "bitField1_ |= 0x04000000"
+string GenerateSetBit(int bit_index);
+
+// Generates the java code for the expression that clears the bit at the given
+// bit index.
+// Example: "bitField1_ = (bitField1_ & ~0x04000000)"
+string GenerateClearBit(int bit_index);
+
+// Generates the java code for the expression that returns whether the bit at
+// the given bit index contains different values in the current object and
+// another object accessible via the variable 'other'.
+// Example: "((bitField1_ & 0x04000000) != (other.bitField1_ & 0x04000000))"
+string GenerateDifferentBit(int bit_index);
+
+// Sets the 'get_*', 'set_*', 'clear_*' and 'different_*' variables, where * is
+// the given name of the bit, to the appropriate Java expressions for the given
+// bit index.
+void SetBitOperationVariables(const string name,
+ int bitIndex, map<string, string>* variables);
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
new file mode 100644
index 00000000..7c52ca31
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -0,0 +1,555 @@
+// 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/javanano/javanano_message.h>
+#include <google/protobuf/compiler/javanano/javanano_enum.h>
+#include <google/protobuf/compiler/javanano/javanano_extension.h>
+#include <google/protobuf/compiler/javanano/javanano_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 javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+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;
+}
+
+} // 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);
+ }
+}
+
+void MessageGenerator::Generate(io::Printer* printer) {
+ if (!params_.store_unknown_fields() &&
+ (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
+ GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
+ "'store_unknown_fields' generator option is 'true'\n";
+ }
+
+ const string& file_name = descriptor_->file()->name();
+ bool is_own_file =
+ params_.java_multiple_files(file_name)
+ && descriptor_->containing_type() == NULL;
+
+ if (is_own_file) {
+ // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
+ // may have the same names as constants in the nested classes. This causes Java warnings, but
+ // is not fatal, so we suppress those warnings here in the top-most class declaration.
+ printer->Print(
+ "\n"
+ "@SuppressWarnings(\"hiding\")\n"
+ "public final class $classname$ extends\n",
+ "classname", descriptor_->name());
+ } else {
+ printer->Print(
+ "\n"
+ "public static final class $classname$ extends\n",
+ "classname", descriptor_->name());
+ }
+ if (params_.store_unknown_fields() && params_.parcelable_messages()) {
+ printer->Print(
+ " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$> {\n",
+ "classname", descriptor_->name());
+ } else if (params_.store_unknown_fields()) {
+ printer->Print(
+ " com.google.protobuf.nano.ExtendableMessageNano<$classname$> {\n",
+ "classname", descriptor_->name());
+ } else if (params_.parcelable_messages()) {
+ printer->Print(
+ " com.google.protobuf.nano.android.ParcelableMessageNano {\n");
+ } else {
+ printer->Print(
+ " com.google.protobuf.nano.MessageNano {\n");
+ }
+ printer->Indent();
+
+ // Nested types and extensions
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
+ }
+
+ 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);
+ }
+
+ // Lazy initialization of otherwise static final fields can help prevent the
+ // class initializer from being generated. We want to prevent it because it
+ // stops ProGuard from inlining any methods in this class into call sites and
+ // therefore reducing the method count. However, extensions are best kept as
+ // public static final fields with initializers, so with their existence we
+ // won't bother with lazy initialization.
+ bool lazy_init = descriptor_->extension_count() == 0;
+
+ // Empty array
+ if (lazy_init) {
+ printer->Print(
+ "\n"
+ "private static volatile $classname$[] _emptyArray;\n"
+ "public static $classname$[] emptyArray() {\n"
+ " // Lazily initializes the empty array\n"
+ " if (_emptyArray == null) {\n"
+ " synchronized (\n"
+ " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
+ " if (_emptyArray == null) {\n"
+ " _emptyArray = new $classname$[0];\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " return _emptyArray;\n"
+ "}\n",
+ "classname", descriptor_->name());
+ } else {
+ printer->Print(
+ "\n"
+ "private static final $classname$[] EMPTY_ARRAY = {};\n"
+ "public static $classname$[] emptyArray() {\n"
+ " return EMPTY_ARRAY;\n"
+ "}\n",
+ "classname", descriptor_->name());
+ }
+
+ // Integers for bit fields
+ int totalInts = (field_generators_.total_bits() + 31) / 32;
+ if (totalInts > 0) {
+ printer->Print("\n");
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ // Fields and maybe their default values
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ PrintFieldComment(printer, descriptor_->field(i));
+ field_generators_.get(descriptor_->field(i)).GenerateMembers(
+ printer, lazy_init);
+ }
+
+ // Constructor, with lazy init code if needed
+ if (lazy_init && field_generators_.saved_defaults_needed()) {
+ printer->Print(
+ "\n"
+ "private static volatile boolean _classInitialized;\n"
+ "\n"
+ "public $classname$() {\n"
+ " // Lazily initializes the field defaults\n"
+ " if (!_classInitialized) {\n"
+ " synchronized (\n"
+ " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
+ " if (!_classInitialized) {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitSavedDefaultCode(printer);
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " _classInitialized = true;\n"
+ " }\n"
+ " }\n"
+ " }\n");
+ if (params_.generate_clear()) {
+ printer->Print(" clear();\n");
+ }
+ printer->Print("}\n");
+ } else {
+ if (params_.generate_clear()) {
+ printer->Print(
+ "\n"
+ "public $classname$() {\n"
+ " clear();\n"
+ "}\n",
+ "classname", descriptor_->name());
+ }
+ }
+
+ // Other methods in this class
+
+ GenerateClear(printer);
+
+ if (params_.generate_equals()) {
+ GenerateEquals(printer);
+ GenerateHashCode(printer);
+ }
+
+ GenerateMessageSerializationMethods(printer);
+ GenerateMergeFromMethods(printer);
+ GenerateParseFromMethods(printer);
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageGenerator::
+GenerateMessageSerializationMethods(io::Printer* printer) {
+ // Rely on the parent implementations of writeTo() and getSerializedSize()
+ // if there are no fields to serialize in this message.
+ if (descriptor_->field_count() == 0) {
+ return;
+ }
+
+ scoped_array<const FieldDescriptor*> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ printer->Print(
+ "\n"
+ "@Override\n"
+ "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano 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]);
+ }
+
+ // The parent implementation will write any unknown fields if necessary.
+ printer->Print(
+ "super.writeTo(output);\n");
+
+ printer->Outdent();
+ printer->Print("}\n");
+
+ // The parent implementation will get the serialized size for unknown
+ // fields if necessary.
+ printer->Print(
+ "\n"
+ "@Override\n"
+ "protected int computeSerializedSize() {\n"
+ " int size = super.computeSerializedSize();\n");
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
+ }
+
+ printer->Outdent();
+ printer->Print(
+ " return size;\n"
+ "}\n");
+}
+
+void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
+ scoped_array<const FieldDescriptor*> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ printer->Print(
+ "\n"
+ "@Override\n"
+ "public $classname$ mergeFrom(\n"
+ " com.google.protobuf.nano.CodedInputByteBufferNano 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");
+
+ printer->Indent();
+ if (params_.store_unknown_fields()) {
+ printer->Print(
+ "if (!storeUnknownField(input, tag)) {\n"
+ " return this;\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
+ " return this;\n" // it's an endgroup tag
+ "}\n");
+ }
+ printer->Print("break;\n");
+ printer->Outdent();
+ printer->Print("}\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ uint32 tag = WireFormatLite::MakeTag(field->number(),
+ WireFormat::WireTypeForFieldType(field->type()));
+
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateMergingCode(printer);
+
+ printer->Outdent();
+ 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).GenerateMergingCodeFromPacked(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // switch (tag)
+ " }\n" // while (true)
+ "}\n");
+}
+
+void MessageGenerator::
+GenerateParseFromMethods(io::Printer* printer) {
+ // Note: These are separate from GenerateMessageSerializationMethods()
+ // because they need to be generated even for messages that are optimized
+ // for code size.
+ printer->Print(
+ "\n"
+ "public static $classname$ parseFrom(byte[] data)\n"
+ " throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
+ " return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
+ "}\n"
+ "\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
+ " throws java.io.IOException {\n"
+ " return new $classname$().mergeFrom(input);\n"
+ "}\n",
+ "classname", descriptor_->name());
+}
+
+void MessageGenerator::GenerateSerializeOneField(
+ io::Printer* printer, const FieldDescriptor* field) {
+ field_generators_.get(field).GenerateSerializationCode(printer);
+}
+
+void MessageGenerator::GenerateClear(io::Printer* printer) {
+ if (!params_.generate_clear()) {
+ return;
+ }
+ printer->Print(
+ "\n"
+ "public $classname$ clear() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+
+ // Clear bit fields.
+ int totalInts = (field_generators_.total_bits() + 31) / 32;
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("$bit_field_name$ = 0;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+
+ // Call clear for all of the fields.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ field_generators_.get(field).GenerateClearCode(printer);
+ }
+
+ // Clear unknown fields.
+ if (params_.store_unknown_fields()) {
+ printer->Print("unknownFieldData = null;\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ " cachedSize = -1;\n"
+ " return this;\n"
+ "}\n");
+}
+
+void MessageGenerator::GenerateEquals(io::Printer* printer) {
+ // Don't override if there are no fields. We could generate an
+ // equals method that compares types, but often empty messages
+ // are used as namespaces.
+ if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
+ return;
+ }
+
+ printer->Print(
+ "\n"
+ "@Override\n"
+ "public boolean equals(Object o) {\n");
+ printer->Indent();
+ printer->Print(
+ "if (o == this) {\n"
+ " return true;\n"
+ "}\n"
+ "if (!(o instanceof $classname$)) {\n"
+ " return false;\n"
+ "}\n"
+ "$classname$ other = ($classname$) o;\n",
+ "classname", descriptor_->name());
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ field_generators_.get(field).GenerateEqualsCode(printer);
+ }
+
+ if (params_.store_unknown_fields()) {
+ printer->Print(
+ "return unknownFieldDataEquals(other);\n");
+ } else {
+ printer->Print(
+ "return true;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void MessageGenerator::GenerateHashCode(io::Printer* printer) {
+ if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
+ return;
+ }
+
+ printer->Print(
+ "\n"
+ "@Override\n"
+ "public int hashCode() {\n");
+ printer->Indent();
+
+ printer->Print("int result = 17;\n");
+ printer->Print("result = 31 * result + getClass().getName().hashCode();\n");
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ field_generators_.get(field).GenerateHashCodeCode(printer);
+ }
+
+ if (params_.store_unknown_fields()) {
+ printer->Print(
+ "result = 31 * result + unknownFieldDataHashCode();\n");
+ }
+
+ printer->Print("return result;\n");
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h
new file mode 100644
index 00000000..6f25a3a0
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_message.h
@@ -0,0 +1,95 @@
+// 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_JAVANANO_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
+
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+#include <google/protobuf/compiler/javanano/javanano_params.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+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 GenerateEquals(io::Printer* printer);
+ void GenerateHashCode(io::Printer* printer);
+
+ const Params& params_;
+ const Descriptor* descriptor_;
+ FieldGeneratorMap field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
new file mode 100644
index 00000000..a46081d0
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -0,0 +1,259 @@
+// 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/javanano/javanano_message_field.h>
+#include <google/protobuf/compiler/javanano/javanano_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 javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+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"] =
+ RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+ (*variables)["capitalized_name"] =
+ RenameJavaKeywords(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();
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+}
+
+} // 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, bool /* unused lazy_init */) const {
+ printer->Print(variables_,
+ "public $type$ $name$;\n");
+}
+
+void MessageFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = null;\n");
+}
+
+void MessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ == null) {\n"
+ " this.$name$ = new $type$();\n"
+ "}\n");
+
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "input.readGroup(this.$name$, $number$);\n");
+ } else {
+ printer->Print(variables_,
+ "input.readMessage(this.$name$);\n");
+ }
+}
+
+void MessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null) {\n"
+ " output.write$group_or_message$($number$, this.$name$);\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$group_or_message$Size($number$, this.$name$);\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ == null) { \n"
+ " if (other.$name$ != null) {\n"
+ " return false;\n"
+ " }\n"
+ "} else {\n"
+ " if (!this.$name$.equals(other.$name$)) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = 31 * result +\n"
+ " (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
+}
+
+// ===================================================================
+
+RepeatedMessageFieldGenerator::
+RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetMessageVariables(params, descriptor, &variables_);
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+void RepeatedMessageFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_,
+ "public $type$[] $name$;\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = $type$.emptyArray();\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ // First, figure out the length of the array, then parse.
+ printer->Print(variables_,
+ "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
+ " .getRepeatedFieldArrayLength(input, $tag$);\n"
+ "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
+ "$type$[] newArray =\n"
+ " new $type$[i + arrayLength];\n"
+ "if (i != 0) {\n"
+ " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+ "}\n"
+ "for (; i < newArray.length - 1; i++) {\n"
+ " newArray[i] = new $type$();\n");
+
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ " input.readGroup(newArray[i], $number$);\n");
+ } else {
+ printer->Print(variables_,
+ " input.readMessage(newArray[i]);\n");
+ }
+
+ printer->Print(variables_,
+ " input.readTag();\n"
+ "}\n"
+ "// Last one without readTag.\n"
+ "newArray[i] = new $type$();\n");
+
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "input.readGroup(newArray[i], $number$);\n");
+ } else {
+ printer->Print(variables_,
+ "input.readMessage(newArray[i]);\n");
+ }
+
+ printer->Print(variables_,
+ "this.$name$ = newArray;\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n"
+ " for (int i = 0; i < this.$name$.length; i++) {\n"
+ " $type$ element = this.$name$[i];\n"
+ " if (element != null) {\n"
+ " output.write$group_or_message$($number$, element);\n"
+ " }\n"
+ " }\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n"
+ " for (int i = 0; i < this.$name$.length; i++) {\n"
+ " $type$ element = this.$name$[i];\n"
+ " if (element != null) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$group_or_message$Size($number$, element);\n"
+ " }\n"
+ " }\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+ " this.$name$, other.$name$)) {\n"
+ " return false;\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = 31 * result\n"
+ " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
new file mode 100644
index 00000000..5d35fd24
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h
@@ -0,0 +1,96 @@
+// 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_JAVANANO_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class MessageFieldGenerator : public FieldGenerator {
+ public:
+ explicit MessageFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
+ ~MessageFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) 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, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h
new file mode 100644
index 00000000..4691f360
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_params.h
@@ -0,0 +1,240 @@
+// 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_JAVANANO_JAVANANO_PARAMS_H_
+#define PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
+
+#include <map>
+#include <set>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+enum eMultipleFiles { JAVANANO_MUL_UNSET, JAVANANO_MUL_FALSE, JAVANANO_MUL_TRUE };
+
+// Parameters for used by the generators
+class Params {
+ public:
+ typedef map<string, string> NameMap;
+ typedef set<string> NameSet;
+ private:
+ string empty_;
+ string base_name_;
+ eMultipleFiles override_java_multiple_files_;
+ bool store_unknown_fields_;
+ NameMap java_packages_;
+ NameMap java_outer_classnames_;
+ NameSet java_multiple_files_;
+ bool generate_has_;
+ bool java_enum_style_;
+ bool optional_field_accessors_;
+ bool use_reference_types_for_primitives_;
+ bool generate_equals_;
+ bool ignore_services_;
+ bool parcelable_messages_;
+ bool reftypes_primitive_enums_;
+ bool generate_clear_;
+
+ public:
+ Params(const string & base_name) :
+ empty_(""),
+ base_name_(base_name),
+ override_java_multiple_files_(JAVANANO_MUL_UNSET),
+ store_unknown_fields_(false),
+ generate_has_(false),
+ java_enum_style_(false),
+ optional_field_accessors_(false),
+ use_reference_types_for_primitives_(false),
+ generate_equals_(false),
+ ignore_services_(false),
+ parcelable_messages_(false),
+ reftypes_primitive_enums_(false),
+ generate_clear_(true) {
+ }
+
+ 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_override_java_multiple_files(bool java_multiple_files) {
+ if (java_multiple_files) {
+ override_java_multiple_files_ = JAVANANO_MUL_TRUE;
+ } else {
+ override_java_multiple_files_ = JAVANANO_MUL_FALSE;
+ }
+ }
+ void clear_override_java_multiple_files() {
+ override_java_multiple_files_ = JAVANANO_MUL_UNSET;
+ }
+
+ void set_java_multiple_files(const string& file_name, bool value) {
+ if (value) {
+ java_multiple_files_.insert(file_name);
+ } else {
+ java_multiple_files_.erase(file_name);
+ }
+ }
+ bool java_multiple_files(const string& file_name) const {
+ switch (override_java_multiple_files_) {
+ case JAVANANO_MUL_FALSE:
+ return false;
+ case JAVANANO_MUL_TRUE:
+ return true;
+ default:
+ return java_multiple_files_.find(file_name)
+ != java_multiple_files_.end();
+ }
+ }
+
+ void set_store_unknown_fields(bool value) {
+ store_unknown_fields_ = value;
+ }
+ bool store_unknown_fields() const {
+ return store_unknown_fields_;
+ }
+
+ void set_generate_has(bool value) {
+ generate_has_ = value;
+ }
+ bool generate_has() const {
+ return generate_has_;
+ }
+
+ void set_java_enum_style(bool value) {
+ java_enum_style_ = value;
+ }
+ bool java_enum_style() const {
+ return java_enum_style_;
+ }
+
+ void set_optional_field_accessors(bool value) {
+ optional_field_accessors_ = value;
+ }
+ bool optional_field_accessors() const {
+ return optional_field_accessors_;
+ }
+
+ void set_use_reference_types_for_primitives(bool value) {
+ use_reference_types_for_primitives_ = value;
+ }
+ bool use_reference_types_for_primitives() const {
+ return use_reference_types_for_primitives_;
+ }
+
+ void set_generate_equals(bool value) {
+ generate_equals_ = value;
+ }
+ bool generate_equals() const {
+ return generate_equals_;
+ }
+
+ void set_ignore_services(bool value) {
+ ignore_services_ = value;
+ }
+ bool ignore_services() const {
+ return ignore_services_;
+ }
+
+ void set_parcelable_messages(bool value) {
+ parcelable_messages_ = value;
+ }
+ bool parcelable_messages() const {
+ return parcelable_messages_;
+ }
+
+ void set_reftypes_primitive_enums(bool value) {
+ reftypes_primitive_enums_ = value;
+ }
+ bool reftypes_primitive_enums() const {
+ return reftypes_primitive_enums_;
+ }
+
+ void set_generate_clear(bool value) {
+ generate_clear_ = value;
+ }
+ bool generate_clear() const {
+ return generate_clear_;
+ }
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
new file mode 100644
index 00000000..a3bc3a84
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -0,0 +1,910 @@
+// 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 <math.h>
+#include <string>
+
+#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+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;
+}
+
+bool IsArrayType(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 false;
+ case JAVATYPE_BYTES : return true;
+ case JAVATYPE_ENUM : return false;
+ case JAVATYPE_MESSAGE: return false;
+
+ // 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 AllAscii(const string& text) {
+ for (int i = 0; i < text.size(); i++) {
+ if ((text[i] & 0x80) != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
+ map<string, string>* variables) {
+ (*variables)["name"] =
+ RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+ (*variables)["capitalized_name"] =
+ RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
+ (*variables)["number"] = SimpleItoa(descriptor->number());
+ if (params.use_reference_types_for_primitives()
+ && !descriptor->is_repeated()) {
+ (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+ } else {
+ (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
+ }
+ // Deals with defaults. For C++-string types (string and bytes),
+ // we might need to have the generated code do the unicode decoding
+ // (see comments in InternalNano.java for gory details.). We would
+ // like to do this once into a static field and re-use that from
+ // then on.
+ if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ !descriptor->default_value_string().empty() &&
+ !params.use_reference_types_for_primitives()) {
+ if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
+ (*variables)["default"] = DefaultValue(params, descriptor);
+ (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
+ (*variables)["default_constant_value"] = strings::Substitute(
+ "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
+ CEscape(descriptor->default_value_string()));
+ (*variables)["default_copy_if_needed"] =
+ (*variables)["default"] + ".clone()";
+ } else if (AllAscii(descriptor->default_value_string())) {
+ // All chars are ASCII. In this case directly referencing a
+ // CEscape()'d string literal works fine.
+ (*variables)["default"] =
+ "\"" + CEscape(descriptor->default_value_string()) + "\"";
+ (*variables)["default_copy_if_needed"] = (*variables)["default"];
+ } else {
+ // Strings where some chars are non-ASCII. We need to save the
+ // default value.
+ (*variables)["default"] = DefaultValue(params, descriptor);
+ (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
+ (*variables)["default_constant_value"] = strings::Substitute(
+ "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
+ CEscape(descriptor->default_value_string()));
+ (*variables)["default_copy_if_needed"] = (*variables)["default"];
+ }
+ } else {
+ // Non-string, non-bytes field. Defaults are literals.
+ (*variables)["default"] = DefaultValue(params, descriptor);
+ (*variables)["default_copy_if_needed"] = (*variables)["default"];
+ }
+ (*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()));
+ (*variables)["non_packed_tag"] = SimpleItoa(
+ internal::WireFormatLite::MakeTag(descriptor->number(),
+ internal::WireFormat::WireTypeForFieldType(descriptor->type())));
+ int fixed_size = FixedSize(descriptor->type());
+ if (fixed_size != -1) {
+ (*variables)["fixed_size"] = SimpleItoa(fixed_size);
+ }
+ (*variables)["message_name"] = descriptor->containing_type()->name();
+ (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor);
+}
+} // namespace
+
+// ===================================================================
+
+PrimitiveFieldGenerator::
+PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetPrimitiveVariables(descriptor, params, &variables_);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
+ return variables_.find("default_constant") != variables_.end();
+}
+
+void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
+ if (variables_.find("default_constant") != variables_.end()) {
+ printer->Print(variables_,
+ "$default_constant$ = $default_constant_value$;\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer, bool lazy_init) const {
+ if (variables_.find("default_constant") != variables_.end()) {
+ // Those primitive types that need a saved default.
+ if (lazy_init) {
+ printer->Print(variables_,
+ "private static $type$ $default_constant$;\n");
+ } else {
+ printer->Print(variables_,
+ "private static final $type$ $default_constant$ =\n"
+ " $default_constant_value$;\n");
+ }
+ }
+
+ printer->Print(variables_,
+ "public $type$ $name$;\n");
+
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "public boolean has$capitalized_name$;\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = $default_copy_if_needed$;\n");
+
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "has$capitalized_name$ = false;\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "this.$name$ = input.read$capitalized_type$();\n");
+
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "has$capitalized_name$ = true;\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializationConditional(io::Printer* printer) const {
+ if (params_.use_reference_types_for_primitives()) {
+ // For reference type mode, serialize based on equality
+ // to null.
+ printer->Print(variables_,
+ "if (this.$name$ != null) {\n");
+ return;
+ }
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "if (has$capitalized_name$ || ");
+ } else {
+ printer->Print(variables_,
+ "if (");
+ }
+ JavaType java_type = GetJavaType(descriptor_);
+ if (IsArrayType(java_type)) {
+ printer->Print(variables_,
+ "!java.util.Arrays.equals(this.$name$, $default$)) {\n");
+ } else if (IsReferenceType(java_type)) {
+ printer->Print(variables_,
+ "!this.$name$.equals($default$)) {\n");
+ } else if (java_type == JAVATYPE_FLOAT) {
+ printer->Print(variables_,
+ "java.lang.Float.floatToIntBits(this.$name$)\n"
+ " != java.lang.Float.floatToIntBits($default$)) {\n");
+ } else if (java_type == JAVATYPE_DOUBLE) {
+ printer->Print(variables_,
+ "java.lang.Double.doubleToLongBits(this.$name$)\n"
+ " != java.lang.Double.doubleToLongBits($default$)) {\n");
+ } else {
+ printer->Print(variables_,
+ "this.$name$ != $default$) {\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->is_required() && !params_.generate_has()) {
+ // Always serialize a required field if we don't have the 'has' signal.
+ printer->Print(variables_,
+ "output.write$capitalized_type$($number$, this.$name$);\n");
+ } else {
+ GenerateSerializationConditional(printer);
+ printer->Print(variables_,
+ " output.write$capitalized_type$($number$, this.$name$);\n"
+ "}\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ if (descriptor_->is_required() && !params_.generate_has()) {
+ printer->Print(variables_,
+ "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$Size($number$, this.$name$);\n");
+ } else {
+ GenerateSerializationConditional(printer);
+ printer->Print(variables_,
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$Size($number$, this.$name$);\n"
+ "}\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ // We define equality as serialized form equality. If generate_has(),
+ // then if the field value equals the default value in both messages,
+ // but one's 'has' field is set and the other's is not, the serialized
+ // forms are different and we should return false.
+ JavaType java_type = GetJavaType(descriptor_);
+ if (java_type == JAVATYPE_BYTES) {
+ printer->Print(variables_,
+ "if (!java.util.Arrays.equals(this.$name$, other.$name$)");
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "\n"
+ " || (java.util.Arrays.equals(this.$name$, $default$)\n"
+ " && this.has$capitalized_name$ != other.has$capitalized_name$)");
+ }
+ printer->Print(") {\n"
+ " return false;\n"
+ "}\n");
+ } else if (java_type == JAVATYPE_STRING
+ || params_.use_reference_types_for_primitives()) {
+ printer->Print(variables_,
+ "if (this.$name$ == null) {\n"
+ " if (other.$name$ != null) {\n"
+ " return false;\n"
+ " }\n"
+ "} else if (!this.$name$.equals(other.$name$)");
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "\n"
+ " || (this.$name$.equals($default$)\n"
+ " && this.has$capitalized_name$ != other.has$capitalized_name$)");
+ }
+ printer->Print(") {\n"
+ " return false;\n"
+ "}\n");
+ } else if (java_type == JAVATYPE_FLOAT) {
+ printer->Print(variables_,
+ "{\n"
+ " int bits = java.lang.Float.floatToIntBits(this.$name$);\n"
+ " if (bits != java.lang.Float.floatToIntBits(other.$name$)");
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "\n"
+ " || (bits == java.lang.Float.floatToIntBits($default$)\n"
+ " && this.has$capitalized_name$ != other.has$capitalized_name$)");
+ }
+ printer->Print(") {\n"
+ " return false;\n"
+ " }\n"
+ "}\n");
+ } else if (java_type == JAVATYPE_DOUBLE) {
+ printer->Print(variables_,
+ "{\n"
+ " long bits = java.lang.Double.doubleToLongBits(this.$name$);\n"
+ " if (bits != java.lang.Double.doubleToLongBits(other.$name$)");
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "\n"
+ " || (bits == java.lang.Double.doubleToLongBits($default$)\n"
+ " && this.has$capitalized_name$ != other.has$capitalized_name$)");
+ }
+ printer->Print(") {\n"
+ " return false;\n"
+ " }\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (this.$name$ != other.$name$");
+ if (params_.generate_has()) {
+ printer->Print(variables_,
+ "\n"
+ " || (this.$name$ == $default$\n"
+ " && this.has$capitalized_name$ != other.has$capitalized_name$)");
+ }
+ printer->Print(") {\n"
+ " return false;\n"
+ "}\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ JavaType java_type = GetJavaType(descriptor_);
+ if (java_type == JAVATYPE_BYTES) {
+ printer->Print(variables_,
+ "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n");
+ } else if (java_type == JAVATYPE_STRING
+ || params_.use_reference_types_for_primitives()) {
+ printer->Print(variables_,
+ "result = 31 * result\n"
+ " + (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
+ } else {
+ switch (java_type) {
+ // For all Java primitive types below, the hash codes match the
+ // results of BoxedType.valueOf(primitiveValue).hashCode().
+ case JAVATYPE_INT:
+ printer->Print(variables_,
+ "result = 31 * result + this.$name$;\n");
+ break;
+ case JAVATYPE_LONG:
+ printer->Print(variables_,
+ "result = 31 * result\n"
+ " + (int) (this.$name$ ^ (this.$name$ >>> 32));\n");
+ break;
+ case JAVATYPE_FLOAT:
+ printer->Print(variables_,
+ "result = 31 * result\n"
+ " + java.lang.Float.floatToIntBits(this.$name$);\n");
+ break;
+ case JAVATYPE_DOUBLE:
+ printer->Print(variables_,
+ "{\n"
+ " long v = java.lang.Double.doubleToLongBits(this.$name$);\n"
+ " result = 31 * result + (int) (v ^ (v >>> 32));\n"
+ "}\n");
+ break;
+ case JAVATYPE_BOOLEAN:
+ printer->Print(variables_,
+ "result = 31 * result + (this.$name$ ? 1231 : 1237);\n");
+ break;
+ default:
+ GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
+ break;
+ }
+ }
+}
+
+// ===================================================================
+
+AccessorPrimitiveFieldGenerator::
+AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params, int has_bit_index)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetPrimitiveVariables(descriptor, params, &variables_);
+ SetBitOperationVariables("has", has_bit_index, &variables_);
+}
+
+AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
+
+bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
+ return variables_.find("default_constant") != variables_.end();
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateInitSavedDefaultCode(io::Printer* printer) const {
+ if (variables_.find("default_constant") != variables_.end()) {
+ printer->Print(variables_,
+ "$default_constant$ = $default_constant_value$;\n");
+ }
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer, bool lazy_init) const {
+ if (variables_.find("default_constant") != variables_.end()) {
+ // Those primitive types that need a saved default.
+ if (lazy_init) {
+ printer->Print(variables_,
+ "private static $type$ $default_constant$;\n");
+ } else {
+ printer->Print(variables_,
+ "private static final $type$ $default_constant$ =\n"
+ " $default_constant_value$;\n");
+ }
+ }
+ printer->Print(variables_,
+ "private $type$ $name$_;\n"
+ "public $type$ get$capitalized_name$() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$($type$ value) {\n");
+ if (IsReferenceType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ " if (value == null) {\n"
+ " throw new java.lang.NullPointerException();\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " $name$_ = value;\n"
+ " $set_has$;\n"
+ " return this;\n"
+ "}\n"
+ "public boolean has$capitalized_name$() {\n"
+ " return $get_has$;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_ = $default_copy_if_needed$;\n"
+ " $clear_has$;\n"
+ " return this;\n"
+ "}\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_ = $default_copy_if_needed$;\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_ = input.read$capitalized_type$();\n"
+ "$set_has$;\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_has$) {\n"
+ " output.write$capitalized_type$($number$, $name$_);\n"
+ "}\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_has$) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$Size($number$, $name$_);\n"
+ "}\n");
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ switch (GetJavaType(descriptor_)) {
+ // For all Java primitive types below, the equality checks match the
+ // results of BoxedType.valueOf(primitiveValue).equals(otherValue).
+ case JAVATYPE_FLOAT:
+ printer->Print(variables_,
+ "if ($different_has$\n"
+ " || java.lang.Float.floatToIntBits($name$_)\n"
+ " != java.lang.Float.floatToIntBits(other.$name$_)) {\n"
+ " return false;\n"
+ "}\n");
+ break;
+ case JAVATYPE_DOUBLE:
+ printer->Print(variables_,
+ "if ($different_has$\n"
+ " || java.lang.Double.doubleToLongBits($name$_)\n"
+ " != java.lang.Double.doubleToLongBits(other.$name$_)) {\n"
+ " return false;\n"
+ "}\n");
+ break;
+ case JAVATYPE_INT:
+ case JAVATYPE_LONG:
+ case JAVATYPE_BOOLEAN:
+ printer->Print(variables_,
+ "if ($different_has$\n"
+ " || $name$_ != other.$name$_) {\n"
+ " return false;\n"
+ "}\n");
+ break;
+ case JAVATYPE_STRING:
+ // Accessor style would guarantee $name$_ non-null
+ printer->Print(variables_,
+ "if ($different_has$\n"
+ " || !$name$_.equals(other.$name$_)) {\n"
+ " return false;\n"
+ "}\n");
+ break;
+ case JAVATYPE_BYTES:
+ // Accessor style would guarantee $name$_ non-null
+ printer->Print(variables_,
+ "if ($different_has$\n"
+ " || !java.util.Arrays.equals($name$_, other.$name$_)) {\n"
+ " return false;\n"
+ "}\n");
+ break;
+ default:
+ GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
+ break;
+ }
+}
+
+void AccessorPrimitiveFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ switch (GetJavaType(descriptor_)) {
+ // For all Java primitive types below, the hash codes match the
+ // results of BoxedType.valueOf(primitiveValue).hashCode().
+ case JAVATYPE_INT:
+ printer->Print(variables_,
+ "result = 31 * result + $name$_;\n");
+ break;
+ case JAVATYPE_LONG:
+ printer->Print(variables_,
+ "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n");
+ break;
+ case JAVATYPE_FLOAT:
+ printer->Print(variables_,
+ "result = 31 * result +\n"
+ " java.lang.Float.floatToIntBits($name$_);\n");
+ break;
+ case JAVATYPE_DOUBLE:
+ printer->Print(variables_,
+ "{\n"
+ " long v = java.lang.Double.doubleToLongBits($name$_);\n"
+ " result = 31 * result + (int) (v ^ (v >>> 32));\n"
+ "}\n");
+ break;
+ case JAVATYPE_BOOLEAN:
+ printer->Print(variables_,
+ "result = 31 * result + ($name$_ ? 1231 : 1237);\n");
+ break;
+ case JAVATYPE_STRING:
+ // Accessor style would guarantee $name$_ non-null
+ printer->Print(variables_,
+ "result = 31 * result + $name$_.hashCode();\n");
+ break;
+ case JAVATYPE_BYTES:
+ // Accessor style would guarantee $name$_ non-null
+ printer->Print(variables_,
+ "result = 31 * result + java.util.Arrays.hashCode($name$_);\n");
+ break;
+ default:
+ GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
+ break;
+ }
+}
+
+// ===================================================================
+
+RepeatedPrimitiveFieldGenerator::
+RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetPrimitiveVariables(descriptor, params, &variables_);
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
+ printer->Print(variables_,
+ "public $type$[] $name$;\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = $default$;\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ // First, figure out the length of the array, then parse.
+ printer->Print(variables_,
+ "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
+ " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
+ "int i = this.$name$ == null ? 0 : this.$name$.length;\n");
+
+ if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
+ printer->Print(variables_,
+ "byte[][] newArray = new byte[i + arrayLength][];\n");
+ } else {
+ printer->Print(variables_,
+ "$type$[] newArray = new $type$[i + arrayLength];\n");
+ }
+ printer->Print(variables_,
+ "if (i != 0) {\n"
+ " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+ "}\n"
+ "for (; i < newArray.length - 1; i++) {\n"
+ " newArray[i] = input.read$capitalized_type$();\n"
+ " input.readTag();\n"
+ "}\n"
+ "// Last one without readTag.\n"
+ "newArray[i] = input.read$capitalized_type$();\n"
+ "this.$name$ = newArray;\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergingCodeFromPacked(io::Printer* printer) const {
+ printer->Print(
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n");
+
+ // If we know the elements will all be of the same size, the arrayLength
+ // can be calculated much more easily. However, FixedSize() returns 1 for
+ // repeated bool fields, which are guaranteed to have the fixed size of
+ // 1 byte per value only if we control the output. On the wire they can
+ // legally appear as variable-size integers, so we need to use the slow
+ // way for repeated bool fields.
+ if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
+ || FixedSize(descriptor_->type()) == -1) {
+ printer->Print(variables_,
+ "// First pass to compute array length.\n"
+ "int arrayLength = 0;\n"
+ "int startPos = input.getPosition();\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " input.read$capitalized_type$();\n"
+ " arrayLength++;\n"
+ "}\n"
+ "input.rewindToPosition(startPos);\n");
+ } else {
+ printer->Print(variables_,
+ "int arrayLength = length / $fixed_size$;\n");
+ }
+
+ printer->Print(variables_,
+ "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
+ "$type$[] newArray = new $type$[i + arrayLength];\n"
+ "if (i != 0) {\n"
+ " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
+ "}\n"
+ "for (; i < newArray.length; i++) {\n"
+ " newArray[i] = input.read$capitalized_type$();\n"
+ "}\n"
+ "this.$name$ = newArray;\n"
+ "input.popLimit(limit);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateRepeatedDataSizeCode(io::Printer* printer) const {
+ // Creates a variable dataSize and puts the serialized size in there.
+ // If the element type is a Java reference type, also generates
+ // dataCount which stores the number of non-null elements in the field.
+ if (IsReferenceType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "int dataCount = 0;\n"
+ "int dataSize = 0;\n"
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " $type$ element = this.$name$[i];\n"
+ " if (element != null) {\n"
+ " dataCount++;\n"
+ " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$SizeNoTag(element);\n"
+ " }\n"
+ "}\n");
+ } else if (FixedSize(descriptor_->type()) == -1) {
+ printer->Print(variables_,
+ "int dataSize = 0;\n"
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " $type$ element = this.$name$[i];\n"
+ " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$SizeNoTag(element);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "int dataSize = $fixed_size$ * this.$name$.length;\n");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n");
+ printer->Indent();
+
+ if (descriptor_->is_packable() && descriptor_->options().packed()) {
+ GenerateRepeatedDataSizeCode(printer);
+ printer->Print(variables_,
+ "output.writeRawVarint32($tag$);\n"
+ "output.writeRawVarint32(dataSize);\n"
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " output.write$capitalized_type$NoTag(this.$name$[i]);\n"
+ "}\n");
+ } else if (IsReferenceType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " $type$ element = this.$name$[i];\n"
+ " if (element != null) {\n"
+ " output.write$capitalized_type$($number$, element);\n"
+ " }\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " output.write$capitalized_type$($number$, this.$name$[i]);\n"
+ "}\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n");
+ printer->Indent();
+
+ GenerateRepeatedDataSizeCode(printer);
+
+ printer->Print(
+ "size += dataSize;\n");
+ if (descriptor_->is_packable() && descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "size += $tag_size$;\n"
+ "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeRawVarint32Size(dataSize);\n");
+ } else if (IsReferenceType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "size += $tag_size$ * dataCount;\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * this.$name$.length;\n");
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+ " this.$name$, other.$name$)) {\n"
+ " return false;\n"
+ "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = 31 * result\n"
+ " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
new file mode 100644
index 00000000..c04a19b7
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
@@ -0,0 +1,126 @@
+// 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_JAVANANO_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class PrimitiveFieldGenerator : public FieldGenerator {
+ public:
+ explicit PrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Params &params);
+ ~PrimitiveFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ bool SavedDefaultNeeded() const;
+ void GenerateInitSavedDefaultCode(io::Printer* printer) const;
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ void GenerateSerializationConditional(io::Printer* printer) const;
+
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class AccessorPrimitiveFieldGenerator : public FieldGenerator {
+ public:
+ explicit AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Params &params, int has_bit_index);
+ ~AccessorPrimitiveFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ bool SavedDefaultNeeded() const;
+ void GenerateInitSavedDefaultCode(io::Printer* printer) const;
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator);
+};
+
+class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
+ public:
+ explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ ~RepeatedPrimitiveFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateMergingCodeFromPacked(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
+
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__