aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/main/java/com/google/protobuf/nano/InternalNano.java12
-rw-r--r--java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java35
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.cc6
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.h12
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.cc39
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.h20
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.cc4
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.cc92
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.cc6
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.h7
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.cc94
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.h15
12 files changed, 248 insertions, 94 deletions
diff --git a/java/src/main/java/com/google/protobuf/nano/InternalNano.java b/java/src/main/java/com/google/protobuf/nano/InternalNano.java
index ce4a206..90ca11d 100644
--- a/java/src/main/java/com/google/protobuf/nano/InternalNano.java
+++ b/java/src/main/java/com/google/protobuf/nano/InternalNano.java
@@ -46,6 +46,18 @@ public final class InternalNano {
private InternalNano() {}
/**
+ * An object to provide synchronization when lazily initializing static fields
+ * of {@link MessageNano} subclasses.
+ * <p>
+ * To enable earlier versions of ProGuard to inline short methods from a
+ * generated MessageNano subclass to the call sites, that class must not have
+ * a class initializer, which will be created if there is any static variable
+ * initializers. To lazily initialize the static variables in a thread-safe
+ * manner, the initialization code will synchronize on this object.
+ */
+ public static final Object LAZY_INIT_LOCK = new Object();
+
+ /**
* Helper called by generated code to construct default values for string
* fields.
* <p>
diff --git a/java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java b/java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
index d135a51..c4e123c 100644
--- a/java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
+++ b/java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
@@ -62,7 +62,7 @@ public final class MessageNanoPrinter {
StringBuffer buf = new StringBuffer();
try {
- print(null, message.getClass(), message, new StringBuffer(), buf);
+ print(null, message, new StringBuffer(), buf);
} catch (IllegalAccessException e) {
return "Error printing proto: " + e.getMessage();
}
@@ -70,33 +70,32 @@ public final class MessageNanoPrinter {
}
/**
- * Function that will print the given message/class into the StringBuffer.
+ * Function that will print the given message/field into the StringBuffer.
* Meant to be called recursively.
*
* @param identifier the identifier to use, or {@code null} if this is the root message to
* print.
- * @param clazz the class of {@code message}.
- * @param message the value to print. May in fact be a primitive value or byte array and not a
+ * @param object the value to print. May in fact be a primitive value or byte array and not a
* message.
* @param indentBuf the indentation each line should begin with.
* @param buf the output buffer.
*/
- private static void print(String identifier, Class<?> clazz, Object message,
+ private static void print(String identifier, Object object,
StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException {
- if (message == null) {
+ if (object == null) {
// This can happen if...
// - we're about to print a message, String, or byte[], but it not present;
// - we're about to print a primitive, but "reftype" optional style is enabled, and
// the field is unset.
// In both cases the appropriate behavior is to output nothing.
- } else if (MessageNano.class.isAssignableFrom(clazz)) { // Nano proto message
+ } else if (object instanceof MessageNano) { // Nano proto message
int origIndentBufLength = indentBuf.length();
if (identifier != null) {
buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n");
indentBuf.append(INDENT);
}
- for (Field field : clazz.getFields()) {
+ for (Field field : object.getClass().getFields()) {
// Proto fields are public, non-static variables that do not begin or end with '_'
int modifiers = field.getModifiers();
String fieldName = field.getName();
@@ -106,24 +105,24 @@ public final class MessageNanoPrinter {
continue;
}
- Class <?> fieldType = field.getType();
- Object value = field.get(message);
+ Class<?> fieldType = field.getType();
+ Object value = field.get(object);
if (fieldType.isArray()) {
Class<?> arrayType = fieldType.getComponentType();
// bytes is special since it's not repeated, but is represented by an array
if (arrayType == byte.class) {
- print(fieldName, fieldType, value, indentBuf, buf);
+ print(fieldName, value, indentBuf, buf);
} else {
int len = value == null ? 0 : Array.getLength(value);
for (int i = 0; i < len; i++) {
Object elem = Array.get(value, i);
- print(fieldName, arrayType, elem, indentBuf, buf);
+ print(fieldName, elem, indentBuf, buf);
}
}
} else {
- print(fieldName, fieldType, value, indentBuf, buf);
+ print(fieldName, value, indentBuf, buf);
}
}
if (identifier != null) {
@@ -134,13 +133,13 @@ public final class MessageNanoPrinter {
// Non-null primitive value
identifier = deCamelCaseify(identifier);
buf.append(indentBuf).append(identifier).append(": ");
- if (message instanceof String) {
- String stringMessage = sanitizeString((String) message);
+ if (object instanceof String) {
+ String stringMessage = sanitizeString((String) object);
buf.append("\"").append(stringMessage).append("\"");
- } else if (message instanceof byte[]) {
- appendQuotedBytes((byte[]) message, buf);
+ } else if (object instanceof byte[]) {
+ appendQuotedBytes((byte[]) object, buf);
} else {
- buf.append(message);
+ buf.append(object);
}
buf.append("\n");
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
index 17f0e26..5d3511b 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
@@ -87,7 +87,7 @@ EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"public $type$ $name$;\n");
@@ -214,7 +214,7 @@ AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
void AccessorEnumFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"private int $name$_;\n"
"public int get$capitalized_name$() {\n"
@@ -291,7 +291,7 @@ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& para
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"public $type$[] $name$;\n");
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
index 9000d20..c477af2 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
@@ -46,11 +46,12 @@ namespace javanano {
class EnumFieldGenerator : public FieldGenerator {
public:
- explicit EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ explicit EnumFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
~EnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateMembers(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;
@@ -72,7 +73,7 @@ class AccessorEnumFieldGenerator : public FieldGenerator {
~AccessorEnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateMembers(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;
@@ -89,11 +90,12 @@ class AccessorEnumFieldGenerator : public FieldGenerator {
class RepeatedEnumFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ explicit RepeatedEnumFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
~RepeatedEnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateMembers(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 GenerateMergingCodeFromPacked(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 2581669..e3e4cef 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_field.cc
@@ -46,6 +46,19 @@ 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
@@ -56,24 +69,26 @@ void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
<< "called on field generator that does not support packing.";
}
-FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Params &params)
+// =============================================
+
+FieldGeneratorMap::FieldGeneratorMap(
+ const Descriptor* descriptor, const Params &params)
: descriptor_(descriptor),
field_generators_(
- new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
- extension_generators_(
- new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
+ 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++) {
- 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, &next_has_bit_index));
+ 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,
@@ -122,10 +137,6 @@ const FieldGenerator& FieldGeneratorMap::get(
return *field_generators_[field->index()];
}
-const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
- return *extension_generators_[index];
-}
-
} // namespace javanano
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
index 14b6489..61fc621 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_field.h
@@ -53,11 +53,23 @@ namespace javanano {
class FieldGenerator {
public:
- //FieldGenerator() {}
FieldGenerator(const Params& params) : params_(params) {}
virtual ~FieldGenerator();
- virtual void GenerateMembers(io::Printer* printer) const = 0;
+ 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;
@@ -84,14 +96,14 @@ class FieldGeneratorMap {
~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const;
- const FieldGenerator& get_extension(int index) 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_;
- scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
int total_bits_;
+ bool saved_defaults_needed_;
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
const Params &params, int* next_has_bit_index);
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
index 95ee670..b3bedcb 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -261,9 +261,7 @@ string FieldConstantName(const FieldDescriptor *field) {
}
string FieldDefaultConstantName(const FieldDescriptor *field) {
- string name = field->name() + "_DEFAULT";
- UpperString(&name);
- return name;
+ return "_" + RenameJavaKeywords(UnderscoresToCamelCase(field)) + "Default";
}
JavaType GetJavaType(FieldDescriptor::Type field_type) {
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
index f7ab62c..c09670a 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -155,14 +155,6 @@ void MessageGenerator::Generate(io::Printer* printer) {
" com.google.protobuf.nano.MessageNano {\n");
}
printer->Indent();
- printer->Print(
- "\n"
- "public static final $classname$[] EMPTY_ARRAY = {};\n"
- "\n"
- "public $classname$() {\n"
- " clear();\n"
- "}\n",
- "classname", descriptor_->name());
// Nested types and extensions
for (int i = 0; i < descriptor_->extension_count(); i++) {
@@ -177,6 +169,42 @@ void MessageGenerator::Generate(io::Printer* printer) {
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) {
@@ -187,13 +215,57 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
}
- // Fields
+ // 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);
+ 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"
+ " clear();\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "\n"
+ "public $classname$() {\n"
+ " clear();\n"
+ "}\n",
+ "classname", descriptor_->name());
}
+ // Other methods in this class
+
GenerateClear(printer);
if (params_.generate_equals()) {
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
index 74d3f85..a46081d 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -82,7 +82,7 @@ MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"public $type$ $name$;\n");
}
@@ -158,7 +158,7 @@ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& p
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
void RepeatedMessageFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"public $type$[] $name$;\n");
}
@@ -166,7 +166,7 @@ GenerateMembers(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
- "$name$ = $type$.EMPTY_ARRAY;\n");
+ "$name$ = $type$.emptyArray();\n");
}
void RepeatedMessageFieldGenerator::
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
index 55e2610..e94a37b 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h
@@ -46,11 +46,12 @@ namespace javanano {
class MessageFieldGenerator : public FieldGenerator {
public:
- explicit MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ explicit MessageFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
~MessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateMembers(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;
@@ -72,7 +73,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
~RepeatedMessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateMembers(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;
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
index c0717e6..3428f69 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -251,35 +251,41 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param
} else {
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
}
- (*variables)["default"] = DefaultValue(params, descriptor);
- (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
- // 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 "private static final" field and re-use that from
+ // 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()) {
- string default_value;
if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
- default_value = strings::Substitute(
+ (*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()";
+ (*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 {
- if (AllAscii(descriptor->default_value_string())) {
- // All chars are ASCII. In this case CEscape() works fine.
- default_value = "\"" + CEscape(descriptor->default_value_string()) + "\"";
- } else {
- default_value = strings::Substitute(
- "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
- CEscape(descriptor->default_value_string()));
- }
+ // 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"];
}
- (*variables)["default_constant_value"] = default_value;
} 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));
@@ -306,12 +312,29 @@ PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
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) const {
- if (variables_.find("default_constant_value") != variables_.end()) {
+GenerateMembers(io::Printer* printer, bool lazy_init) const {
+ if (variables_.find("default_constant") != variables_.end()) {
// Those primitive types that need a saved default.
- printer->Print(variables_,
- "private static final $type$ $default_constant$ = $default_constant_value$;\n");
+ 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_,
@@ -514,11 +537,30 @@ AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
+bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
+ return variables_.find("default_constant") != variables_.end();
+}
+
void AccessorPrimitiveFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
- if (variables_.find("default_constant_value") != variables_.end()) {
+GenerateInitSavedDefaultCode(io::Printer* printer) const {
+ if (variables_.find("default_constant") != variables_.end()) {
printer->Print(variables_,
- "private static final $type$ $default_constant$ = $default_constant_value$;\n");
+ "$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"
@@ -671,7 +713,7 @@ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params&
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
void RepeatedPrimitiveFieldGenerator::
-GenerateMembers(io::Printer* printer) const {
+GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
printer->Print(variables_,
"public $type$[] $name$;\n");
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
index d207535..c04a19b 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
@@ -46,11 +46,14 @@ namespace javanano {
class PrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params &params);
+ explicit PrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Params &params);
~PrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateMembers(io::Printer* printer) const;
+ 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;
@@ -69,12 +72,14 @@ class PrimitiveFieldGenerator : public FieldGenerator {
class AccessorPrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit AccessorPrimitiveFieldGenerator( const FieldDescriptor* descriptor,
+ explicit AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Params &params, int has_bit_index);
~AccessorPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateMembers(io::Printer* printer) const;
+ 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;
@@ -95,7 +100,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateMembers(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 GenerateMergingCodeFromPacked(io::Printer* printer) const;