Merge "Avoid class initializers to help ProGuard."

pull/91/head
Max Cai 11 years ago committed by Gerrit Code Review
commit b3bc6095b2
  1. 12
      java/src/main/java/com/google/protobuf/nano/InternalNano.java
  2. 35
      java/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
  3. 6
      src/google/protobuf/compiler/javanano/javanano_enum_field.cc
  4. 12
      src/google/protobuf/compiler/javanano/javanano_enum_field.h
  5. 39
      src/google/protobuf/compiler/javanano/javanano_field.cc
  6. 20
      src/google/protobuf/compiler/javanano/javanano_field.h
  7. 4
      src/google/protobuf/compiler/javanano/javanano_helpers.cc
  8. 92
      src/google/protobuf/compiler/javanano/javanano_message.cc
  9. 6
      src/google/protobuf/compiler/javanano/javanano_message_field.cc
  10. 7
      src/google/protobuf/compiler/javanano/javanano_message_field.h
  11. 88
      src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
  12. 15
      src/google/protobuf/compiler/javanano/javanano_primitive_field.h

@ -45,6 +45,18 @@ public final class InternalNano {
private 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 * Helper called by generated code to construct default values for string
* fields. * fields.

@ -62,7 +62,7 @@ public final class MessageNanoPrinter {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
try { try {
print(null, message.getClass(), message, new StringBuffer(), buf); print(null, message, new StringBuffer(), buf);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
return "Error printing proto: " + e.getMessage(); 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. * Meant to be called recursively.
* *
* @param identifier the identifier to use, or {@code null} if this is the root message to * @param identifier the identifier to use, or {@code null} if this is the root message to
* print. * print.
* @param clazz the class of {@code message}. * @param object the value to print. May in fact be a primitive value or byte array and not a
* @param message the value to print. May in fact be a primitive value or byte array and not a
* message. * message.
* @param indentBuf the indentation each line should begin with. * @param indentBuf the indentation each line should begin with.
* @param buf the output buffer. * @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 { StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException {
if (message == null) { if (object == null) {
// This can happen if... // This can happen if...
// - we're about to print a message, String, or byte[], but it not present; // - 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 // - we're about to print a primitive, but "reftype" optional style is enabled, and
// the field is unset. // the field is unset.
// In both cases the appropriate behavior is to output nothing. // 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(); int origIndentBufLength = indentBuf.length();
if (identifier != null) { if (identifier != null) {
buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n"); buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n");
indentBuf.append(INDENT); 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 '_' // Proto fields are public, non-static variables that do not begin or end with '_'
int modifiers = field.getModifiers(); int modifiers = field.getModifiers();
String fieldName = field.getName(); String fieldName = field.getName();
@ -106,24 +105,24 @@ public final class MessageNanoPrinter {
continue; continue;
} }
Class <?> fieldType = field.getType(); Class<?> fieldType = field.getType();
Object value = field.get(message); Object value = field.get(object);
if (fieldType.isArray()) { if (fieldType.isArray()) {
Class<?> arrayType = fieldType.getComponentType(); Class<?> arrayType = fieldType.getComponentType();
// bytes is special since it's not repeated, but is represented by an array // bytes is special since it's not repeated, but is represented by an array
if (arrayType == byte.class) { if (arrayType == byte.class) {
print(fieldName, fieldType, value, indentBuf, buf); print(fieldName, value, indentBuf, buf);
} else { } else {
int len = value == null ? 0 : Array.getLength(value); int len = value == null ? 0 : Array.getLength(value);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Object elem = Array.get(value, i); Object elem = Array.get(value, i);
print(fieldName, arrayType, elem, indentBuf, buf); print(fieldName, elem, indentBuf, buf);
} }
} }
} else { } else {
print(fieldName, fieldType, value, indentBuf, buf); print(fieldName, value, indentBuf, buf);
} }
} }
if (identifier != null) { if (identifier != null) {
@ -134,13 +133,13 @@ public final class MessageNanoPrinter {
// Non-null primitive value // Non-null primitive value
identifier = deCamelCaseify(identifier); identifier = deCamelCaseify(identifier);
buf.append(indentBuf).append(identifier).append(": "); buf.append(indentBuf).append(identifier).append(": ");
if (message instanceof String) { if (object instanceof String) {
String stringMessage = sanitizeString((String) message); String stringMessage = sanitizeString((String) object);
buf.append("\"").append(stringMessage).append("\""); buf.append("\"").append(stringMessage).append("\"");
} else if (message instanceof byte[]) { } else if (object instanceof byte[]) {
appendQuotedBytes((byte[]) message, buf); appendQuotedBytes((byte[]) object, buf);
} else { } else {
buf.append(message); buf.append(object);
} }
buf.append("\n"); buf.append("\n");
} }

@ -87,7 +87,7 @@ EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
EnumFieldGenerator::~EnumFieldGenerator() {} EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator:: void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$ $name$;\n"); "public $type$ $name$;\n");
@ -214,7 +214,7 @@ AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
void AccessorEnumFieldGenerator:: void AccessorEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"private int $name$_;\n" "private int $name$_;\n"
"public int get$capitalized_name$() {\n" "public int get$capitalized_name$() {\n"
@ -291,7 +291,7 @@ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& para
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator:: void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$[] $name$;\n"); "public $type$[] $name$;\n");
} }

@ -46,11 +46,12 @@ namespace javanano {
class EnumFieldGenerator : public FieldGenerator { class EnumFieldGenerator : public FieldGenerator {
public: public:
explicit EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params); explicit EnumFieldGenerator(
const FieldDescriptor* descriptor, const Params& params);
~EnumFieldGenerator(); ~EnumFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
@ -72,7 +73,7 @@ class AccessorEnumFieldGenerator : public FieldGenerator {
~AccessorEnumFieldGenerator(); ~AccessorEnumFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
@ -89,11 +90,12 @@ class AccessorEnumFieldGenerator : public FieldGenerator {
class RepeatedEnumFieldGenerator : public FieldGenerator { class RepeatedEnumFieldGenerator : public FieldGenerator {
public: public:
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params); explicit RepeatedEnumFieldGenerator(
const FieldDescriptor* descriptor, const Params& params);
~RepeatedEnumFieldGenerator(); ~RepeatedEnumFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateMergingCodeFromPacked(io::Printer* printer) const; void GenerateMergingCodeFromPacked(io::Printer* printer) const;

@ -46,6 +46,19 @@ namespace javanano {
FieldGenerator::~FieldGenerator() {} 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 { void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
// Reaching here indicates a bug. Cases are: // Reaching here indicates a bug. Cases are:
// - This FieldGenerator should support packing, but this method should be // - 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."; << "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), : descriptor_(descriptor),
field_generators_( field_generators_(
new scoped_ptr<FieldGenerator>[descriptor->field_count()]), new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
extension_generators_(
new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
int next_has_bit_index = 0; int next_has_bit_index = 0;
bool saved_defaults_needed = false;
// Construct all the FieldGenerators. // Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) { for (int i = 0; i < descriptor->field_count(); i++) {
field_generators_[i].reset( FieldGenerator* field_generator = MakeGenerator(
MakeGenerator(descriptor->field(i), params, &next_has_bit_index)); descriptor->field(i), params, &next_has_bit_index);
} saved_defaults_needed = saved_defaults_needed
for (int i = 0; i < descriptor->extension_count(); i++) { || field_generator->SavedDefaultNeeded();
extension_generators_[i].reset( field_generators_[i].reset(field_generator);
MakeGenerator(descriptor->extension(i), params, &next_has_bit_index));
} }
total_bits_ = next_has_bit_index; total_bits_ = next_has_bit_index;
saved_defaults_needed_ = saved_defaults_needed;
} }
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
@ -122,10 +137,6 @@ const FieldGenerator& FieldGeneratorMap::get(
return *field_generators_[field->index()]; return *field_generators_[field->index()];
} }
const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
return *extension_generators_[index];
}
} // namespace javanano } // namespace javanano
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf

@ -53,11 +53,23 @@ namespace javanano {
class FieldGenerator { class FieldGenerator {
public: public:
//FieldGenerator() {}
FieldGenerator(const Params& params) : params_(params) {} FieldGenerator(const Params& params) : params_(params) {}
virtual ~FieldGenerator(); 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 GenerateClearCode(io::Printer* printer) const = 0;
virtual void GenerateMergingCode(io::Printer* printer) const = 0; virtual void GenerateMergingCode(io::Printer* printer) const = 0;
@ -84,14 +96,14 @@ class FieldGeneratorMap {
~FieldGeneratorMap(); ~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const; const FieldGenerator& get(const FieldDescriptor* field) const;
const FieldGenerator& get_extension(int index) const;
int total_bits() const { return total_bits_; } int total_bits() const { return total_bits_; }
bool saved_defaults_needed() const { return saved_defaults_needed_; }
private: private:
const Descriptor* descriptor_; const Descriptor* descriptor_;
scoped_array<scoped_ptr<FieldGenerator> > field_generators_; scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
int total_bits_; int total_bits_;
bool saved_defaults_needed_;
static FieldGenerator* MakeGenerator(const FieldDescriptor* field, static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
const Params &params, int* next_has_bit_index); const Params &params, int* next_has_bit_index);

@ -261,9 +261,7 @@ string FieldConstantName(const FieldDescriptor *field) {
} }
string FieldDefaultConstantName(const FieldDescriptor *field) { string FieldDefaultConstantName(const FieldDescriptor *field) {
string name = field->name() + "_DEFAULT"; return "_" + RenameJavaKeywords(UnderscoresToCamelCase(field)) + "Default";
UpperString(&name);
return name;
} }
JavaType GetJavaType(FieldDescriptor::Type field_type) { JavaType GetJavaType(FieldDescriptor::Type field_type) {

@ -155,14 +155,6 @@ void MessageGenerator::Generate(io::Printer* printer) {
" com.google.protobuf.nano.MessageNano {\n"); " com.google.protobuf.nano.MessageNano {\n");
} }
printer->Indent(); 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 // Nested types and extensions
for (int i = 0; i < descriptor_->extension_count(); i++) { 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); 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 // Integers for bit fields
int totalInts = (field_generators_.total_bits() + 31) / 32; int totalInts = (field_generators_.total_bits() + 31) / 32;
if (totalInts > 0) { 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++) { for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("\n"); printer->Print("\n");
PrintFieldComment(printer, descriptor_->field(i)); 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); GenerateClear(printer);
if (params_.generate_equals()) { if (params_.generate_equals()) {

@ -82,7 +82,7 @@ MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
MessageFieldGenerator::~MessageFieldGenerator() {} MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator:: void MessageFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$ $name$;\n"); "public $type$ $name$;\n");
} }
@ -158,7 +158,7 @@ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& p
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
void RepeatedMessageFieldGenerator:: void RepeatedMessageFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$[] $name$;\n"); "public $type$[] $name$;\n");
} }
@ -166,7 +166,7 @@ GenerateMembers(io::Printer* printer) const {
void RepeatedMessageFieldGenerator:: void RepeatedMessageFieldGenerator::
GenerateClearCode(io::Printer* printer) const { GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"$name$ = $type$.EMPTY_ARRAY;\n"); "$name$ = $type$.emptyArray();\n");
} }
void RepeatedMessageFieldGenerator:: void RepeatedMessageFieldGenerator::

@ -46,11 +46,12 @@ namespace javanano {
class MessageFieldGenerator : public FieldGenerator { class MessageFieldGenerator : public FieldGenerator {
public: public:
explicit MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params); explicit MessageFieldGenerator(
const FieldDescriptor* descriptor, const Params& params);
~MessageFieldGenerator(); ~MessageFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
@ -72,7 +73,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
~RepeatedMessageFieldGenerator(); ~RepeatedMessageFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;

@ -251,35 +251,41 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param
} else { } else {
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
} }
(*variables)["default"] = DefaultValue(params, descriptor); // Deals with defaults. For C++-string types (string and bytes),
(*variables)["default_constant"] = FieldDefaultConstantName(descriptor); // we might need to have the generated code do the unicode decoding
// For C++-string types (string and bytes), we might need to have // (see comments in InternalNano.java for gory details.). We would
// the generated code do the unicode decoding (see comments in // like to do this once into a static field and re-use that from
// InternalNano.java for gory details.). We would like to do this
// once into a "private static final" field and re-use that from
// then on. // then on.
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING && if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
!descriptor->default_value_string().empty() && !descriptor->default_value_string().empty() &&
!params.use_reference_types_for_primitives()) { !params.use_reference_types_for_primitives()) {
string default_value;
if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { 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\")", "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
CEscape(descriptor->default_value_string())); CEscape(descriptor->default_value_string()));
(*variables)["default_copy_if_needed"] = (*variables)["default"] + ".clone()"; (*variables)["default_copy_if_needed"] =
} else { (*variables)["default"] + ".clone()";
if (AllAscii(descriptor->default_value_string())) { } else if (AllAscii(descriptor->default_value_string())) {
// All chars are ASCII. In this case CEscape() works fine. // All chars are ASCII. In this case directly referencing a
default_value = "\"" + CEscape(descriptor->default_value_string()) + "\""; // CEscape()'d string literal works fine.
(*variables)["default"] =
"\"" + CEscape(descriptor->default_value_string()) + "\"";
(*variables)["default_copy_if_needed"] = (*variables)["default"];
} else { } else {
default_value = strings::Substitute( // 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\")", "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
CEscape(descriptor->default_value_string())); CEscape(descriptor->default_value_string()));
}
(*variables)["default_copy_if_needed"] = (*variables)["default"]; (*variables)["default_copy_if_needed"] = (*variables)["default"];
} }
(*variables)["default_constant_value"] = default_value;
} else { } else {
// Non-string, non-bytes field. Defaults are literals.
(*variables)["default"] = DefaultValue(params, descriptor);
(*variables)["default_copy_if_needed"] = (*variables)["default"]; (*variables)["default_copy_if_needed"] = (*variables)["default"];
} }
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
@ -306,12 +312,29 @@ PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} 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:: void PrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool lazy_init) const {
if (variables_.find("default_constant_value") != variables_.end()) { if (variables_.find("default_constant") != variables_.end()) {
// Those primitive types that need a saved default. // Those primitive types that need a saved default.
if (lazy_init) {
printer->Print(variables_,
"private static $type$ $default_constant$;\n");
} else {
printer->Print(variables_, printer->Print(variables_,
"private static final $type$ $default_constant$ = $default_constant_value$;\n"); "private static final $type$ $default_constant$ =\n"
" $default_constant_value$;\n");
}
} }
printer->Print(variables_, printer->Print(variables_,
@ -514,11 +537,30 @@ AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {} AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
return variables_.find("default_constant") != variables_.end();
}
void AccessorPrimitiveFieldGenerator:: void AccessorPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateInitSavedDefaultCode(io::Printer* printer) const {
if (variables_.find("default_constant_value") != variables_.end()) { if (variables_.find("default_constant") != variables_.end()) {
printer->Print(variables_, 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_, printer->Print(variables_,
"private $type$ $name$_;\n" "private $type$ $name$_;\n"
@ -671,7 +713,7 @@ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params&
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
void RepeatedPrimitiveFieldGenerator:: void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
printer->Print(variables_, printer->Print(variables_,
"public $type$[] $name$;\n"); "public $type$[] $name$;\n");
} }

@ -46,11 +46,14 @@ namespace javanano {
class PrimitiveFieldGenerator : public FieldGenerator { class PrimitiveFieldGenerator : public FieldGenerator {
public: public:
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params &params); explicit PrimitiveFieldGenerator(
const FieldDescriptor* descriptor, const Params &params);
~PrimitiveFieldGenerator(); ~PrimitiveFieldGenerator();
// implements FieldGenerator --------------------------------------- // 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 GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
@ -69,12 +72,14 @@ class PrimitiveFieldGenerator : public FieldGenerator {
class AccessorPrimitiveFieldGenerator : public FieldGenerator { class AccessorPrimitiveFieldGenerator : public FieldGenerator {
public: public:
explicit AccessorPrimitiveFieldGenerator( const FieldDescriptor* descriptor, explicit AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Params &params, int has_bit_index); const Params &params, int has_bit_index);
~AccessorPrimitiveFieldGenerator(); ~AccessorPrimitiveFieldGenerator();
// implements FieldGenerator --------------------------------------- // 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 GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
@ -95,7 +100,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
~RepeatedPrimitiveFieldGenerator(); ~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator --------------------------------------- // implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer, bool lazy_init) const;
void GenerateClearCode(io::Printer* printer) const; void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const;
void GenerateMergingCodeFromPacked(io::Printer* printer) const; void GenerateMergingCodeFromPacked(io::Printer* printer) const;

Loading…
Cancel
Save