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 <map>
     36 #include <math.h>
     37 #include <string>
     38 
     39 #include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
     40 #include <google/protobuf/stubs/common.h>
     41 #include <google/protobuf/compiler/javanano/javanano_helpers.h>
     42 #include <google/protobuf/io/printer.h>
     43 #include <google/protobuf/wire_format.h>
     44 #include <google/protobuf/stubs/strutil.h>
     45 #include <google/protobuf/stubs/substitute.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 bool IsReferenceType(JavaType type) {
     58   switch (type) {
     59     case JAVATYPE_INT    : return false;
     60     case JAVATYPE_LONG   : return false;
     61     case JAVATYPE_FLOAT  : return false;
     62     case JAVATYPE_DOUBLE : return false;
     63     case JAVATYPE_BOOLEAN: return false;
     64     case JAVATYPE_STRING : return true;
     65     case JAVATYPE_BYTES  : return true;
     66     case JAVATYPE_ENUM   : return false;
     67     case JAVATYPE_MESSAGE: return true;
     68 
     69     // No default because we want the compiler to complain if any new
     70     // JavaTypes are added.
     71   }
     72 
     73   GOOGLE_LOG(FATAL) << "Can't get here.";
     74   return false;
     75 }
     76 
     77 bool IsArrayType(JavaType type) {
     78   switch (type) {
     79     case JAVATYPE_INT    : return false;
     80     case JAVATYPE_LONG   : return false;
     81     case JAVATYPE_FLOAT  : return false;
     82     case JAVATYPE_DOUBLE : return false;
     83     case JAVATYPE_BOOLEAN: return false;
     84     case JAVATYPE_STRING : return false;
     85     case JAVATYPE_BYTES  : return true;
     86     case JAVATYPE_ENUM   : return false;
     87     case JAVATYPE_MESSAGE: return false;
     88 
     89     // No default because we want the compiler to complain if any new
     90     // JavaTypes are added.
     91   }
     92 
     93   GOOGLE_LOG(FATAL) << "Can't get here.";
     94   return false;
     95 }
     96 
     97 const char* GetCapitalizedType(const FieldDescriptor* field) {
     98   switch (field->type()) {
     99     case FieldDescriptor::TYPE_INT32   : return "Int32"   ;
    100     case FieldDescriptor::TYPE_UINT32  : return "UInt32"  ;
    101     case FieldDescriptor::TYPE_SINT32  : return "SInt32"  ;
    102     case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ;
    103     case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
    104     case FieldDescriptor::TYPE_INT64   : return "Int64"   ;
    105     case FieldDescriptor::TYPE_UINT64  : return "UInt64"  ;
    106     case FieldDescriptor::TYPE_SINT64  : return "SInt64"  ;
    107     case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ;
    108     case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
    109     case FieldDescriptor::TYPE_FLOAT   : return "Float"   ;
    110     case FieldDescriptor::TYPE_DOUBLE  : return "Double"  ;
    111     case FieldDescriptor::TYPE_BOOL    : return "Bool"    ;
    112     case FieldDescriptor::TYPE_STRING  : return "String"  ;
    113     case FieldDescriptor::TYPE_BYTES   : return "Bytes"   ;
    114     case FieldDescriptor::TYPE_ENUM    : return "Enum"    ;
    115     case FieldDescriptor::TYPE_GROUP   : return "Group"   ;
    116     case FieldDescriptor::TYPE_MESSAGE : return "Message" ;
    117 
    118     // No default because we want the compiler to complain if any new
    119     // types are added.
    120   }
    121 
    122   GOOGLE_LOG(FATAL) << "Can't get here.";
    123   return NULL;
    124 }
    125 
    126 // For encodings with fixed sizes, returns that size in bytes.  Otherwise
    127 // returns -1.
    128 int FixedSize(FieldDescriptor::Type type) {
    129   switch (type) {
    130     case FieldDescriptor::TYPE_INT32   : return -1;
    131     case FieldDescriptor::TYPE_INT64   : return -1;
    132     case FieldDescriptor::TYPE_UINT32  : return -1;
    133     case FieldDescriptor::TYPE_UINT64  : return -1;
    134     case FieldDescriptor::TYPE_SINT32  : return -1;
    135     case FieldDescriptor::TYPE_SINT64  : return -1;
    136     case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
    137     case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
    138     case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
    139     case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
    140     case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
    141     case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
    142 
    143     case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
    144     case FieldDescriptor::TYPE_ENUM    : return -1;
    145 
    146     case FieldDescriptor::TYPE_STRING  : return -1;
    147     case FieldDescriptor::TYPE_BYTES   : return -1;
    148     case FieldDescriptor::TYPE_GROUP   : return -1;
    149     case FieldDescriptor::TYPE_MESSAGE : return -1;
    150 
    151     // No default because we want the compiler to complain if any new
    152     // types are added.
    153   }
    154   GOOGLE_LOG(FATAL) << "Can't get here.";
    155   return -1;
    156 }
    157 
    158 // Return true if the type is a that has variable length
    159 // for instance String's.
    160 bool IsVariableLenType(JavaType type) {
    161   switch (type) {
    162     case JAVATYPE_INT    : return false;
    163     case JAVATYPE_LONG   : return false;
    164     case JAVATYPE_FLOAT  : return false;
    165     case JAVATYPE_DOUBLE : return false;
    166     case JAVATYPE_BOOLEAN: return false;
    167     case JAVATYPE_STRING : return true;
    168     case JAVATYPE_BYTES  : return true;
    169     case JAVATYPE_ENUM   : return false;
    170     case JAVATYPE_MESSAGE: return true;
    171 
    172     // No default because we want the compiler to complain if any new
    173     // JavaTypes are added.
    174   }
    175 
    176   GOOGLE_LOG(FATAL) << "Can't get here.";
    177   return false;
    178 }
    179 
    180 bool AllAscii(const string& text) {
    181   for (int i = 0; i < text.size(); i++) {
    182     if ((text[i] & 0x80) != 0) {
    183       return false;
    184     }
    185   }
    186   return true;
    187 }
    188 
    189 void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
    190                            map<string, string>* variables) {
    191   (*variables)["name"] =
    192     RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
    193   (*variables)["capitalized_name"] =
    194     RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
    195   (*variables)["number"] = SimpleItoa(descriptor->number());
    196   if (params.use_reference_types_for_primitives()
    197       && !descriptor->is_repeated()) {
    198     (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
    199   } else {
    200     (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
    201   }
    202   // Deals with defaults. For C++-string types (string and bytes),
    203   // we might need to have the generated code do the unicode decoding
    204   // (see comments in InternalNano.java for gory details.). We would
    205   // like to do this once into a static field and re-use that from
    206   // then on.
    207   if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
    208       !descriptor->default_value_string().empty() &&
    209       !params.use_reference_types_for_primitives()) {
    210     if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
    211       (*variables)["default"] = DefaultValue(params, descriptor);
    212       (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
    213       (*variables)["default_constant_value"] = strings::Substitute(
    214           "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
    215           CEscape(descriptor->default_value_string()));
    216       (*variables)["default_copy_if_needed"] =
    217           (*variables)["default"] + ".clone()";
    218     } else if (AllAscii(descriptor->default_value_string())) {
    219       // All chars are ASCII.  In this case directly referencing a
    220       // CEscape()'d string literal works fine.
    221       (*variables)["default"] =
    222           "\"" + CEscape(descriptor->default_value_string()) + "\"";
    223       (*variables)["default_copy_if_needed"] = (*variables)["default"];
    224     } else {
    225       // Strings where some chars are non-ASCII. We need to save the
    226       // default value.
    227       (*variables)["default"] = DefaultValue(params, descriptor);
    228       (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
    229       (*variables)["default_constant_value"] = strings::Substitute(
    230           "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
    231           CEscape(descriptor->default_value_string()));
    232       (*variables)["default_copy_if_needed"] = (*variables)["default"];
    233     }
    234   } else {
    235     // Non-string, non-bytes field. Defaults are literals.
    236     (*variables)["default"] = DefaultValue(params, descriptor);
    237     (*variables)["default_copy_if_needed"] = (*variables)["default"];
    238   }
    239   (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
    240   (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
    241   (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
    242   (*variables)["tag_size"] = SimpleItoa(
    243       WireFormat::TagSize(descriptor->number(), descriptor->type()));
    244   (*variables)["non_packed_tag"] = SimpleItoa(
    245       internal::WireFormatLite::MakeTag(descriptor->number(),
    246           internal::WireFormat::WireTypeForFieldType(descriptor->type())));
    247   int fixed_size = FixedSize(descriptor->type());
    248   if (fixed_size != -1) {
    249     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
    250   }
    251   (*variables)["message_name"] = descriptor->containing_type()->name();
    252   (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor);
    253 }
    254 }  // namespace
    255 
    256 // ===================================================================
    257 
    258 PrimitiveFieldGenerator::
    259 PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
    260   : FieldGenerator(params), descriptor_(descriptor) {
    261   SetPrimitiveVariables(descriptor, params, &variables_);
    262 }
    263 
    264 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
    265 
    266 bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
    267   return variables_.find("default_constant") != variables_.end();
    268 }
    269 
    270 void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
    271   if (variables_.find("default_constant") != variables_.end()) {
    272     printer->Print(variables_,
    273       "$default_constant$ = $default_constant_value$;\n");
    274   }
    275 }
    276 
    277 void PrimitiveFieldGenerator::
    278 GenerateMembers(io::Printer* printer, bool lazy_init) const {
    279   if (variables_.find("default_constant") != variables_.end()) {
    280     // Those primitive types that need a saved default.
    281     if (lazy_init) {
    282       printer->Print(variables_,
    283         "private static $type$ $default_constant$;\n");
    284     } else {
    285       printer->Print(variables_,
    286         "private static final $type$ $default_constant$ =\n"
    287         "    $default_constant_value$;\n");
    288     }
    289   }
    290 
    291   printer->Print(variables_,
    292     "public $type$ $name$;\n");
    293 
    294   if (params_.generate_has()) {
    295     printer->Print(variables_,
    296       "public boolean has$capitalized_name$;\n");
    297   }
    298 }
    299 
    300 void PrimitiveFieldGenerator::
    301 GenerateClearCode(io::Printer* printer) const {
    302   printer->Print(variables_,
    303     "$name$ = $default_copy_if_needed$;\n");
    304 
    305   if (params_.generate_has()) {
    306     printer->Print(variables_,
    307       "has$capitalized_name$ = false;\n");
    308   }
    309 }
    310 
    311 void PrimitiveFieldGenerator::
    312 GenerateMergingCode(io::Printer* printer) const {
    313   printer->Print(variables_,
    314     "this.$name$ = input.read$capitalized_type$();\n");
    315 
    316   if (params_.generate_has()) {
    317     printer->Print(variables_,
    318       "has$capitalized_name$ = true;\n");
    319   }
    320 }
    321 
    322 void PrimitiveFieldGenerator::
    323 GenerateSerializationConditional(io::Printer* printer) const {
    324   if (params_.use_reference_types_for_primitives()) {
    325     // For reference type mode, serialize based on equality
    326     // to null.
    327     printer->Print(variables_,
    328       "if (this.$name$ != null) {\n");
    329     return;
    330   }
    331   if (params_.generate_has()) {
    332     printer->Print(variables_,
    333       "if (has$capitalized_name$ || ");
    334   } else {
    335     printer->Print(variables_,
    336       "if (");
    337   }
    338   JavaType java_type = GetJavaType(descriptor_);
    339   if (IsArrayType(java_type)) {
    340     printer->Print(variables_,
    341       "!java.util.Arrays.equals(this.$name$, $default$)) {\n");
    342   } else if (IsReferenceType(java_type)) {
    343     printer->Print(variables_,
    344       "!this.$name$.equals($default$)) {\n");
    345   } else if (java_type == JAVATYPE_FLOAT) {
    346     printer->Print(variables_,
    347       "java.lang.Float.floatToIntBits(this.$name$)\n"
    348       "    != java.lang.Float.floatToIntBits($default$)) {\n");
    349   } else if (java_type == JAVATYPE_DOUBLE) {
    350     printer->Print(variables_,
    351       "java.lang.Double.doubleToLongBits(this.$name$)\n"
    352       "    != java.lang.Double.doubleToLongBits($default$)) {\n");
    353   } else {
    354     printer->Print(variables_,
    355       "this.$name$ != $default$) {\n");
    356   }
    357 }
    358 
    359 void PrimitiveFieldGenerator::
    360 GenerateSerializationCode(io::Printer* printer) const {
    361   if (descriptor_->is_required() && !params_.generate_has()) {
    362     // Always serialize a required field if we don't have the 'has' signal.
    363     printer->Print(variables_,
    364       "output.write$capitalized_type$($number$, this.$name$);\n");
    365   } else {
    366     GenerateSerializationConditional(printer);
    367     printer->Print(variables_,
    368       "  output.write$capitalized_type$($number$, this.$name$);\n"
    369       "}\n");
    370   }
    371 }
    372 
    373 void PrimitiveFieldGenerator::
    374 GenerateSerializedSizeCode(io::Printer* printer) const {
    375   if (descriptor_->is_required() && !params_.generate_has()) {
    376     printer->Print(variables_,
    377       "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    378       "    .compute$capitalized_type$Size($number$, this.$name$);\n");
    379   } else {
    380     GenerateSerializationConditional(printer);
    381     printer->Print(variables_,
    382       "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    383       "      .compute$capitalized_type$Size($number$, this.$name$);\n"
    384       "}\n");
    385   }
    386 }
    387 
    388 void RepeatedPrimitiveFieldGenerator::
    389 GenerateFixClonedCode(io::Printer* printer) const {
    390   printer->Print(variables_,
    391     "if (this.$name$ != null && this.$name$.length > 0) {\n"
    392     "  cloned.$name$ = this.$name$.clone();\n"
    393     "}\n");
    394 }
    395 
    396 void PrimitiveFieldGenerator::
    397 GenerateEqualsCode(io::Printer* printer) const {
    398   // We define equality as serialized form equality. If generate_has(),
    399   // then if the field value equals the default value in both messages,
    400   // but one's 'has' field is set and the other's is not, the serialized
    401   // forms are different and we should return false.
    402   JavaType java_type = GetJavaType(descriptor_);
    403   if (java_type == JAVATYPE_BYTES) {
    404     printer->Print(variables_,
    405       "if (!java.util.Arrays.equals(this.$name$, other.$name$)");
    406     if (params_.generate_has()) {
    407       printer->Print(variables_,
    408         "\n"
    409         "    || (java.util.Arrays.equals(this.$name$, $default$)\n"
    410         "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
    411     }
    412     printer->Print(") {\n"
    413       "  return false;\n"
    414       "}\n");
    415   } else if (java_type == JAVATYPE_STRING
    416       || params_.use_reference_types_for_primitives()) {
    417     printer->Print(variables_,
    418       "if (this.$name$ == null) {\n"
    419       "  if (other.$name$ != null) {\n"
    420       "    return false;\n"
    421       "  }\n"
    422       "} else if (!this.$name$.equals(other.$name$)");
    423     if (params_.generate_has()) {
    424       printer->Print(variables_,
    425         "\n"
    426         "    || (this.$name$.equals($default$)\n"
    427         "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
    428     }
    429     printer->Print(") {\n"
    430       "  return false;\n"
    431       "}\n");
    432   } else if (java_type == JAVATYPE_FLOAT) {
    433     printer->Print(variables_,
    434       "{\n"
    435       "  int bits = java.lang.Float.floatToIntBits(this.$name$);\n"
    436       "  if (bits != java.lang.Float.floatToIntBits(other.$name$)");
    437     if (params_.generate_has()) {
    438       printer->Print(variables_,
    439         "\n"
    440         "      || (bits == java.lang.Float.floatToIntBits($default$)\n"
    441         "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
    442     }
    443     printer->Print(") {\n"
    444       "    return false;\n"
    445       "  }\n"
    446       "}\n");
    447   } else if (java_type == JAVATYPE_DOUBLE) {
    448     printer->Print(variables_,
    449       "{\n"
    450       "  long bits = java.lang.Double.doubleToLongBits(this.$name$);\n"
    451       "  if (bits != java.lang.Double.doubleToLongBits(other.$name$)");
    452     if (params_.generate_has()) {
    453       printer->Print(variables_,
    454         "\n"
    455         "      || (bits == java.lang.Double.doubleToLongBits($default$)\n"
    456         "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
    457     }
    458     printer->Print(") {\n"
    459       "    return false;\n"
    460       "  }\n"
    461       "}\n");
    462   } else {
    463     printer->Print(variables_,
    464       "if (this.$name$ != other.$name$");
    465     if (params_.generate_has()) {
    466       printer->Print(variables_,
    467         "\n"
    468         "    || (this.$name$ == $default$\n"
    469         "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
    470     }
    471     printer->Print(") {\n"
    472       "  return false;\n"
    473       "}\n");
    474   }
    475 }
    476 
    477 void PrimitiveFieldGenerator::
    478 GenerateHashCodeCode(io::Printer* printer) const {
    479   JavaType java_type = GetJavaType(descriptor_);
    480   if (java_type == JAVATYPE_BYTES) {
    481     printer->Print(variables_,
    482       "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n");
    483   } else if (java_type == JAVATYPE_STRING
    484       || params_.use_reference_types_for_primitives()) {
    485     printer->Print(variables_,
    486       "result = 31 * result\n"
    487       "    + (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
    488   } else {
    489     switch (java_type) {
    490       // For all Java primitive types below, the hash codes match the
    491       // results of BoxedType.valueOf(primitiveValue).hashCode().
    492       case JAVATYPE_INT:
    493         printer->Print(variables_,
    494           "result = 31 * result + this.$name$;\n");
    495         break;
    496       case JAVATYPE_LONG:
    497         printer->Print(variables_,
    498           "result = 31 * result\n"
    499           "    + (int) (this.$name$ ^ (this.$name$ >>> 32));\n");
    500         break;
    501       case JAVATYPE_FLOAT:
    502         printer->Print(variables_,
    503           "result = 31 * result\n"
    504           "    + java.lang.Float.floatToIntBits(this.$name$);\n");
    505         break;
    506       case JAVATYPE_DOUBLE:
    507         printer->Print(variables_,
    508           "{\n"
    509           "  long v = java.lang.Double.doubleToLongBits(this.$name$);\n"
    510           "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
    511           "}\n");
    512         break;
    513       case JAVATYPE_BOOLEAN:
    514         printer->Print(variables_,
    515           "result = 31 * result + (this.$name$ ? 1231 : 1237);\n");
    516         break;
    517       default:
    518         GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
    519         break;
    520     }
    521   }
    522 }
    523 
    524 // ===================================================================
    525 
    526 AccessorPrimitiveFieldGenerator::
    527 AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
    528      const Params& params, int has_bit_index)
    529   : FieldGenerator(params), descriptor_(descriptor) {
    530   SetPrimitiveVariables(descriptor, params, &variables_);
    531   SetBitOperationVariables("has", has_bit_index, &variables_);
    532 }
    533 
    534 AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
    535 
    536 bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
    537   return variables_.find("default_constant") != variables_.end();
    538 }
    539 
    540 void AccessorPrimitiveFieldGenerator::
    541 GenerateInitSavedDefaultCode(io::Printer* printer) const {
    542   if (variables_.find("default_constant") != variables_.end()) {
    543     printer->Print(variables_,
    544       "$default_constant$ = $default_constant_value$;\n");
    545   }
    546 }
    547 
    548 void AccessorPrimitiveFieldGenerator::
    549 GenerateMembers(io::Printer* printer, bool lazy_init) const {
    550   if (variables_.find("default_constant") != variables_.end()) {
    551     // Those primitive types that need a saved default.
    552     if (lazy_init) {
    553       printer->Print(variables_,
    554         "private static $type$ $default_constant$;\n");
    555     } else {
    556       printer->Print(variables_,
    557         "private static final $type$ $default_constant$ =\n"
    558         "    $default_constant_value$;\n");
    559     }
    560   }
    561   printer->Print(variables_,
    562     "private $type$ $name$_;\n"
    563     "public $type$ get$capitalized_name$() {\n"
    564     "  return $name$_;\n"
    565     "}\n"
    566     "public $message_name$ set$capitalized_name$($type$ value) {\n");
    567   if (IsReferenceType(GetJavaType(descriptor_))) {
    568     printer->Print(variables_,
    569       "  if (value == null) {\n"
    570       "    throw new java.lang.NullPointerException();\n"
    571       "  }\n");
    572   }
    573   printer->Print(variables_,
    574     "  $name$_ = value;\n"
    575     "  $set_has$;\n"
    576     "  return this;\n"
    577     "}\n"
    578     "public boolean has$capitalized_name$() {\n"
    579     "  return $get_has$;\n"
    580     "}\n"
    581     "public $message_name$ clear$capitalized_name$() {\n"
    582     "  $name$_ = $default_copy_if_needed$;\n"
    583     "  $clear_has$;\n"
    584     "  return this;\n"
    585     "}\n");
    586 }
    587 
    588 void AccessorPrimitiveFieldGenerator::
    589 GenerateClearCode(io::Printer* printer) const {
    590   printer->Print(variables_,
    591     "$name$_ = $default_copy_if_needed$;\n");
    592 }
    593 
    594 void AccessorPrimitiveFieldGenerator::
    595 GenerateMergingCode(io::Printer* printer) const {
    596   printer->Print(variables_,
    597     "$name$_ = input.read$capitalized_type$();\n"
    598     "$set_has$;\n");
    599 }
    600 
    601 void AccessorPrimitiveFieldGenerator::
    602 GenerateSerializationCode(io::Printer* printer) const {
    603   printer->Print(variables_,
    604     "if ($get_has$) {\n"
    605     "  output.write$capitalized_type$($number$, $name$_);\n"
    606     "}\n");
    607 }
    608 
    609 void AccessorPrimitiveFieldGenerator::
    610 GenerateSerializedSizeCode(io::Printer* printer) const {
    611   printer->Print(variables_,
    612     "if ($get_has$) {\n"
    613     "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    614     "      .compute$capitalized_type$Size($number$, $name$_);\n"
    615     "}\n");
    616 }
    617 
    618 void AccessorPrimitiveFieldGenerator::
    619 GenerateEqualsCode(io::Printer* printer) const {
    620   switch (GetJavaType(descriptor_)) {
    621     // For all Java primitive types below, the equality checks match the
    622     // results of BoxedType.valueOf(primitiveValue).equals(otherValue).
    623     case JAVATYPE_FLOAT:
    624       printer->Print(variables_,
    625         "if ($different_has$\n"
    626         "    || java.lang.Float.floatToIntBits($name$_)\n"
    627         "        != java.lang.Float.floatToIntBits(other.$name$_)) {\n"
    628         "  return false;\n"
    629         "}\n");
    630       break;
    631     case JAVATYPE_DOUBLE:
    632       printer->Print(variables_,
    633         "if ($different_has$\n"
    634         "    || java.lang.Double.doubleToLongBits($name$_)\n"
    635         "        != java.lang.Double.doubleToLongBits(other.$name$_)) {\n"
    636         "  return false;\n"
    637         "}\n");
    638       break;
    639     case JAVATYPE_INT:
    640     case JAVATYPE_LONG:
    641     case JAVATYPE_BOOLEAN:
    642       printer->Print(variables_,
    643         "if ($different_has$\n"
    644         "    || $name$_ != other.$name$_) {\n"
    645         "  return false;\n"
    646         "}\n");
    647       break;
    648     case JAVATYPE_STRING:
    649       // Accessor style would guarantee $name$_ non-null
    650       printer->Print(variables_,
    651         "if ($different_has$\n"
    652         "    || !$name$_.equals(other.$name$_)) {\n"
    653         "  return false;\n"
    654         "}\n");
    655       break;
    656     case JAVATYPE_BYTES:
    657       // Accessor style would guarantee $name$_ non-null
    658       printer->Print(variables_,
    659         "if ($different_has$\n"
    660         "    || !java.util.Arrays.equals($name$_, other.$name$_)) {\n"
    661         "  return false;\n"
    662         "}\n");
    663       break;
    664     default:
    665       GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
    666       break;
    667   }
    668 }
    669 
    670 void AccessorPrimitiveFieldGenerator::
    671 GenerateHashCodeCode(io::Printer* printer) const {
    672   switch (GetJavaType(descriptor_)) {
    673     // For all Java primitive types below, the hash codes match the
    674     // results of BoxedType.valueOf(primitiveValue).hashCode().
    675     case JAVATYPE_INT:
    676       printer->Print(variables_,
    677         "result = 31 * result + $name$_;\n");
    678       break;
    679     case JAVATYPE_LONG:
    680       printer->Print(variables_,
    681         "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n");
    682       break;
    683     case JAVATYPE_FLOAT:
    684       printer->Print(variables_,
    685         "result = 31 * result +\n"
    686         "    java.lang.Float.floatToIntBits($name$_);\n");
    687       break;
    688     case JAVATYPE_DOUBLE:
    689       printer->Print(variables_,
    690         "{\n"
    691         "  long v = java.lang.Double.doubleToLongBits($name$_);\n"
    692         "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
    693         "}\n");
    694       break;
    695     case JAVATYPE_BOOLEAN:
    696       printer->Print(variables_,
    697         "result = 31 * result + ($name$_ ? 1231 : 1237);\n");
    698       break;
    699     case JAVATYPE_STRING:
    700       // Accessor style would guarantee $name$_ non-null
    701       printer->Print(variables_,
    702         "result = 31 * result + $name$_.hashCode();\n");
    703       break;
    704     case JAVATYPE_BYTES:
    705       // Accessor style would guarantee $name$_ non-null
    706       printer->Print(variables_,
    707         "result = 31 * result + java.util.Arrays.hashCode($name$_);\n");
    708       break;
    709     default:
    710       GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
    711       break;
    712   }
    713 }
    714 
    715 // ===================================================================
    716 
    717 RepeatedPrimitiveFieldGenerator::
    718 RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
    719   : FieldGenerator(params), descriptor_(descriptor) {
    720   SetPrimitiveVariables(descriptor, params, &variables_);
    721 }
    722 
    723 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
    724 
    725 void RepeatedPrimitiveFieldGenerator::
    726 GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
    727   printer->Print(variables_,
    728     "public $type$[] $name$;\n");
    729 }
    730 
    731 void RepeatedPrimitiveFieldGenerator::
    732 GenerateClearCode(io::Printer* printer) const {
    733   printer->Print(variables_,
    734     "$name$ = $default$;\n");
    735 }
    736 
    737 void RepeatedPrimitiveFieldGenerator::
    738 GenerateMergingCode(io::Printer* printer) const {
    739   // First, figure out the length of the array, then parse.
    740   printer->Print(variables_,
    741     "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
    742     "    .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
    743     "int i = this.$name$ == null ? 0 : this.$name$.length;\n");
    744 
    745   if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
    746     printer->Print(variables_,
    747       "byte[][] newArray = new byte[i + arrayLength][];\n");
    748   } else {
    749     printer->Print(variables_,
    750       "$type$[] newArray = new $type$[i + arrayLength];\n");
    751   }
    752   printer->Print(variables_,
    753     "if (i != 0) {\n"
    754     "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
    755     "}\n"
    756     "for (; i < newArray.length - 1; i++) {\n"
    757     "  newArray[i] = input.read$capitalized_type$();\n"
    758     "  input.readTag();\n"
    759     "}\n"
    760     "// Last one without readTag.\n"
    761     "newArray[i] = input.read$capitalized_type$();\n"
    762     "this.$name$ = newArray;\n");
    763 }
    764 
    765 void RepeatedPrimitiveFieldGenerator::
    766 GenerateMergingCodeFromPacked(io::Printer* printer) const {
    767   printer->Print(
    768     "int length = input.readRawVarint32();\n"
    769     "int limit = input.pushLimit(length);\n");
    770 
    771   // If we know the elements will all be of the same size, the arrayLength
    772   // can be calculated much more easily. However, FixedSize() returns 1 for
    773   // repeated bool fields, which are guaranteed to have the fixed size of
    774   // 1 byte per value only if we control the output. On the wire they can
    775   // legally appear as variable-size integers, so we need to use the slow
    776   // way for repeated bool fields.
    777   if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
    778       || FixedSize(descriptor_->type()) == -1) {
    779     printer->Print(variables_,
    780       "// First pass to compute array length.\n"
    781       "int arrayLength = 0;\n"
    782       "int startPos = input.getPosition();\n"
    783       "while (input.getBytesUntilLimit() > 0) {\n"
    784       "  input.read$capitalized_type$();\n"
    785       "  arrayLength++;\n"
    786       "}\n"
    787       "input.rewindToPosition(startPos);\n");
    788   } else {
    789     printer->Print(variables_,
    790       "int arrayLength = length / $fixed_size$;\n");
    791   }
    792 
    793   printer->Print(variables_,
    794     "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
    795     "$type$[] newArray = new $type$[i + arrayLength];\n"
    796     "if (i != 0) {\n"
    797     "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
    798     "}\n"
    799     "for (; i < newArray.length; i++) {\n"
    800     "  newArray[i] = input.read$capitalized_type$();\n"
    801     "}\n"
    802     "this.$name$ = newArray;\n"
    803     "input.popLimit(limit);\n");
    804 }
    805 
    806 void RepeatedPrimitiveFieldGenerator::
    807 GenerateRepeatedDataSizeCode(io::Printer* printer) const {
    808   // Creates a variable dataSize and puts the serialized size in there.
    809   // If the element type is a Java reference type, also generates
    810   // dataCount which stores the number of non-null elements in the field.
    811   if (IsReferenceType(GetJavaType(descriptor_))) {
    812     printer->Print(variables_,
    813       "int dataCount = 0;\n"
    814       "int dataSize = 0;\n"
    815       "for (int i = 0; i < this.$name$.length; i++) {\n"
    816       "  $type$ element = this.$name$[i];\n"
    817       "  if (element != null) {\n"
    818       "    dataCount++;\n"
    819       "    dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    820       "        .compute$capitalized_type$SizeNoTag(element);\n"
    821       "  }\n"
    822       "}\n");
    823   } else if (FixedSize(descriptor_->type()) == -1) {
    824     printer->Print(variables_,
    825       "int dataSize = 0;\n"
    826       "for (int i = 0; i < this.$name$.length; i++) {\n"
    827       "  $type$ element = this.$name$[i];\n"
    828       "  dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    829       "      .compute$capitalized_type$SizeNoTag(element);\n"
    830       "}\n");
    831   } else {
    832     printer->Print(variables_,
    833       "int dataSize = $fixed_size$ * this.$name$.length;\n");
    834   }
    835 }
    836 
    837 void RepeatedPrimitiveFieldGenerator::
    838 GenerateSerializationCode(io::Printer* printer) const {
    839   printer->Print(variables_,
    840     "if (this.$name$ != null && this.$name$.length > 0) {\n");
    841   printer->Indent();
    842 
    843   if (descriptor_->is_packable() && descriptor_->options().packed()) {
    844     GenerateRepeatedDataSizeCode(printer);
    845     printer->Print(variables_,
    846       "output.writeRawVarint32($tag$);\n"
    847       "output.writeRawVarint32(dataSize);\n"
    848       "for (int i = 0; i < this.$name$.length; i++) {\n"
    849       "  output.write$capitalized_type$NoTag(this.$name$[i]);\n"
    850       "}\n");
    851   } else if (IsReferenceType(GetJavaType(descriptor_))) {
    852     printer->Print(variables_,
    853       "for (int i = 0; i < this.$name$.length; i++) {\n"
    854       "  $type$ element = this.$name$[i];\n"
    855       "  if (element != null) {\n"
    856       "    output.write$capitalized_type$($number$, element);\n"
    857       "  }\n"
    858       "}\n");
    859   } else {
    860     printer->Print(variables_,
    861       "for (int i = 0; i < this.$name$.length; i++) {\n"
    862       "  output.write$capitalized_type$($number$, this.$name$[i]);\n"
    863       "}\n");
    864   }
    865 
    866   printer->Outdent();
    867   printer->Print("}\n");
    868 }
    869 
    870 void RepeatedPrimitiveFieldGenerator::
    871 GenerateSerializedSizeCode(io::Printer* printer) const {
    872   printer->Print(variables_,
    873     "if (this.$name$ != null && this.$name$.length > 0) {\n");
    874   printer->Indent();
    875 
    876   GenerateRepeatedDataSizeCode(printer);
    877 
    878   printer->Print(
    879     "size += dataSize;\n");
    880   if (descriptor_->is_packable() && descriptor_->options().packed()) {
    881     printer->Print(variables_,
    882       "size += $tag_size$;\n"
    883       "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
    884       "    .computeRawVarint32Size(dataSize);\n");
    885   } else if (IsReferenceType(GetJavaType(descriptor_))) {
    886     printer->Print(variables_,
    887       "size += $tag_size$ * dataCount;\n");
    888   } else {
    889     printer->Print(variables_,
    890       "size += $tag_size$ * this.$name$.length;\n");
    891   }
    892 
    893   printer->Outdent();
    894 
    895   printer->Print(
    896     "}\n");
    897 }
    898 
    899 void RepeatedPrimitiveFieldGenerator::
    900 GenerateEqualsCode(io::Printer* printer) const {
    901   printer->Print(variables_,
    902     "if (!com.google.protobuf.nano.InternalNano.equals(\n"
    903     "    this.$name$, other.$name$)) {\n"
    904     "  return false;\n"
    905     "}\n");
    906 }
    907 
    908 void RepeatedPrimitiveFieldGenerator::
    909 GenerateHashCodeCode(io::Printer* printer) const {
    910   printer->Print(variables_,
    911     "result = 31 * result\n"
    912     "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
    913 }
    914 
    915 }  // namespace javanano
    916 }  // namespace compiler
    917 }  // namespace protobuf
    918 }  // namespace google
    919