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