aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax Cai <maxtroy@google.com>2013-09-20 18:29:40 +0100
committerMax Cai <maxtroy@google.com>2013-09-23 15:27:13 +0100
commite74fe623e115237968a3de1143d7cdb4df710858 (patch)
treec4413272f7a158a97d3a88915d544aa57ee51578 /src
parent47dee56155c7bdb9855e51ff08c99db306d11a2d (diff)
downloadexternal_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')
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.cc86
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.h28
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.cc26
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.h8
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.cc7
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.h5
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.cc45
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.cc95
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.h28
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.cc109
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.h28
-rw-r--r--src/google/protobuf/unittest_accessors_nano.proto116
12 files changed, 525 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 &params) {
+FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
+ const Params &params, 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 &params);
+ static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+ const Params &params, 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 &params, 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;
diff --git a/src/google/protobuf/unittest_accessors_nano.proto b/src/google/protobuf/unittest_accessors_nano.proto
new file mode 100644
index 0000000..875af25
--- /dev/null
+++ b/src/google/protobuf/unittest_accessors_nano.proto
@@ -0,0 +1,116 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: maxtroy@google.com (Max Cai)
+
+package protobuf_unittest;
+
+option java_package = "com.google.protobuf.nano";
+option java_outer_classname = "NanoAccessorsOuterClass";
+
+message TestNanoAccessors {
+
+ message NestedMessage {
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ }
+
+ // Singular
+ optional int32 optional_int32 = 1;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+
+ optional NestedMessage optional_nested_message = 18;
+
+ optional NestedEnum optional_nested_enum = 21;
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated NestedMessage repeated_nested_message = 48;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+
+ // Singular with defaults
+ optional int32 default_int32 = 61 [default = 41 ];
+ optional string default_string = 74 [default = "hello"];
+ optional bytes default_bytes = 75 [default = "world"];
+
+ optional float default_float_nan = 99 [default = nan];
+
+ optional NestedEnum default_nested_enum = 81 [default = BAR];
+
+ // Required
+ required int32 id = 86;
+
+ // Add enough optional fields to make 2 bit fields in total
+ optional int32 filler100 = 100;
+ optional int32 filler101 = 101;
+ optional int32 filler102 = 102;
+ optional int32 filler103 = 103;
+ optional int32 filler104 = 104;
+ optional int32 filler105 = 105;
+ optional int32 filler106 = 106;
+ optional int32 filler107 = 107;
+ optional int32 filler108 = 108;
+ optional int32 filler109 = 109;
+ optional int32 filler110 = 110;
+ optional int32 filler111 = 111;
+ optional int32 filler112 = 112;
+ optional int32 filler113 = 113;
+ optional int32 filler114 = 114;
+ optional int32 filler115 = 115;
+ optional int32 filler116 = 116;
+ optional int32 filler117 = 117;
+ optional int32 filler118 = 118;
+ optional int32 filler119 = 119;
+ optional int32 filler120 = 120;
+ optional int32 filler121 = 121;
+ optional int32 filler122 = 122;
+ optional int32 filler123 = 123;
+ optional int32 filler124 = 124;
+ optional int32 filler125 = 125;
+ optional int32 filler126 = 126;
+ optional int32 filler127 = 127;
+ optional int32 filler128 = 128;
+ optional int32 filler129 = 129;
+ optional int32 filler130 = 130;
+
+ optional int32 before_bit_field_check = 139;
+ optional int32 bit_field_check = 140;
+ optional int32 after_bit_field_check = 141;
+}