Index: third_party/protobuf/src/google/protobuf/compiler/javanano/javanano_message.cc |
diff --git a/third_party/protobuf/src/google/protobuf/compiler/javanano/javanano_message.cc b/third_party/protobuf/src/google/protobuf/compiler/javanano/javanano_message.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a41da5ae3301e1da57453a5f98f3d043fb1c4f38 |
--- /dev/null |
+++ b/third_party/protobuf/src/google/protobuf/compiler/javanano/javanano_message.cc |
@@ -0,0 +1,676 @@ |
+// 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? |
+ if (IsMapEntry(descriptor_->nested_type(i))) continue; |
+ 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? |
+ if (IsMapEntry(descriptor_->nested_type(i))) continue; |
+ 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$>", |
+ "classname", descriptor_->name()); |
+ } else if (params_.store_unknown_fields()) { |
+ printer->Print( |
+ " com.google.protobuf.nano.ExtendableMessageNano<$classname$>", |
+ "classname", descriptor_->name()); |
+ } else if (params_.parcelable_messages()) { |
+ printer->Print( |
+ " com.google.protobuf.nano.android.ParcelableMessageNano"); |
+ } else { |
+ printer->Print( |
+ " com.google.protobuf.nano.MessageNano"); |
+ } |
+ if (params_.generate_clone()) { |
+ printer->Print(" implements java.lang.Cloneable {\n"); |
+ } else { |
+ printer->Print(" {\n"); |
+ } |
+ printer->Indent(); |
+ |
+ if (params_.parcelable_messages()) { |
+ printer->Print( |
+ "\n" |
+ "// Used by Parcelable\n" |
+ "@SuppressWarnings({\"unused\"})\n" |
+ "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n" |
+ " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n" |
+ " $classname$>($classname$.class);\n", |
+ "classname", descriptor_->name()); |
+ } |
+ |
+ // 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++) { |
+ if (IsMapEntry(descriptor_->nested_type(i))) continue; |
+ MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); |
+ } |
+ |
+ // oneof |
+ map<string, string> vars; |
+ vars["message_name"] = descriptor_->name(); |
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
+ const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); |
+ vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc); |
+ vars["oneof_capitalized_name"] = |
+ UnderscoresToCapitalizedCamelCase(oneof_desc); |
+ vars["oneof_index"] = SimpleItoa(oneof_desc->index()); |
+ // Oneof Constants |
+ for (int j = 0; j < oneof_desc->field_count(); j++) { |
+ const FieldDescriptor* field = oneof_desc->field(j); |
+ vars["number"] = SimpleItoa(field->number()); |
+ vars["cap_field_name"] = ToUpper(field->name()); |
+ printer->Print(vars, |
+ "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n"); |
+ } |
+ // oneofCase_ and oneof_ |
+ printer->Print(vars, |
+ "private int $oneof_name$Case_ = 0;\n" |
+ "private java.lang.Object $oneof_name$_;\n"); |
+ printer->Print(vars, |
+ "public int get$oneof_capitalized_name$Case() {\n" |
+ " return this.$oneof_name$Case_;\n" |
+ "}\n"); |
+ // Oneof clear |
+ printer->Print(vars, |
+ "public $message_name$ clear$oneof_capitalized_name$() {\n" |
+ " this.$oneof_name$Case_ = 0;\n" |
+ " this.$oneof_name$_ = null;\n" |
+ " return this;\n" |
+ "}\n"); |
+ } |
+ |
+ // 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 { |
+ printer->Print( |
+ "\n" |
+ "public $classname$() {\n", |
+ "classname", descriptor_->name()); |
+ if (params_.generate_clear()) { |
+ printer->Print(" clear();\n"); |
+ } else { |
+ printer->Indent(); |
+ GenerateFieldInitializers(printer); |
+ printer->Outdent(); |
+ } |
+ printer->Print("}\n"); |
+ } |
+ |
+ // Other methods in this class |
+ |
+ GenerateClear(printer); |
+ |
+ if (params_.generate_clone()) { |
+ GenerateClone(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(); |
+ if (HasMapField(descriptor_)) { |
+ printer->Print( |
+ "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n" |
+ " com.google.protobuf.nano.MapFactories.getMapFactory();\n"); |
+ } |
+ |
+ 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(); |
+ |
+ GenerateFieldInitializers(printer); |
+ |
+ printer->Outdent(); |
+ printer->Print( |
+ " return this;\n" |
+ "}\n"); |
+} |
+ |
+void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) { |
+ // 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 oneofs. |
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
+ printer->Print( |
+ "clear$oneof_capitalized_name$();\n", |
+ "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase( |
+ descriptor_->oneof_decl(i))); |
+ } |
+ |
+ // Clear unknown fields. |
+ if (params_.store_unknown_fields()) { |
+ printer->Print("unknownFieldData = null;\n"); |
+ } |
+ printer->Print("cachedSize = -1;\n"); |
+} |
+ |
+void MessageGenerator::GenerateClone(io::Printer* printer) { |
+ printer->Print( |
+ "@Override\n" |
+ "public $classname$ clone() {\n", |
+ "classname", descriptor_->name()); |
+ printer->Indent(); |
+ |
+ printer->Print( |
+ "$classname$ cloned;\n" |
+ "try {\n" |
+ " cloned = ($classname$) super.clone();\n" |
+ "} catch (java.lang.CloneNotSupportedException e) {\n" |
+ " throw new java.lang.AssertionError(e);\n" |
+ "}\n", |
+ "classname", descriptor_->name()); |
+ |
+ for (int i = 0; i < descriptor_->field_count(); i++) { |
+ field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer); |
+ } |
+ |
+ printer->Outdent(); |
+ printer->Print( |
+ " return cloned;\n" |
+ "}\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()); |
+ |
+ // Checking oneof case before checking each oneof field. |
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { |
+ const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); |
+ printer->Print( |
+ "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n" |
+ " return false;\n" |
+ "}\n", |
+ "oneof_name", UnderscoresToCamelCase(oneof_desc)); |
+ } |
+ |
+ 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( |
+ "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n" |
+ " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n" |
+ "} else {\n" |
+ " return unknownFieldData.equals(other.unknownFieldData);\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 + \n" |
+ " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n" |
+ " unknownFieldData.hashCode());\n"); |
+ } |
+ |
+ printer->Print("return result;\n"); |
+ |
+ printer->Outdent(); |
+ printer->Print("}\n"); |
+} |
+ |
+// =================================================================== |
+ |
+} // namespace javanano |
+} // namespace compiler |
+} // namespace protobuf |
+} // namespace google |