diff options
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 ¶ms) +// ============================================= + +FieldGeneratorMap::FieldGeneratorMap( + const Descriptor* descriptor, const Params ¶ms) : 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 ¶ms, 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 ¶ms); + explicit PrimitiveFieldGenerator( + const FieldDescriptor* descriptor, const Params ¶ms); ~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 ¶ms, 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; |