diff options
author | Max Cai <maxtroy@google.com> | 2013-09-20 18:29:40 +0100 |
---|---|---|
committer | Max Cai <maxtroy@google.com> | 2013-09-23 15:27:13 +0100 |
commit | e74fe623e115237968a3de1143d7cdb4df710858 (patch) | |
tree | c4413272f7a158a97d3a88915d544aa57ee51578 /src/google/protobuf/compiler/javanano | |
parent | 47dee56155c7bdb9855e51ff08c99db306d11a2d (diff) | |
download | external_protobuf-e74fe623e115237968a3de1143d7cdb4df710858.zip external_protobuf-e74fe623e115237968a3de1143d7cdb4df710858.tar.gz external_protobuf-e74fe623e115237968a3de1143d7cdb4df710858.tar.bz2 |
Accessor style for optional fields.
This CL implements the 'optional_field_style=accessors' option.
All optional fields will now be 1 Java field and 1 bit in a shared
bitfield behind get/set/has/clear accessor methods. The setter
performs null check for reference types (Strings and byte[]s).
Also decentralized the clear code generation.
Change-Id: I60ac78329e352e76c2f8139fba1f292383080ad3
Diffstat (limited to 'src/google/protobuf/compiler/javanano')
11 files changed, 409 insertions, 56 deletions
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc index 9c4acb9..b30b9fb 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc @@ -90,7 +90,18 @@ GenerateMembers(io::Printer* printer) const { } void EnumFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +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_, " this.$name$ = input.readInt32();\n"); @@ -146,6 +157,71 @@ string EnumFieldGenerator::GetBoxedType() const { // =================================================================== +AccessorEnumFieldGenerator:: +AccessorEnumFieldGenerator(const FieldDescriptor* descriptor, + const Params& params, int has_bit_index) + : FieldGenerator(params), descriptor_(descriptor) { + SetEnumVariables(params, descriptor, &variables_); + SetBitOperationVariables("has", has_bit_index, &variables_); +} + +AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} + +void AccessorEnumFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private int $name$_ = $default$;\n" + "public int get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n" + "public void set$capitalized_name$(int value) {\n" + " $name$_ = value;\n" + " $set_has$;\n" + "}\n" + "public boolean has$capitalized_name$() {\n" + " return $get_has$;\n" + "}\n" + "public void clear$capitalized_name$() {\n" + " $name$_ = $default$;\n" + " $clear_has$;\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_, + "set$capitalized_name$(input.readInt32());\n"); +} + +void AccessorEnumFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " output.writeInt32($number$, $name$_);\n" + "}\n"); +} + +void AccessorEnumFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" + " .computeInt32Size($number$, $name$_);\n" + "}\n"); +} + +string AccessorEnumFieldGenerator::GetBoxedType() const { + return ClassName(params_, descriptor_->enum_type()); +} + +// =================================================================== + RepeatedEnumFieldGenerator:: RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) : FieldGenerator(params), descriptor_(descriptor) { @@ -165,7 +241,13 @@ GenerateMembers(io::Printer* printer) const { } void RepeatedEnumFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +GenerateClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$ = com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY;\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { // First, figure out the length of the array, then parse. if (descriptor_->options().packed()) { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h index 6e1a443..934aaaa 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h @@ -51,7 +51,8 @@ class EnumFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) 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; @@ -64,6 +65,28 @@ class EnumFieldGenerator : public FieldGenerator { 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) 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; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map<string, string> variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorEnumFieldGenerator); +}; + class RepeatedEnumFieldGenerator : public FieldGenerator { public: explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params); @@ -71,7 +94,8 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) 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; diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc index ea25786..6629f96 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_field.cc @@ -53,16 +53,21 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Params extension_generators_( new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) { + int next_has_bit_index = 0; // Construct all the FieldGenerators. for (int i = 0; i < descriptor->field_count(); i++) { - field_generators_[i].reset(MakeGenerator(descriptor->field(i), params)); + field_generators_[i].reset( + MakeGenerator(descriptor->field(i), params, &next_has_bit_index)); } for (int i = 0; i < descriptor->extension_count(); i++) { - extension_generators_[i].reset(MakeGenerator(descriptor->extension(i), params)); + extension_generators_[i].reset( + MakeGenerator(descriptor->extension(i), params, &next_has_bit_index)); } + total_bits_ = next_has_bit_index; } -FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, const Params ¶ms) { +FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, + const Params ¶ms, int* next_has_bit_index) { if (field->is_repeated()) { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: @@ -72,6 +77,21 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, c default: return new RepeatedPrimitiveFieldGenerator(field, params); } + } else if (params.optional_field_accessors() && field->is_optional()) { + // 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 (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + return new AccessorMessageFieldGenerator(field, params); + case JAVATYPE_ENUM: + return new AccessorEnumFieldGenerator( + field, params, (*next_has_bit_index)++); + default: + return new AccessorPrimitiveFieldGenerator( + field, params, (*next_has_bit_index)++); + } } else { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h index 7db48a5..dad2e7a 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_field.h @@ -58,7 +58,8 @@ class FieldGenerator { virtual ~FieldGenerator(); virtual void GenerateMembers(io::Printer* printer) const = 0; - virtual void GenerateParsingCode(io::Printer* printer) const = 0; + virtual void GenerateClearCode(io::Printer* printer) const = 0; + virtual void GenerateMergingCode(io::Printer* printer) const = 0; virtual void GenerateSerializationCode(io::Printer* printer) const = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; @@ -78,13 +79,16 @@ class FieldGeneratorMap { const FieldGenerator& get(const FieldDescriptor* field) const; const FieldGenerator& get_extension(int index) const; + int total_bits() const { return total_bits_; } private: const Descriptor* descriptor_; scoped_array<scoped_ptr<FieldGenerator> > field_generators_; scoped_array<scoped_ptr<FieldGenerator> > extension_generators_; + int total_bits_; - static FieldGenerator* MakeGenerator(const FieldDescriptor* field, const Params ¶ms); + static FieldGenerator* MakeGenerator(const FieldDescriptor* field, + const Params ¶ms, int* next_has_bit_index); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index ebc9c63..630ecd1 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -484,6 +484,13 @@ string GenerateClearBit(int bit_index) { 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); +} + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h index 03fd434..cddc077 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.h +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h @@ -163,6 +163,11 @@ string GenerateSetBit(int bit_index); // Example: "bitField1_ = (bitField1_ & ~0x04)" string GenerateClearBit(int bit_index); +// Sets the 'get_*', 'set_*' and 'clear_*' variables, where * is the given bit +// field name, 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 diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 851c443..c9ea654 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -137,9 +137,9 @@ void MessageGenerator::Generate(io::Printer* printer) { // warnings here in the class declaration. printer->Print( "@SuppressWarnings(\"hiding\")\n" - "public $modifiers$ final class $classname$ extends\n" + "public $modifiers$final class $classname$ extends\n" " com.google.protobuf.nano.MessageNano {\n", - "modifiers", is_own_file ? "" : "static", + "modifiers", is_own_file ? "" : "static ", "classname", descriptor_->name()); printer->Indent(); printer->Print( @@ -167,6 +167,13 @@ void MessageGenerator::Generate(io::Printer* printer) { MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); } + // Integers for bit fields + int totalInts = (field_generators_.total_bits() + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + // Fields for (int i = 0; i < descriptor_->field_count(); i++) { PrintFieldComment(printer, descriptor_->field(i)); @@ -327,7 +334,7 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) { "tag", SimpleItoa(tag)); printer->Indent(); - field_generators_.get(field).GenerateParsingCode(printer); + field_generators_.get(field).GenerateMergingCode(printer); printer->Outdent(); printer->Print( @@ -376,33 +383,17 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { "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); - - if (field->type() == FieldDescriptor::TYPE_BYTES && - !field->default_value_string().empty()) { - // Need to clone the default value because it is of a mutable - // type. - printer->Print( - "$name$ = $default$.clone();\n", - "name", RenameJavaKeywords(UnderscoresToCamelCase(field)), - "default", DefaultValue(params_, field)); - } else { - printer->Print( - "$name$ = $default$;\n", - "name", RenameJavaKeywords(UnderscoresToCamelCase(field)), - "default", DefaultValue(params_, field)); - } - - if (params_.generate_has() && - field->label() != FieldDescriptor::LABEL_REPEATED && - field->type() != FieldDescriptor::TYPE_GROUP && - field->type() != FieldDescriptor::TYPE_MESSAGE) { - printer->Print( - "has$capitalized_name$ = false;\n", - "capitalized_name", UnderscoresToCapitalizedCamelCase(field)); - } + field_generators_.get(field).GenerateClearCode(printer); } // Clear unknown fields. diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index 7d9a281..02dbdb1 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -88,9 +88,17 @@ GenerateMembers(io::Printer* printer) const { } void MessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +GenerateClearCode(io::Printer* printer) const { printer->Print(variables_, - "this.$name$ = new $type$();\n"); + "$name$ = null;\n"); +} + +void MessageFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ == null) {\n" + " this.$name$ = new $type$();\n" + "}"); if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, @@ -124,6 +132,81 @@ string MessageFieldGenerator::GetBoxedType() const { // =================================================================== +AccessorMessageFieldGenerator:: +AccessorMessageFieldGenerator( + const FieldDescriptor* descriptor, const Params& params) + : FieldGenerator(params), descriptor_(descriptor) { + SetMessageVariables(params, descriptor, &variables_); +} + +AccessorMessageFieldGenerator::~AccessorMessageFieldGenerator() {} + +void AccessorMessageFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $type$ $name$_ = null;\n" + "public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n" + "public void set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new java.lang.NullPointerException();\n" + " }\n" + " $name$_ = value;\n" + "}\n" + "public boolean has$capitalized_name$() {\n" + " return $name$_ != null;\n" + "}\n" + "public void clear$capitalized_name$() {\n" + " $name$_ = null;\n" + "}\n"); +} + +void AccessorMessageFieldGenerator:: +GenerateClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = null;\n"); +} + +void AccessorMessageFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!has$capitalized_name$()) {\n" + " set$capitalized_name$(new $type$());\n" + "}"); + + if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "input.readGroup($name$_, $number$);\n"); + } else { + printer->Print(variables_, + "input.readMessage($name$_);\n"); + } +} + +void AccessorMessageFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " output.write$group_or_message$($number$, $name$_);\n" + "}\n"); +} + +void AccessorMessageFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" + " .compute$group_or_message$Size($number$, $name$_);\n" + "}\n"); +} + +string AccessorMessageFieldGenerator::GetBoxedType() const { + return ClassName(params_, descriptor_->message_type()); +} + +// =================================================================== + RepeatedMessageFieldGenerator:: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params) : FieldGenerator(params), descriptor_(descriptor) { @@ -139,7 +222,13 @@ GenerateMembers(io::Printer* printer) const { } void RepeatedMessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +GenerateClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$ = $type$.EMPTY_ARRAY;\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.getRepeatedFieldArrayLength(input, $tag$);\n" diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h index 943a832..9807513 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h @@ -51,7 +51,8 @@ class MessageFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) 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; @@ -64,6 +65,28 @@ class MessageFieldGenerator : public FieldGenerator { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; +class AccessorMessageFieldGenerator : public FieldGenerator { + public: + explicit AccessorMessageFieldGenerator( + const FieldDescriptor* descriptor, const Params& params); + ~AccessorMessageFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer) 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; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map<string, string> variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorMessageFieldGenerator); +}; + class RepeatedMessageFieldGenerator : public FieldGenerator { public: explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, @@ -72,7 +95,8 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) 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; diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index 79357e9..69664d3 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -260,6 +260,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param default_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 CEscape() works fine. @@ -269,8 +270,11 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")", CEscape(descriptor->default_value_string())); } + (*variables)["default_copy_if_needed"] = (*variables)["default"]; } (*variables)["default_constant_value"] = default_value; + } else { + (*variables)["default_copy_if_needed"] = (*variables)["default"]; } (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); @@ -280,7 +284,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param if (IsReferenceType(GetJavaType(descriptor))) { (*variables)["null_check"] = " if (value == null) {\n" - " throw new NullPointerException();\n" + " throw new java.lang.NullPointerException();\n" " }\n"; } else { (*variables)["null_check"] = ""; @@ -310,17 +314,9 @@ GenerateMembers(io::Printer* printer) const { // Those primitive types that need a saved default. printer->Print(variables_, "private static final $type$ $default_constant$ = $default_constant_value$;\n"); - if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) { - printer->Print(variables_, - "public $type$ $name$ = $default$.clone();\n"); - } else { - printer->Print(variables_, - "public $type$ $name$ = $default$;\n"); - } - } else { - printer->Print(variables_, - "public $type$ $name$ = $default$;\n"); } + printer->Print(variables_, + "public $type$ $name$ = $default_copy_if_needed$;\n"); if (params_.generate_has()) { printer->Print(variables_, @@ -329,7 +325,18 @@ GenerateMembers(io::Printer* printer) const { } void PrimitiveFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +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"); @@ -397,6 +404,76 @@ string PrimitiveFieldGenerator::GetBoxedType() const { // =================================================================== +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() {} + +void AccessorPrimitiveFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + if (variables_.find("default_constant_value") != variables_.end()) { + printer->Print(variables_, + "private static final $type$ $default_constant$ = $default_constant_value$;\n"); + } + printer->Print(variables_, + "private $type$ $name$_ = $default_copy_if_needed$;\n" + "public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n" + "public void set$capitalized_name$($type$ value) {\n" + "$null_check$" + " $name$_ = value;\n" + " $set_has$;\n" + "}\n" + "public boolean has$capitalized_name$() {\n" + " return $get_has$;\n" + "}\n" + "public void clear$capitalized_name$() {\n" + " $name$_ = $default_copy_if_needed$;\n" + " $clear_has$;\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_, + "set$capitalized_name$(input.read$capitalized_type$());\n"); +} + +void AccessorPrimitiveFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " output.write$capitalized_type$($number$, $name$_);\n" + "}\n"); +} + +void AccessorPrimitiveFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" + " .compute$capitalized_type$Size($number$, $name$_);\n" + "}\n"); +} + +string AccessorPrimitiveFieldGenerator::GetBoxedType() const { + return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); +} + +// =================================================================== + RepeatedPrimitiveFieldGenerator:: RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) : FieldGenerator(params), descriptor_(descriptor) { @@ -412,7 +489,13 @@ GenerateMembers(io::Printer* printer) const { } void RepeatedPrimitiveFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +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. if (descriptor_->options().packed()) { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h index a56082d..b42e2f3 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h @@ -51,7 +51,8 @@ class PrimitiveFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) 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; @@ -66,6 +67,28 @@ class PrimitiveFieldGenerator : public FieldGenerator { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; +class AccessorPrimitiveFieldGenerator : public FieldGenerator { + public: + explicit AccessorPrimitiveFieldGenerator( const FieldDescriptor* descriptor, + const Params ¶ms, int has_bit_index); + ~AccessorPrimitiveFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer) 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; + + string GetBoxedType() 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); @@ -73,7 +96,8 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) 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; |