From ccc48faf20dbf3b3cddcffe78d198876d543529b Mon Sep 17 00:00:00 2001 From: Brian Duff Date: Tue, 15 Oct 2013 18:35:44 -0700 Subject: Implement hashCode() and equals() behind a generator option. The option is only called 'generate_equals' because: - equals() is the main thing; hashCode() is there only to complement equals(); - it's shorter; - toString() should not be included in this option because it's more for debugging and it's more likely to stop ProGuard from working well. Also shortened the "has bit" expression; was ((bitField & mask) == mask), now ((bitField & mask) != 0). Both the Java code and the bytecode are slightly shorter. Change-Id: Ic309a08a60883bf454eb6612679aa99611620e76 --- .../protobuf/compiler/javanano/javanano_message.cc | 84 +++++++++++++++++++++- 1 file changed, 81 insertions(+), 3 deletions(-) (limited to 'src/google/protobuf/compiler/javanano/javanano_message.cc') diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index c55ca55..63f8955 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -198,6 +198,11 @@ void MessageGenerator::Generate(io::Printer* printer) { GenerateClear(printer); + if (params_.generate_equals()) { + GenerateEquals(printer); + GenerateHashCode(printer); + } + // If we have an extension range, generate accessors for extensions. if (params_.store_unknown_fields() && descriptor_->extension_range_count() > 0) { @@ -326,11 +331,11 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) { if (params_.store_unknown_fields()) { printer->Print( "if (unknownFieldData == null) {\n" - " unknownFieldData = \n" + " unknownFieldData =\n" " new java.util.ArrayList();\n" "}\n" - "if (!com.google.protobuf.nano.WireFormatNano.storeUnknownField(unknownFieldData, \n" - " input, tag)) {\n" + "if (!com.google.protobuf.nano.WireFormatNano.storeUnknownField(\n" + " unknownFieldData, input, tag)) {\n" " return this;\n" "}\n"); } else { @@ -427,6 +432,79 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { "}\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( + "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n" + " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();" + "} else {\n" + " return unknownFieldData.equals(other.unknownFieldData);\n" + "}\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"); + 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 + (unknownFieldData == null || unknownFieldData.isEmpty()\n" + " ? 0 : unknownFieldData.hashCode());\n"); + } + + printer->Print("return result;\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + // =================================================================== } // namespace javanano -- cgit v1.1