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
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
IsReferenceType(JavaType type)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
IsArrayType(JavaType type)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
GetCapitalizedType(const FieldDescriptor * field)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.
FixedSize(FieldDescriptor::Type type)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.
IsVariableLenType(JavaType type)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
AllAscii(const string & text)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
SetPrimitiveVariables(const FieldDescriptor * descriptor,const Params params,map<string,string> * variables)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::
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Params & params)259 PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
260 : FieldGenerator(params), descriptor_(descriptor) {
261 SetPrimitiveVariables(descriptor, params, &variables_);
262 }
263
~PrimitiveFieldGenerator()264 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
265
SavedDefaultNeeded() const266 bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
267 return variables_.find("default_constant") != variables_.end();
268 }
269
GenerateInitSavedDefaultCode(io::Printer * printer) const270 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::
GenerateMembers(io::Printer * printer,bool lazy_init) const278 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 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
308 void PrimitiveFieldGenerator::
GenerateClearCode(io::Printer * printer) const309 GenerateClearCode(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
327 void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const328 GenerateMergingCode(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
347 void PrimitiveFieldGenerator::
GenerateSerializationConditional(io::Printer * printer) const348 GenerateSerializationConditional(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
387 void PrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const388 GenerateSerializationCode(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
401 void PrimitiveFieldGenerator::
GenerateWriteCode(io::Printer * printer) const402 GenerateWriteCode(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
414 void PrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const415 GenerateSerializedSizeCode(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
427 void PrimitiveFieldGenerator::
GenerateComputeSizeCode(io::Printer * printer) const428 GenerateComputeSizeCode(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
441 void RepeatedPrimitiveFieldGenerator::
GenerateFixClonedCode(io::Printer * printer) const442 GenerateFixClonedCode(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
449 void PrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const450 GenerateEqualsCode(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
530 void PrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer * printer) const531 GenerateHashCodeCode(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
579 AccessorPrimitiveFieldGenerator::
AccessorPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Params & params,int has_bit_index)580 AccessorPrimitiveFieldGenerator(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
~AccessorPrimitiveFieldGenerator()587 AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
588
SavedDefaultNeeded() const589 bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
590 return variables_.find("default_constant") != variables_.end();
591 }
592
593 void AccessorPrimitiveFieldGenerator::
GenerateInitSavedDefaultCode(io::Printer * printer) const594 GenerateInitSavedDefaultCode(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
601 void AccessorPrimitiveFieldGenerator::
GenerateMembers(io::Printer * printer,bool lazy_init) const602 GenerateMembers(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
641 void AccessorPrimitiveFieldGenerator::
GenerateClearCode(io::Printer * printer) const642 GenerateClearCode(io::Printer* printer) const {
643
644 printer->Print(variables_,
645 "$name$_ = $default_copy_if_needed$;\n");
646 }
647
648 void AccessorPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const649 GenerateMergingCode(io::Printer* printer) const {
650 printer->Print(variables_,
651 "$name$_ = input.read$capitalized_type$();\n"
652 "$set_has$;\n");
653 }
654
655 void AccessorPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const656 GenerateSerializationCode(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
663 void AccessorPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const664 GenerateSerializedSizeCode(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
672 void AccessorPrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const673 GenerateEqualsCode(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
724 void AccessorPrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer * printer) const725 GenerateHashCodeCode(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
771 RepeatedPrimitiveFieldGenerator::
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Params & params)772 RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
773 : FieldGenerator(params), descriptor_(descriptor) {
774 SetPrimitiveVariables(descriptor, params, &variables_);
775 }
776
~RepeatedPrimitiveFieldGenerator()777 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
778
779 void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer * printer,bool) const780 GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
781 printer->Print(variables_,
782 "public $type$[] $name$;\n");
783 }
784
785 void RepeatedPrimitiveFieldGenerator::
GenerateClearCode(io::Printer * printer) const786 GenerateClearCode(io::Printer* printer) const {
787 printer->Print(variables_,
788 "$name$ = $default$;\n");
789 }
790
791 void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const792 GenerateMergingCode(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
819 void RepeatedPrimitiveFieldGenerator::
GenerateMergingCodeFromPacked(io::Printer * printer) const820 GenerateMergingCodeFromPacked(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
860 void RepeatedPrimitiveFieldGenerator::
GenerateRepeatedDataSizeCode(io::Printer * printer) const861 GenerateRepeatedDataSizeCode(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
891 void RepeatedPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const892 GenerateSerializationCode(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
924 void RepeatedPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const925 GenerateSerializedSizeCode(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
953 void RepeatedPrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const954 GenerateEqualsCode(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
962 void RepeatedPrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer * printer) const963 GenerateHashCodeCode(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