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
57bool 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
77bool 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
97const 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.
128int 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.
160bool 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
180bool 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
189void 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
258PrimitiveFieldGenerator::
259PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
260  : FieldGenerator(params), descriptor_(descriptor) {
261  SetPrimitiveVariables(descriptor, params, &variables_);
262}
263
264PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
265
266bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
267  return variables_.find("default_constant") != variables_.end();
268}
269
270void 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
277void PrimitiveFieldGenerator::
278GenerateMembers(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  JavaType java_type = GetJavaType(descriptor_);
292  if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
293    printer->Print(variables_,
294      "public $type$ $name$Buffer;\n"
295      "public int $name$Offset;\n"
296      "public int $name$Length;\n");
297  } else {
298    printer->Print(variables_,
299      "public $type$ $name$;\n");
300  }
301
302  if (params_.generate_has()) {
303    printer->Print(variables_,
304      "public boolean has$capitalized_name$;\n");
305  }
306}
307
308void PrimitiveFieldGenerator::
309GenerateClearCode(io::Printer* printer) const {
310  JavaType java_type = GetJavaType(descriptor_);
311  if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
312    printer->Print(variables_,
313      "$name$Buffer = $default_copy_if_needed$;\n"
314      "$name$Offset = -1;\n"
315      "$name$Length = 0;\n");
316  } else {
317    printer->Print(variables_,
318      "$name$ = $default_copy_if_needed$;\n");
319  }
320
321  if (params_.generate_has()) {
322    printer->Print(variables_,
323      "has$capitalized_name$ = false;\n");
324  }
325}
326
327void PrimitiveFieldGenerator::
328GenerateMergingCode(io::Printer* printer) const {
329  JavaType java_type = GetJavaType(descriptor_);
330  if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
331    printer->Print(variables_,
332      "this.$name$Buffer = input.getBuffer();\n"
333      "this.$name$Length = input.readRawVarint32();\n"
334      "this.$name$Offset = input.getAbsolutePosition();\n"
335      "input.skipRawBytes(this.$name$Length);\n");
336  } else {
337    printer->Print(variables_,
338      "this.$name$ = input.read$capitalized_type$();\n");
339  }
340
341  if (params_.generate_has()) {
342    printer->Print(variables_,
343      "has$capitalized_name$ = true;\n");
344  }
345}
346
347void PrimitiveFieldGenerator::
348GenerateSerializationConditional(io::Printer* printer) const {
349  if (params_.use_reference_types_for_primitives()) {
350    // For reference type mode, serialize based on equality
351    // to null.
352    printer->Print(variables_,
353      "if (this.$name$ != null) {\n");
354    return;
355  }
356  if (params_.generate_has()) {
357    printer->Print(variables_,
358      "if (has$capitalized_name$ || ");
359  } else {
360    printer->Print(variables_,
361      "if (");
362  }
363  JavaType java_type = GetJavaType(descriptor_);
364  if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
365    printer->Print(variables_,
366      "this.$name$Offset != -1) {\n");
367  } else if (IsArrayType(java_type)) {
368    printer->Print(variables_,
369      "!java.util.Arrays.equals(this.$name$, $default$)) {\n");
370  } else if (IsReferenceType(java_type)) {
371    printer->Print(variables_,
372      "!this.$name$.equals($default$)) {\n");
373  } else if (java_type == JAVATYPE_FLOAT) {
374    printer->Print(variables_,
375      "java.lang.Float.floatToIntBits(this.$name$)\n"
376      "    != java.lang.Float.floatToIntBits($default$)) {\n");
377  } else if (java_type == JAVATYPE_DOUBLE) {
378    printer->Print(variables_,
379      "java.lang.Double.doubleToLongBits(this.$name$)\n"
380      "    != java.lang.Double.doubleToLongBits($default$)) {\n");
381  } else {
382    printer->Print(variables_,
383      "this.$name$ != $default$) {\n");
384  }
385}
386
387void PrimitiveFieldGenerator::
388GenerateSerializationCode(io::Printer* printer) const {
389  if (descriptor_->is_required() && !params_.generate_has()) {
390    // Always serialize a required field if we don't have the 'has' signal.
391    GenerateWriteCode(printer);
392  } else {
393    GenerateSerializationConditional(printer);
394    printer->Indent();
395    GenerateWriteCode(printer);
396    printer->Outdent();
397    printer->Print("}\n");
398  }
399}
400
401void PrimitiveFieldGenerator::
402GenerateWriteCode(io::Printer* printer) const {
403  JavaType java_type = GetJavaType(descriptor_);
404  if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
405    printer->Print(variables_,
406      "output.write$capitalized_type$($number$, this.$name$Buffer,\n"
407      "    this.$name$Offset, this.$name$Length);\n");
408  } else {
409    printer->Print(variables_,
410      "output.write$capitalized_type$($number$, this.$name$);\n");
411  }
412}
413
414void PrimitiveFieldGenerator::
415GenerateSerializedSizeCode(io::Printer* printer) const {
416  if (descriptor_->is_required() && !params_.generate_has()) {
417    GenerateComputeSizeCode(printer);
418  } else {
419    GenerateSerializationConditional(printer);
420    printer->Indent();
421    GenerateComputeSizeCode(printer);
422    printer->Outdent();
423    printer->Print("}\n");
424  }
425}
426
427void PrimitiveFieldGenerator::
428GenerateComputeSizeCode(io::Printer* printer) const {
429  JavaType java_type = GetJavaType(descriptor_);
430  if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
431    printer->Print(variables_,
432      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
433      "    .compute$capitalized_type$Size($number$, this.$name$Length);\n");
434  } else {
435    printer->Print(variables_,
436      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
437      "    .compute$capitalized_type$Size($number$, this.$name$);\n");
438  }
439}
440
441void RepeatedPrimitiveFieldGenerator::
442GenerateFixClonedCode(io::Printer* printer) const {
443  printer->Print(variables_,
444    "if (this.$name$ != null && this.$name$.length > 0) {\n"
445    "  cloned.$name$ = this.$name$.clone();\n"
446    "}\n");
447}
448
449void PrimitiveFieldGenerator::
450GenerateEqualsCode(io::Printer* printer) const {
451  // We define equality as serialized form equality. If generate_has(),
452  // then if the field value equals the default value in both messages,
453  // but one's 'has' field is set and the other's is not, the serialized
454  // forms are different and we should return false.
455  JavaType java_type = GetJavaType(descriptor_);
456  if (java_type == JAVATYPE_BYTES) {
457    printer->Print(variables_,
458      "if (!java.util.Arrays.equals(this.$name$, other.$name$)");
459    if (params_.generate_has()) {
460      printer->Print(variables_,
461        "\n"
462        "    || (java.util.Arrays.equals(this.$name$, $default$)\n"
463        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
464    }
465    printer->Print(") {\n"
466      "  return false;\n"
467      "}\n");
468  } else if (java_type == JAVATYPE_STRING
469      || params_.use_reference_types_for_primitives()) {
470    printer->Print(variables_,
471      "if (this.$name$ == null) {\n"
472      "  if (other.$name$ != null) {\n"
473      "    return false;\n"
474      "  }\n"
475      "} else if (!this.$name$.equals(other.$name$)");
476    if (params_.generate_has()) {
477      printer->Print(variables_,
478        "\n"
479        "    || (this.$name$.equals($default$)\n"
480        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
481    }
482    printer->Print(") {\n"
483      "  return false;\n"
484      "}\n");
485  } else if (java_type == JAVATYPE_FLOAT) {
486    printer->Print(variables_,
487      "{\n"
488      "  int bits = java.lang.Float.floatToIntBits(this.$name$);\n"
489      "  if (bits != java.lang.Float.floatToIntBits(other.$name$)");
490    if (params_.generate_has()) {
491      printer->Print(variables_,
492        "\n"
493        "      || (bits == java.lang.Float.floatToIntBits($default$)\n"
494        "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
495    }
496    printer->Print(") {\n"
497      "    return false;\n"
498      "  }\n"
499      "}\n");
500  } else if (java_type == JAVATYPE_DOUBLE) {
501    printer->Print(variables_,
502      "{\n"
503      "  long bits = java.lang.Double.doubleToLongBits(this.$name$);\n"
504      "  if (bits != java.lang.Double.doubleToLongBits(other.$name$)");
505    if (params_.generate_has()) {
506      printer->Print(variables_,
507        "\n"
508        "      || (bits == java.lang.Double.doubleToLongBits($default$)\n"
509        "          && this.has$capitalized_name$ != other.has$capitalized_name$)");
510    }
511    printer->Print(") {\n"
512      "    return false;\n"
513      "  }\n"
514      "}\n");
515  } else {
516    printer->Print(variables_,
517      "if (this.$name$ != other.$name$");
518    if (params_.generate_has()) {
519      printer->Print(variables_,
520        "\n"
521        "    || (this.$name$ == $default$\n"
522        "        && this.has$capitalized_name$ != other.has$capitalized_name$)");
523    }
524    printer->Print(") {\n"
525      "  return false;\n"
526      "}\n");
527  }
528}
529
530void PrimitiveFieldGenerator::
531GenerateHashCodeCode(io::Printer* printer) const {
532  JavaType java_type = GetJavaType(descriptor_);
533  if (java_type == JAVATYPE_BYTES) {
534    printer->Print(variables_,
535      "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n");
536  } else if (java_type == JAVATYPE_STRING
537      || params_.use_reference_types_for_primitives()) {
538    printer->Print(variables_,
539      "result = 31 * result\n"
540      "    + (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
541  } else {
542    switch (java_type) {
543      // For all Java primitive types below, the hash codes match the
544      // results of BoxedType.valueOf(primitiveValue).hashCode().
545      case JAVATYPE_INT:
546        printer->Print(variables_,
547          "result = 31 * result + this.$name$;\n");
548        break;
549      case JAVATYPE_LONG:
550        printer->Print(variables_,
551          "result = 31 * result\n"
552          "    + (int) (this.$name$ ^ (this.$name$ >>> 32));\n");
553        break;
554      case JAVATYPE_FLOAT:
555        printer->Print(variables_,
556          "result = 31 * result\n"
557          "    + java.lang.Float.floatToIntBits(this.$name$);\n");
558        break;
559      case JAVATYPE_DOUBLE:
560        printer->Print(variables_,
561          "{\n"
562          "  long v = java.lang.Double.doubleToLongBits(this.$name$);\n"
563          "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
564          "}\n");
565        break;
566      case JAVATYPE_BOOLEAN:
567        printer->Print(variables_,
568          "result = 31 * result + (this.$name$ ? 1231 : 1237);\n");
569        break;
570      default:
571        GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
572        break;
573    }
574  }
575}
576
577// ===================================================================
578
579AccessorPrimitiveFieldGenerator::
580AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
581     const Params& params, int has_bit_index)
582  : FieldGenerator(params), descriptor_(descriptor) {
583  SetPrimitiveVariables(descriptor, params, &variables_);
584  SetBitOperationVariables("has", has_bit_index, &variables_);
585}
586
587AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
588
589bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
590  return variables_.find("default_constant") != variables_.end();
591}
592
593void AccessorPrimitiveFieldGenerator::
594GenerateInitSavedDefaultCode(io::Printer* printer) const {
595  if (variables_.find("default_constant") != variables_.end()) {
596    printer->Print(variables_,
597      "$default_constant$ = $default_constant_value$;\n");
598  }
599}
600
601void AccessorPrimitiveFieldGenerator::
602GenerateMembers(io::Printer* printer, bool lazy_init) const {
603  if (variables_.find("default_constant") != variables_.end()) {
604    // Those primitive types that need a saved default.
605    if (lazy_init) {
606      printer->Print(variables_,
607        "private static $type$ $default_constant$;\n");
608    } else {
609      printer->Print(variables_,
610        "private static final $type$ $default_constant$ =\n"
611        "    $default_constant_value$;\n");
612    }
613  }
614  printer->Print(variables_,
615    "private $type$ $name$_;\n"
616    "public $type$ get$capitalized_name$() {\n"
617    "  return $name$_;\n"
618    "}\n"
619    "public $message_name$ set$capitalized_name$($type$ value) {\n");
620  if (IsReferenceType(GetJavaType(descriptor_))) {
621    printer->Print(variables_,
622      "  if (value == null) {\n"
623      "    throw new java.lang.NullPointerException();\n"
624      "  }\n");
625  }
626  printer->Print(variables_,
627    "  $name$_ = value;\n"
628    "  $set_has$;\n"
629    "  return this;\n"
630    "}\n"
631    "public boolean has$capitalized_name$() {\n"
632    "  return $get_has$;\n"
633    "}\n"
634    "public $message_name$ clear$capitalized_name$() {\n"
635    "  $name$_ = $default_copy_if_needed$;\n"
636    "  $clear_has$;\n"
637    "  return this;\n"
638    "}\n");
639}
640
641void AccessorPrimitiveFieldGenerator::
642GenerateClearCode(io::Printer* printer) const {
643
644  printer->Print(variables_,
645    "$name$_ = $default_copy_if_needed$;\n");
646}
647
648void AccessorPrimitiveFieldGenerator::
649GenerateMergingCode(io::Printer* printer) const {
650  printer->Print(variables_,
651    "$name$_ = input.read$capitalized_type$();\n"
652    "$set_has$;\n");
653}
654
655void AccessorPrimitiveFieldGenerator::
656GenerateSerializationCode(io::Printer* printer) const {
657  printer->Print(variables_,
658    "if ($get_has$) {\n"
659    "  output.write$capitalized_type$($number$, $name$_);\n"
660    "}\n");
661}
662
663void AccessorPrimitiveFieldGenerator::
664GenerateSerializedSizeCode(io::Printer* printer) const {
665  printer->Print(variables_,
666    "if ($get_has$) {\n"
667    "  size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
668    "      .compute$capitalized_type$Size($number$, $name$_);\n"
669    "}\n");
670}
671
672void AccessorPrimitiveFieldGenerator::
673GenerateEqualsCode(io::Printer* printer) const {
674  switch (GetJavaType(descriptor_)) {
675    // For all Java primitive types below, the equality checks match the
676    // results of BoxedType.valueOf(primitiveValue).equals(otherValue).
677    case JAVATYPE_FLOAT:
678      printer->Print(variables_,
679        "if ($different_has$\n"
680        "    || java.lang.Float.floatToIntBits($name$_)\n"
681        "        != java.lang.Float.floatToIntBits(other.$name$_)) {\n"
682        "  return false;\n"
683        "}\n");
684      break;
685    case JAVATYPE_DOUBLE:
686      printer->Print(variables_,
687        "if ($different_has$\n"
688        "    || java.lang.Double.doubleToLongBits($name$_)\n"
689        "        != java.lang.Double.doubleToLongBits(other.$name$_)) {\n"
690        "  return false;\n"
691        "}\n");
692      break;
693    case JAVATYPE_INT:
694    case JAVATYPE_LONG:
695    case JAVATYPE_BOOLEAN:
696      printer->Print(variables_,
697        "if ($different_has$\n"
698        "    || $name$_ != other.$name$_) {\n"
699        "  return false;\n"
700        "}\n");
701      break;
702    case JAVATYPE_STRING:
703      // Accessor style would guarantee $name$_ non-null
704      printer->Print(variables_,
705        "if ($different_has$\n"
706        "    || !$name$_.equals(other.$name$_)) {\n"
707        "  return false;\n"
708        "}\n");
709      break;
710    case JAVATYPE_BYTES:
711      // Accessor style would guarantee $name$_ non-null
712      printer->Print(variables_,
713        "if ($different_has$\n"
714        "    || !java.util.Arrays.equals($name$_, other.$name$_)) {\n"
715        "  return false;\n"
716        "}\n");
717      break;
718    default:
719      GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
720      break;
721  }
722}
723
724void AccessorPrimitiveFieldGenerator::
725GenerateHashCodeCode(io::Printer* printer) const {
726  switch (GetJavaType(descriptor_)) {
727    // For all Java primitive types below, the hash codes match the
728    // results of BoxedType.valueOf(primitiveValue).hashCode().
729    case JAVATYPE_INT:
730      printer->Print(variables_,
731        "result = 31 * result + $name$_;\n");
732      break;
733    case JAVATYPE_LONG:
734      printer->Print(variables_,
735        "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n");
736      break;
737    case JAVATYPE_FLOAT:
738      printer->Print(variables_,
739        "result = 31 * result +\n"
740        "    java.lang.Float.floatToIntBits($name$_);\n");
741      break;
742    case JAVATYPE_DOUBLE:
743      printer->Print(variables_,
744        "{\n"
745        "  long v = java.lang.Double.doubleToLongBits($name$_);\n"
746        "  result = 31 * result + (int) (v ^ (v >>> 32));\n"
747        "}\n");
748      break;
749    case JAVATYPE_BOOLEAN:
750      printer->Print(variables_,
751        "result = 31 * result + ($name$_ ? 1231 : 1237);\n");
752      break;
753    case JAVATYPE_STRING:
754      // Accessor style would guarantee $name$_ non-null
755      printer->Print(variables_,
756        "result = 31 * result + $name$_.hashCode();\n");
757      break;
758    case JAVATYPE_BYTES:
759      // Accessor style would guarantee $name$_ non-null
760      printer->Print(variables_,
761        "result = 31 * result + java.util.Arrays.hashCode($name$_);\n");
762      break;
763    default:
764      GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
765      break;
766  }
767}
768
769// ===================================================================
770
771RepeatedPrimitiveFieldGenerator::
772RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
773  : FieldGenerator(params), descriptor_(descriptor) {
774  SetPrimitiveVariables(descriptor, params, &variables_);
775}
776
777RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
778
779void RepeatedPrimitiveFieldGenerator::
780GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
781  printer->Print(variables_,
782    "public $type$[] $name$;\n");
783}
784
785void RepeatedPrimitiveFieldGenerator::
786GenerateClearCode(io::Printer* printer) const {
787  printer->Print(variables_,
788    "$name$ = $default$;\n");
789}
790
791void RepeatedPrimitiveFieldGenerator::
792GenerateMergingCode(io::Printer* printer) const {
793  // First, figure out the length of the array, then parse.
794  printer->Print(variables_,
795    "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
796    "    .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
797    "int i = this.$name$ == null ? 0 : this.$name$.length;\n");
798
799  if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
800    printer->Print(variables_,
801      "byte[][] newArray = new byte[i + arrayLength][];\n");
802  } else {
803    printer->Print(variables_,
804      "$type$[] newArray = new $type$[i + arrayLength];\n");
805  }
806  printer->Print(variables_,
807    "if (i != 0) {\n"
808    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
809    "}\n"
810    "for (; i < newArray.length - 1; i++) {\n"
811    "  newArray[i] = input.read$capitalized_type$();\n"
812    "  input.readTag();\n"
813    "}\n"
814    "// Last one without readTag.\n"
815    "newArray[i] = input.read$capitalized_type$();\n"
816    "this.$name$ = newArray;\n");
817}
818
819void RepeatedPrimitiveFieldGenerator::
820GenerateMergingCodeFromPacked(io::Printer* printer) const {
821  printer->Print(
822    "int length = input.readRawVarint32();\n"
823    "int limit = input.pushLimit(length);\n");
824
825  // If we know the elements will all be of the same size, the arrayLength
826  // can be calculated much more easily. However, FixedSize() returns 1 for
827  // repeated bool fields, which are guaranteed to have the fixed size of
828  // 1 byte per value only if we control the output. On the wire they can
829  // legally appear as variable-size integers, so we need to use the slow
830  // way for repeated bool fields.
831  if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
832      || FixedSize(descriptor_->type()) == -1) {
833    printer->Print(variables_,
834      "// First pass to compute array length.\n"
835      "int arrayLength = 0;\n"
836      "int startPos = input.getPosition();\n"
837      "while (input.getBytesUntilLimit() > 0) {\n"
838      "  input.read$capitalized_type$();\n"
839      "  arrayLength++;\n"
840      "}\n"
841      "input.rewindToPosition(startPos);\n");
842  } else {
843    printer->Print(variables_,
844      "int arrayLength = length / $fixed_size$;\n");
845  }
846
847  printer->Print(variables_,
848    "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
849    "$type$[] newArray = new $type$[i + arrayLength];\n"
850    "if (i != 0) {\n"
851    "  java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
852    "}\n"
853    "for (; i < newArray.length; i++) {\n"
854    "  newArray[i] = input.read$capitalized_type$();\n"
855    "}\n"
856    "this.$name$ = newArray;\n"
857    "input.popLimit(limit);\n");
858}
859
860void RepeatedPrimitiveFieldGenerator::
861GenerateRepeatedDataSizeCode(io::Printer* printer) const {
862  // Creates a variable dataSize and puts the serialized size in there.
863  // If the element type is a Java reference type, also generates
864  // dataCount which stores the number of non-null elements in the field.
865  if (IsReferenceType(GetJavaType(descriptor_))) {
866    printer->Print(variables_,
867      "int dataCount = 0;\n"
868      "int dataSize = 0;\n"
869      "for (int i = 0; i < this.$name$.length; i++) {\n"
870      "  $type$ element = this.$name$[i];\n"
871      "  if (element != null) {\n"
872      "    dataCount++;\n"
873      "    dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
874      "        .compute$capitalized_type$SizeNoTag(element);\n"
875      "  }\n"
876      "}\n");
877  } else if (FixedSize(descriptor_->type()) == -1) {
878    printer->Print(variables_,
879      "int dataSize = 0;\n"
880      "for (int i = 0; i < this.$name$.length; i++) {\n"
881      "  $type$ element = this.$name$[i];\n"
882      "  dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
883      "      .compute$capitalized_type$SizeNoTag(element);\n"
884      "}\n");
885  } else {
886    printer->Print(variables_,
887      "int dataSize = $fixed_size$ * this.$name$.length;\n");
888  }
889}
890
891void RepeatedPrimitiveFieldGenerator::
892GenerateSerializationCode(io::Printer* printer) const {
893  printer->Print(variables_,
894    "if (this.$name$ != null && this.$name$.length > 0) {\n");
895  printer->Indent();
896
897  if (descriptor_->is_packable() && descriptor_->options().packed()) {
898    GenerateRepeatedDataSizeCode(printer);
899    printer->Print(variables_,
900      "output.writeRawVarint32($tag$);\n"
901      "output.writeRawVarint32(dataSize);\n"
902      "for (int i = 0; i < this.$name$.length; i++) {\n"
903      "  output.write$capitalized_type$NoTag(this.$name$[i]);\n"
904      "}\n");
905  } else if (IsReferenceType(GetJavaType(descriptor_))) {
906    printer->Print(variables_,
907      "for (int i = 0; i < this.$name$.length; i++) {\n"
908      "  $type$ element = this.$name$[i];\n"
909      "  if (element != null) {\n"
910      "    output.write$capitalized_type$($number$, element);\n"
911      "  }\n"
912      "}\n");
913  } else {
914    printer->Print(variables_,
915      "for (int i = 0; i < this.$name$.length; i++) {\n"
916      "  output.write$capitalized_type$($number$, this.$name$[i]);\n"
917      "}\n");
918  }
919
920  printer->Outdent();
921  printer->Print("}\n");
922}
923
924void RepeatedPrimitiveFieldGenerator::
925GenerateSerializedSizeCode(io::Printer* printer) const {
926  printer->Print(variables_,
927    "if (this.$name$ != null && this.$name$.length > 0) {\n");
928  printer->Indent();
929
930  GenerateRepeatedDataSizeCode(printer);
931
932  printer->Print(
933    "size += dataSize;\n");
934  if (descriptor_->is_packable() && descriptor_->options().packed()) {
935    printer->Print(variables_,
936      "size += $tag_size$;\n"
937      "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
938      "    .computeRawVarint32Size(dataSize);\n");
939  } else if (IsReferenceType(GetJavaType(descriptor_))) {
940    printer->Print(variables_,
941      "size += $tag_size$ * dataCount;\n");
942  } else {
943    printer->Print(variables_,
944      "size += $tag_size$ * this.$name$.length;\n");
945  }
946
947  printer->Outdent();
948
949  printer->Print(
950    "}\n");
951}
952
953void RepeatedPrimitiveFieldGenerator::
954GenerateEqualsCode(io::Printer* printer) const {
955  printer->Print(variables_,
956    "if (!com.google.protobuf.nano.InternalNano.equals(\n"
957    "    this.$name$, other.$name$)) {\n"
958    "  return false;\n"
959    "}\n");
960}
961
962void RepeatedPrimitiveFieldGenerator::
963GenerateHashCodeCode(io::Printer* printer) const {
964  printer->Print(variables_,
965    "result = 31 * result\n"
966    "    + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
967}
968
969}  // namespace javanano
970}  // namespace compiler
971}  // namespace protobuf
972}  // namespace google
973