Home | History | Annotate | Download | only in javanano
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // http://code.google.com/p/protobuf/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 // Author: kenton (at) google.com (Kenton Varda)
     32 //  Based on original Protocol Buffers design by
     33 //  Sanjay Ghemawat, Jeff Dean, and others.
     34 
     35 #include <algorithm>
     36 #include <google/protobuf/stubs/hash.h>
     37 #include <google/protobuf/compiler/javanano/javanano_message.h>
     38 #include <google/protobuf/compiler/javanano/javanano_enum.h>
     39 #include <google/protobuf/compiler/javanano/javanano_extension.h>
     40 #include <google/protobuf/compiler/javanano/javanano_helpers.h>
     41 #include <google/protobuf/stubs/strutil.h>
     42 #include <google/protobuf/io/printer.h>
     43 #include <google/protobuf/io/coded_stream.h>
     44 #include <google/protobuf/wire_format.h>
     45 #include <google/protobuf/descriptor.pb.h>
     46 
     47 namespace google {
     48 namespace protobuf {
     49 namespace compiler {
     50 namespace javanano {
     51 
     52 using internal::WireFormat;
     53 using internal::WireFormatLite;
     54 
     55 namespace {
     56 
     57 struct FieldOrderingByNumber {
     58   inline bool operator()(const FieldDescriptor* a,
     59                          const FieldDescriptor* b) const {
     60     return a->number() < b->number();
     61   }
     62 };
     63 
     64 // Sort the fields of the given Descriptor by number into a new[]'d array
     65 // and return it.
     66 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
     67   const FieldDescriptor** fields =
     68     new const FieldDescriptor*[descriptor->field_count()];
     69   for (int i = 0; i < descriptor->field_count(); i++) {
     70     fields[i] = descriptor->field(i);
     71   }
     72   sort(fields, fields + descriptor->field_count(),
     73        FieldOrderingByNumber());
     74   return fields;
     75 }
     76 
     77 }  // namespace
     78 
     79 // ===================================================================
     80 
     81 MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
     82   : params_(params),
     83     descriptor_(descriptor),
     84     field_generators_(descriptor, params) {
     85 }
     86 
     87 MessageGenerator::~MessageGenerator() {}
     88 
     89 void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
     90   // Generate static members for all nested types.
     91   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     92     // TODO(kenton):  Reuse MessageGenerator objects?
     93     MessageGenerator(descriptor_->nested_type(i), params_)
     94       .GenerateStaticVariables(printer);
     95   }
     96 }
     97 
     98 void MessageGenerator::GenerateStaticVariableInitializers(
     99     io::Printer* printer) {
    100   // Generate static member initializers for all nested types.
    101   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
    102    // TODO(kenton):  Reuse MessageGenerator objects?
    103     MessageGenerator(descriptor_->nested_type(i), params_)
    104       .GenerateStaticVariableInitializers(printer);
    105   }
    106 }
    107 
    108 void MessageGenerator::Generate(io::Printer* printer) {
    109   if (!params_.store_unknown_fields() &&
    110       (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
    111     GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
    112         "'store_unknown_fields' generator option is 'true'\n";
    113   }
    114 
    115   const string& file_name = descriptor_->file()->name();
    116   bool is_own_file =
    117     params_.java_multiple_files(file_name)
    118       && descriptor_->containing_type() == NULL;
    119 
    120   if (is_own_file) {
    121     // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
    122     // may have the same names as constants in the nested classes. This causes Java warnings, but
    123     // is not fatal, so we suppress those warnings here in the top-most class declaration.
    124     printer->Print(
    125       "\n"
    126       "@SuppressWarnings(\"hiding\")\n"
    127       "public final class $classname$ extends\n",
    128       "classname", descriptor_->name());
    129   } else {
    130     printer->Print(
    131       "\n"
    132       "public static final class $classname$ extends\n",
    133       "classname", descriptor_->name());
    134   }
    135   if (params_.store_unknown_fields() && params_.parcelable_messages()) {
    136     printer->Print(
    137       "    com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$> {\n",
    138       "classname", descriptor_->name());
    139   } else if (params_.store_unknown_fields()) {
    140     printer->Print(
    141       "    com.google.protobuf.nano.ExtendableMessageNano<$classname$> {\n",
    142       "classname", descriptor_->name());
    143   } else if (params_.parcelable_messages()) {
    144     printer->Print(
    145       "    com.google.protobuf.nano.android.ParcelableMessageNano {\n");
    146   } else {
    147     printer->Print(
    148       "    com.google.protobuf.nano.MessageNano {\n");
    149   }
    150   printer->Indent();
    151 
    152   // Nested types and extensions
    153   for (int i = 0; i < descriptor_->extension_count(); i++) {
    154     ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
    155   }
    156 
    157   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
    158     EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
    159   }
    160 
    161   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
    162     MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
    163   }
    164 
    165   // Lazy initialization of otherwise static final fields can help prevent the
    166   // class initializer from being generated. We want to prevent it because it
    167   // stops ProGuard from inlining any methods in this class into call sites and
    168   // therefore reducing the method count. However, extensions are best kept as
    169   // public static final fields with initializers, so with their existence we
    170   // won't bother with lazy initialization.
    171   bool lazy_init = descriptor_->extension_count() == 0;
    172 
    173   // Empty array
    174   if (lazy_init) {
    175     printer->Print(
    176       "\n"
    177       "private static volatile $classname$[] _emptyArray;\n"
    178       "public static $classname$[] emptyArray() {\n"
    179       "  // Lazily initializes the empty array\n"
    180       "  if (_emptyArray == null) {\n"
    181       "    synchronized (\n"
    182       "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
    183       "      if (_emptyArray == null) {\n"
    184       "        _emptyArray = new $classname$[0];\n"
    185       "      }\n"
    186       "    }\n"
    187       "  }\n"
    188       "  return _emptyArray;\n"
    189       "}\n",
    190       "classname", descriptor_->name());
    191   } else {
    192     printer->Print(
    193       "\n"
    194       "private static final $classname$[] EMPTY_ARRAY = {};\n"
    195       "public static $classname$[] emptyArray() {\n"
    196       "  return EMPTY_ARRAY;\n"
    197       "}\n",
    198       "classname", descriptor_->name());
    199   }
    200 
    201   // Integers for bit fields
    202   int totalInts = (field_generators_.total_bits() + 31) / 32;
    203   if (totalInts > 0) {
    204     printer->Print("\n");
    205     for (int i = 0; i < totalInts; i++) {
    206       printer->Print("private int $bit_field_name$;\n",
    207         "bit_field_name", GetBitFieldName(i));
    208     }
    209   }
    210 
    211   // Fields and maybe their default values
    212   for (int i = 0; i < descriptor_->field_count(); i++) {
    213     printer->Print("\n");
    214     PrintFieldComment(printer, descriptor_->field(i));
    215     field_generators_.get(descriptor_->field(i)).GenerateMembers(
    216         printer, lazy_init);
    217   }
    218 
    219   // Constructor, with lazy init code if needed
    220   if (lazy_init && field_generators_.saved_defaults_needed()) {
    221     printer->Print(
    222       "\n"
    223       "private static volatile boolean _classInitialized;\n"
    224       "\n"
    225       "public $classname$() {\n"
    226       "  // Lazily initializes the field defaults\n"
    227       "  if (!_classInitialized) {\n"
    228       "    synchronized (\n"
    229       "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
    230       "      if (!_classInitialized) {\n",
    231       "classname", descriptor_->name());
    232     printer->Indent();
    233     printer->Indent();
    234     printer->Indent();
    235     printer->Indent();
    236     for (int i = 0; i < descriptor_->field_count(); i++) {
    237       field_generators_.get(descriptor_->field(i))
    238           .GenerateInitSavedDefaultCode(printer);
    239     }
    240     printer->Outdent();
    241     printer->Outdent();
    242     printer->Outdent();
    243     printer->Outdent();
    244     printer->Print(
    245       "        _classInitialized = true;\n"
    246       "      }\n"
    247       "    }\n"
    248       "  }\n"
    249       "  clear();\n"
    250       "}\n");
    251   } else {
    252     printer->Print(
    253       "\n"
    254       "public $classname$() {\n"
    255       "  clear();\n"
    256       "}\n",
    257       "classname", descriptor_->name());
    258   }
    259 
    260   // Other methods in this class
    261 
    262   GenerateClear(printer);
    263 
    264   if (params_.generate_equals()) {
    265     GenerateEquals(printer);
    266     GenerateHashCode(printer);
    267   }
    268 
    269   GenerateMessageSerializationMethods(printer);
    270   GenerateMergeFromMethods(printer);
    271   GenerateParseFromMethods(printer);
    272 
    273   printer->Outdent();
    274   printer->Print("}\n");
    275 }
    276 
    277 // ===================================================================
    278 
    279 void MessageGenerator::
    280 GenerateMessageSerializationMethods(io::Printer* printer) {
    281   // Rely on the parent implementations of writeTo() and getSerializedSize()
    282   // if there are no fields to serialize in this message.
    283   if (descriptor_->field_count() == 0) {
    284     return;
    285   }
    286 
    287   scoped_array<const FieldDescriptor*> sorted_fields(
    288     SortFieldsByNumber(descriptor_));
    289 
    290   printer->Print(
    291     "\n"
    292     "@Override\n"
    293     "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
    294     "    throws java.io.IOException {\n");
    295   printer->Indent();
    296 
    297   // Output the fields in sorted order
    298   for (int i = 0; i < descriptor_->field_count(); i++) {
    299     GenerateSerializeOneField(printer, sorted_fields[i]);
    300   }
    301 
    302   // The parent implementation will write any unknown fields if necessary.
    303   printer->Print(
    304     "super.writeTo(output);\n");
    305 
    306   printer->Outdent();
    307   printer->Print("}\n");
    308 
    309   // The parent implementation will get the serialized size for unknown
    310   // fields if necessary.
    311   printer->Print(
    312     "\n"
    313     "@Override\n"
    314     "protected int computeSerializedSize() {\n"
    315     "  int size = super.computeSerializedSize();\n");
    316   printer->Indent();
    317 
    318   for (int i = 0; i < descriptor_->field_count(); i++) {
    319     field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
    320   }
    321 
    322   printer->Outdent();
    323   printer->Print(
    324     "  return size;\n"
    325     "}\n");
    326 }
    327 
    328 void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
    329   scoped_array<const FieldDescriptor*> sorted_fields(
    330     SortFieldsByNumber(descriptor_));
    331 
    332   printer->Print(
    333     "\n"
    334     "@Override\n"
    335     "public $classname$ mergeFrom(\n"
    336     "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
    337     "    throws java.io.IOException {\n",
    338     "classname", descriptor_->name());
    339 
    340   printer->Indent();
    341 
    342   printer->Print(
    343     "while (true) {\n");
    344   printer->Indent();
    345 
    346   printer->Print(
    347     "int tag = input.readTag();\n"
    348     "switch (tag) {\n");
    349   printer->Indent();
    350 
    351   printer->Print(
    352     "case 0:\n"          // zero signals EOF / limit reached
    353     "  return this;\n"
    354     "default: {\n");
    355 
    356   printer->Indent();
    357   if (params_.store_unknown_fields()) {
    358     printer->Print(
    359         "if (!storeUnknownField(input, tag)) {\n"
    360         "  return this;\n"
    361         "}\n");
    362   } else {
    363     printer->Print(
    364         "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
    365         "  return this;\n"   // it's an endgroup tag
    366         "}\n");
    367   }
    368   printer->Print("break;\n");
    369   printer->Outdent();
    370   printer->Print("}\n");
    371 
    372   for (int i = 0; i < descriptor_->field_count(); i++) {
    373     const FieldDescriptor* field = sorted_fields[i];
    374     uint32 tag = WireFormatLite::MakeTag(field->number(),
    375       WireFormat::WireTypeForFieldType(field->type()));
    376 
    377     printer->Print(
    378       "case $tag$: {\n",
    379       "tag", SimpleItoa(tag));
    380     printer->Indent();
    381 
    382     field_generators_.get(field).GenerateMergingCode(printer);
    383 
    384     printer->Outdent();
    385     printer->Print(
    386       "  break;\n"
    387       "}\n");
    388 
    389     if (field->is_packable()) {
    390       // To make packed = true wire compatible, we generate parsing code from a
    391       // packed version of this field regardless of field->options().packed().
    392       uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
    393         WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
    394       printer->Print(
    395         "case $tag$: {\n",
    396         "tag", SimpleItoa(packed_tag));
    397       printer->Indent();
    398 
    399       field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
    400 
    401       printer->Outdent();
    402       printer->Print(
    403         "  break;\n"
    404         "}\n");
    405     }
    406   }
    407 
    408   printer->Outdent();
    409   printer->Outdent();
    410   printer->Outdent();
    411   printer->Print(
    412     "    }\n"     // switch (tag)
    413     "  }\n"       // while (true)
    414     "}\n");
    415 }
    416 
    417 void MessageGenerator::
    418 GenerateParseFromMethods(io::Printer* printer) {
    419   // Note:  These are separate from GenerateMessageSerializationMethods()
    420   //   because they need to be generated even for messages that are optimized
    421   //   for code size.
    422   printer->Print(
    423     "\n"
    424     "public static $classname$ parseFrom(byte[] data)\n"
    425     "    throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
    426     "  return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
    427     "}\n"
    428     "\n"
    429     "public static $classname$ parseFrom(\n"
    430     "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
    431     "    throws java.io.IOException {\n"
    432     "  return new $classname$().mergeFrom(input);\n"
    433     "}\n",
    434     "classname", descriptor_->name());
    435 }
    436 
    437 void MessageGenerator::GenerateSerializeOneField(
    438     io::Printer* printer, const FieldDescriptor* field) {
    439   field_generators_.get(field).GenerateSerializationCode(printer);
    440 }
    441 
    442 void MessageGenerator::GenerateClear(io::Printer* printer) {
    443   printer->Print(
    444     "\n"
    445     "public $classname$ clear() {\n",
    446     "classname", descriptor_->name());
    447   printer->Indent();
    448 
    449   // Clear bit fields.
    450   int totalInts = (field_generators_.total_bits() + 31) / 32;
    451   for (int i = 0; i < totalInts; i++) {
    452     printer->Print("$bit_field_name$ = 0;\n",
    453       "bit_field_name", GetBitFieldName(i));
    454   }
    455 
    456   // Call clear for all of the fields.
    457   for (int i = 0; i < descriptor_->field_count(); i++) {
    458     const FieldDescriptor* field = descriptor_->field(i);
    459     field_generators_.get(field).GenerateClearCode(printer);
    460   }
    461 
    462   // Clear unknown fields.
    463   if (params_.store_unknown_fields()) {
    464     printer->Print("unknownFieldData = null;\n");
    465   }
    466 
    467   printer->Outdent();
    468   printer->Print(
    469     "  cachedSize = -1;\n"
    470     "  return this;\n"
    471     "}\n");
    472 }
    473 
    474 void MessageGenerator::GenerateEquals(io::Printer* printer) {
    475   // Don't override if there are no fields. We could generate an
    476   // equals method that compares types, but often empty messages
    477   // are used as namespaces.
    478   if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
    479     return;
    480   }
    481 
    482   printer->Print(
    483     "\n"
    484     "@Override\n"
    485     "public boolean equals(Object o) {\n");
    486   printer->Indent();
    487   printer->Print(
    488     "if (o == this) {\n"
    489     "  return true;\n"
    490     "}\n"
    491     "if (!(o instanceof $classname$)) {\n"
    492     "  return false;\n"
    493     "}\n"
    494     "$classname$ other = ($classname$) o;\n",
    495     "classname", descriptor_->name());
    496 
    497   for (int i = 0; i < descriptor_->field_count(); i++) {
    498     const FieldDescriptor* field = descriptor_->field(i);
    499     field_generators_.get(field).GenerateEqualsCode(printer);
    500   }
    501 
    502   if (params_.store_unknown_fields()) {
    503     printer->Print(
    504       "return unknownFieldDataEquals(other);\n");
    505   } else {
    506     printer->Print(
    507       "return true;\n");
    508   }
    509 
    510   printer->Outdent();
    511   printer->Print("}\n");
    512 }
    513 
    514 void MessageGenerator::GenerateHashCode(io::Printer* printer) {
    515   if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
    516     return;
    517   }
    518 
    519   printer->Print(
    520     "\n"
    521     "@Override\n"
    522     "public int hashCode() {\n");
    523   printer->Indent();
    524 
    525   printer->Print("int result = 17;\n");
    526   for (int i = 0; i < descriptor_->field_count(); i++) {
    527     const FieldDescriptor* field = descriptor_->field(i);
    528     field_generators_.get(field).GenerateHashCodeCode(printer);
    529   }
    530 
    531   if (params_.store_unknown_fields()) {
    532     printer->Print(
    533       "result = 31 * result + unknownFieldDataHashCode();\n");
    534   }
    535 
    536   printer->Print("return result;\n");
    537 
    538   printer->Outdent();
    539   printer->Print("}\n");
    540 }
    541 
    542 // ===================================================================
    543 
    544 }  // namespace javanano
    545 }  // namespace compiler
    546 }  // namespace protobuf
    547 }  // namespace google
    548