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
AllAscii(const string & text)158 bool AllAscii(const string& text) {
159 for (int i = 0; i < text.size(); i++) {
160 if ((text[i] & 0x80) != 0) {
161 return false;
162 }
163 }
164 return true;
165 }
166
167
SetPrimitiveVariables(const FieldDescriptor * descriptor,const Params params,map<string,string> * variables)168 void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
169 map<string, string>* variables) {
170 (*variables)["name"] =
171 RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
172 (*variables)["capitalized_name"] =
173 RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
174 (*variables)["number"] = SimpleItoa(descriptor->number());
175 if (params.use_reference_types_for_primitives()
176 && !descriptor->is_repeated()) {
177 (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
178 } else {
179 (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
180 }
181 // Deals with defaults. For C++-string types (string and bytes),
182 // we might need to have the generated code do the unicode decoding
183 // (see comments in InternalNano.java for gory details.). We would
184 // like to do this once into a static field and re-use that from
185 // then on.
186 if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
187 !descriptor->default_value_string().empty() &&
188 !params.use_reference_types_for_primitives()) {
189 if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
190 (*variables)["default"] = DefaultValue(params, descriptor);
191 (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
192 (*variables)["default_constant_value"] = strings::Substitute(
193 "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
194 CEscape(descriptor->default_value_string()));
195 (*variables)["default_copy_if_needed"] =
196 (*variables)["default"] + ".clone()";
197 } else if (AllAscii(descriptor->default_value_string())) {
198 // All chars are ASCII. In this case directly referencing a
199 // CEscape()'d string literal works fine.
200 (*variables)["default"] =
201 "\"" + CEscape(descriptor->default_value_string()) + "\"";
202 (*variables)["default_copy_if_needed"] = (*variables)["default"];
203 } else {
204 // Strings where some chars are non-ASCII. We need to save the
205 // default value.
206 (*variables)["default"] = DefaultValue(params, descriptor);
207 (*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
208 (*variables)["default_constant_value"] = strings::Substitute(
209 "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
210 CEscape(descriptor->default_value_string()));
211 (*variables)["default_copy_if_needed"] = (*variables)["default"];
212 }
213 } else {
214 // Non-string, non-bytes field. Defaults are literals.
215 (*variables)["default"] = DefaultValue(params, descriptor);
216 (*variables)["default_copy_if_needed"] = (*variables)["default"];
217 }
218 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
219 (*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
220 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
221 (*variables)["tag_size"] = SimpleItoa(
222 WireFormat::TagSize(descriptor->number(), descriptor->type()));
223 (*variables)["non_packed_tag"] = SimpleItoa(
224 internal::WireFormatLite::MakeTag(descriptor->number(),
225 internal::WireFormat::WireTypeForFieldType(descriptor->type())));
226 int fixed_size = FixedSize(descriptor->type());
227 if (fixed_size != -1) {
228 (*variables)["fixed_size"] = SimpleItoa(fixed_size);
229 }
230 (*variables)["message_name"] = descriptor->containing_type()->name();
231 (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor);
232 }
233 } // namespace
234
235 // ===================================================================
236
237 PrimitiveFieldGenerator::
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Params & params)238 PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
239 : FieldGenerator(params), descriptor_(descriptor) {
240 SetPrimitiveVariables(descriptor, params, &variables_);
241 }
242
~PrimitiveFieldGenerator()243 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
244
SavedDefaultNeeded() const245 bool PrimitiveFieldGenerator::SavedDefaultNeeded() const {
246 return variables_.find("default_constant") != variables_.end();
247 }
248
GenerateInitSavedDefaultCode(io::Printer * printer) const249 void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
250 if (variables_.find("default_constant") != variables_.end()) {
251 printer->Print(variables_,
252 "$default_constant$ = $default_constant_value$;\n");
253 }
254 }
255
256 void PrimitiveFieldGenerator::
GenerateMembers(io::Printer * printer,bool lazy_init) const257 GenerateMembers(io::Printer* printer, bool lazy_init) const {
258 if (variables_.find("default_constant") != variables_.end()) {
259 // Those primitive types that need a saved default.
260 if (lazy_init) {
261 printer->Print(variables_,
262 "private static $type$ $default_constant$;\n");
263 } else {
264 printer->Print(variables_,
265 "private static final $type$ $default_constant$ =\n"
266 " $default_constant_value$;\n");
267 }
268 }
269
270 JavaType java_type = GetJavaType(descriptor_);
271 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
272 printer->Print(variables_,
273 "public $type$ $name$Buffer;\n"
274 "public int $name$Offset;\n"
275 "public int $name$Length;\n");
276 } else {
277 printer->Print(variables_,
278 "public $type$ $name$;\n");
279 }
280
281 if (params_.generate_has()) {
282 printer->Print(variables_,
283 "public boolean has$capitalized_name$;\n");
284 }
285 }
286
287 void PrimitiveFieldGenerator::
GenerateClearCode(io::Printer * printer) const288 GenerateClearCode(io::Printer* printer) const {
289 JavaType java_type = GetJavaType(descriptor_);
290 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
291 printer->Print(variables_,
292 "$name$Buffer = $default_copy_if_needed$;\n"
293 "$name$Offset = -1;\n"
294 "$name$Length = 0;\n");
295 } else {
296 printer->Print(variables_,
297 "$name$ = $default_copy_if_needed$;\n");
298 }
299
300 if (params_.generate_has()) {
301 printer->Print(variables_,
302 "has$capitalized_name$ = false;\n");
303 }
304 }
305
306 void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const307 GenerateMergingCode(io::Printer* printer) const {
308 JavaType java_type = GetJavaType(descriptor_);
309 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
310 printer->Print(variables_,
311 "this.$name$Buffer = input.getBuffer();\n"
312 "this.$name$Length = input.readRawVarint32();\n"
313 "this.$name$Offset = input.getAbsolutePosition();\n"
314 "input.skipRawBytes(this.$name$Length);\n");
315 } else {
316 printer->Print(variables_,
317 "this.$name$ = input.read$capitalized_type$();\n");
318 }
319
320 if (params_.generate_has()) {
321 printer->Print(variables_,
322 "has$capitalized_name$ = true;\n");
323 }
324 }
325
326 void PrimitiveFieldGenerator::
GenerateSerializationConditional(io::Printer * printer) const327 GenerateSerializationConditional(io::Printer* printer) const {
328 if (params_.use_reference_types_for_primitives()) {
329 // For reference type mode, serialize based on equality
330 // to null.
331 printer->Print(variables_,
332 "if (this.$name$ != null) {\n");
333 return;
334 }
335 if (params_.generate_has()) {
336 printer->Print(variables_,
337 "if (has$capitalized_name$ || ");
338 } else {
339 printer->Print(variables_,
340 "if (");
341 }
342 JavaType java_type = GetJavaType(descriptor_);
343 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
344 printer->Print(variables_,
345 "this.$name$Offset != -1) {\n");
346 } else if (IsArrayType(java_type)) {
347 printer->Print(variables_,
348 "!java.util.Arrays.equals(this.$name$, $default$)) {\n");
349 } else if (IsReferenceType(java_type)) {
350 printer->Print(variables_,
351 "!this.$name$.equals($default$)) {\n");
352 } else if (java_type == JAVATYPE_FLOAT) {
353 printer->Print(variables_,
354 "java.lang.Float.floatToIntBits(this.$name$)\n"
355 " != java.lang.Float.floatToIntBits($default$)) {\n");
356 } else if (java_type == JAVATYPE_DOUBLE) {
357 printer->Print(variables_,
358 "java.lang.Double.doubleToLongBits(this.$name$)\n"
359 " != java.lang.Double.doubleToLongBits($default$)) {\n");
360 } else {
361 printer->Print(variables_,
362 "this.$name$ != $default$) {\n");
363 }
364 }
365
366 void PrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const367 GenerateSerializationCode(io::Printer* printer) const {
368 if (descriptor_->is_required() && !params_.generate_has()) {
369 // Always serialize a required field if we don't have the 'has' signal.
370 GenerateWriteCode(printer);
371 } else {
372 GenerateSerializationConditional(printer);
373 printer->Indent();
374 GenerateWriteCode(printer);
375 printer->Outdent();
376 printer->Print("}\n");
377 }
378 }
379
380 void PrimitiveFieldGenerator::
GenerateWriteCode(io::Printer * printer) const381 GenerateWriteCode(io::Printer* printer) const {
382 JavaType java_type = GetJavaType(descriptor_);
383 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
384 printer->Print(variables_,
385 "output.write$capitalized_type$($number$, this.$name$Buffer,\n"
386 " this.$name$Offset, this.$name$Length);\n");
387 } else {
388 printer->Print(variables_,
389 "output.write$capitalized_type$($number$, this.$name$);\n");
390 }
391 }
392
393 void PrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const394 GenerateSerializedSizeCode(io::Printer* printer) const {
395 if (descriptor_->is_required() && !params_.generate_has()) {
396 GenerateComputeSizeCode(printer);
397 } else {
398 GenerateSerializationConditional(printer);
399 printer->Indent();
400 GenerateComputeSizeCode(printer);
401 printer->Outdent();
402 printer->Print("}\n");
403 }
404 }
405
406 void PrimitiveFieldGenerator::
GenerateComputeSizeCode(io::Printer * printer) const407 GenerateComputeSizeCode(io::Printer* printer) const {
408 JavaType java_type = GetJavaType(descriptor_);
409 if (java_type == JAVATYPE_BYTES && params_.bytes_offset_length()) {
410 printer->Print(variables_,
411 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
412 " .compute$capitalized_type$Size($number$, this.$name$Length);\n");
413 } else {
414 printer->Print(variables_,
415 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
416 " .compute$capitalized_type$Size($number$, this.$name$);\n");
417 }
418 }
419
420 void RepeatedPrimitiveFieldGenerator::
GenerateFixClonedCode(io::Printer * printer) const421 GenerateFixClonedCode(io::Printer* printer) const {
422 printer->Print(variables_,
423 "if (this.$name$ != null && this.$name$.length > 0) {\n"
424 " cloned.$name$ = this.$name$.clone();\n"
425 "}\n");
426 }
427
428 void PrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const429 GenerateEqualsCode(io::Printer* printer) const {
430 // We define equality as serialized form equality. If generate_has(),
431 // then if the field value equals the default value in both messages,
432 // but one's 'has' field is set and the other's is not, the serialized
433 // forms are different and we should return false.
434 JavaType java_type = GetJavaType(descriptor_);
435 if (java_type == JAVATYPE_BYTES) {
436 printer->Print(variables_,
437 "if (!java.util.Arrays.equals(this.$name$, other.$name$)");
438 if (params_.generate_has()) {
439 printer->Print(variables_,
440 "\n"
441 " || (java.util.Arrays.equals(this.$name$, $default$)\n"
442 " && this.has$capitalized_name$ != other.has$capitalized_name$)");
443 }
444 printer->Print(") {\n"
445 " return false;\n"
446 "}\n");
447 } else if (java_type == JAVATYPE_STRING
448 || params_.use_reference_types_for_primitives()) {
449 printer->Print(variables_,
450 "if (this.$name$ == null) {\n"
451 " if (other.$name$ != null) {\n"
452 " return false;\n"
453 " }\n"
454 "} else if (!this.$name$.equals(other.$name$)");
455 if (params_.generate_has()) {
456 printer->Print(variables_,
457 "\n"
458 " || (this.$name$.equals($default$)\n"
459 " && this.has$capitalized_name$ != other.has$capitalized_name$)");
460 }
461 printer->Print(") {\n"
462 " return false;\n"
463 "}\n");
464 } else if (java_type == JAVATYPE_FLOAT) {
465 printer->Print(variables_,
466 "{\n"
467 " int bits = java.lang.Float.floatToIntBits(this.$name$);\n"
468 " if (bits != java.lang.Float.floatToIntBits(other.$name$)");
469 if (params_.generate_has()) {
470 printer->Print(variables_,
471 "\n"
472 " || (bits == java.lang.Float.floatToIntBits($default$)\n"
473 " && this.has$capitalized_name$ != other.has$capitalized_name$)");
474 }
475 printer->Print(") {\n"
476 " return false;\n"
477 " }\n"
478 "}\n");
479 } else if (java_type == JAVATYPE_DOUBLE) {
480 printer->Print(variables_,
481 "{\n"
482 " long bits = java.lang.Double.doubleToLongBits(this.$name$);\n"
483 " if (bits != java.lang.Double.doubleToLongBits(other.$name$)");
484 if (params_.generate_has()) {
485 printer->Print(variables_,
486 "\n"
487 " || (bits == java.lang.Double.doubleToLongBits($default$)\n"
488 " && this.has$capitalized_name$ != other.has$capitalized_name$)");
489 }
490 printer->Print(") {\n"
491 " return false;\n"
492 " }\n"
493 "}\n");
494 } else {
495 printer->Print(variables_,
496 "if (this.$name$ != other.$name$");
497 if (params_.generate_has()) {
498 printer->Print(variables_,
499 "\n"
500 " || (this.$name$ == $default$\n"
501 " && this.has$capitalized_name$ != other.has$capitalized_name$)");
502 }
503 printer->Print(") {\n"
504 " return false;\n"
505 "}\n");
506 }
507 }
508
509 void PrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer * printer) const510 GenerateHashCodeCode(io::Printer* printer) const {
511 JavaType java_type = GetJavaType(descriptor_);
512 if (java_type == JAVATYPE_BYTES) {
513 printer->Print(variables_,
514 "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n");
515 } else if (java_type == JAVATYPE_STRING
516 || params_.use_reference_types_for_primitives()) {
517 printer->Print(variables_,
518 "result = 31 * result\n"
519 " + (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
520 } else {
521 switch (java_type) {
522 // For all Java primitive types below, the hash codes match the
523 // results of BoxedType.valueOf(primitiveValue).hashCode().
524 case JAVATYPE_INT:
525 printer->Print(variables_,
526 "result = 31 * result + this.$name$;\n");
527 break;
528 case JAVATYPE_LONG:
529 printer->Print(variables_,
530 "result = 31 * result\n"
531 " + (int) (this.$name$ ^ (this.$name$ >>> 32));\n");
532 break;
533 case JAVATYPE_FLOAT:
534 printer->Print(variables_,
535 "result = 31 * result\n"
536 " + java.lang.Float.floatToIntBits(this.$name$);\n");
537 break;
538 case JAVATYPE_DOUBLE:
539 printer->Print(variables_,
540 "{\n"
541 " long v = java.lang.Double.doubleToLongBits(this.$name$);\n"
542 " result = 31 * result + (int) (v ^ (v >>> 32));\n"
543 "}\n");
544 break;
545 case JAVATYPE_BOOLEAN:
546 printer->Print(variables_,
547 "result = 31 * result + (this.$name$ ? 1231 : 1237);\n");
548 break;
549 default:
550 GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
551 break;
552 }
553 }
554 }
555
556 // ===================================================================
557
558 AccessorPrimitiveFieldGenerator::
AccessorPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Params & params,int has_bit_index)559 AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
560 const Params& params, int has_bit_index)
561 : FieldGenerator(params), descriptor_(descriptor) {
562 SetPrimitiveVariables(descriptor, params, &variables_);
563 SetBitOperationVariables("has", has_bit_index, &variables_);
564 }
565
~AccessorPrimitiveFieldGenerator()566 AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
567
SavedDefaultNeeded() const568 bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const {
569 return variables_.find("default_constant") != variables_.end();
570 }
571
572 void AccessorPrimitiveFieldGenerator::
GenerateInitSavedDefaultCode(io::Printer * printer) const573 GenerateInitSavedDefaultCode(io::Printer* printer) const {
574 if (variables_.find("default_constant") != variables_.end()) {
575 printer->Print(variables_,
576 "$default_constant$ = $default_constant_value$;\n");
577 }
578 }
579
580 void AccessorPrimitiveFieldGenerator::
GenerateMembers(io::Printer * printer,bool lazy_init) const581 GenerateMembers(io::Printer* printer, bool lazy_init) const {
582 if (variables_.find("default_constant") != variables_.end()) {
583 // Those primitive types that need a saved default.
584 if (lazy_init) {
585 printer->Print(variables_,
586 "private static $type$ $default_constant$;\n");
587 } else {
588 printer->Print(variables_,
589 "private static final $type$ $default_constant$ =\n"
590 " $default_constant_value$;\n");
591 }
592 }
593 printer->Print(variables_,
594 "private $type$ $name$_;\n"
595 "public $type$ get$capitalized_name$() {\n"
596 " return $name$_;\n"
597 "}\n"
598 "public $message_name$ set$capitalized_name$($type$ value) {\n");
599 if (IsReferenceType(GetJavaType(descriptor_))) {
600 printer->Print(variables_,
601 " if (value == null) {\n"
602 " throw new java.lang.NullPointerException();\n"
603 " }\n");
604 }
605 printer->Print(variables_,
606 " $name$_ = value;\n"
607 " $set_has$;\n"
608 " return this;\n"
609 "}\n"
610 "public boolean has$capitalized_name$() {\n"
611 " return $get_has$;\n"
612 "}\n"
613 "public $message_name$ clear$capitalized_name$() {\n"
614 " $name$_ = $default_copy_if_needed$;\n"
615 " $clear_has$;\n"
616 " return this;\n"
617 "}\n");
618 }
619
620 void AccessorPrimitiveFieldGenerator::
GenerateClearCode(io::Printer * printer) const621 GenerateClearCode(io::Printer* printer) const {
622 printer->Print(variables_,
623 "$name$_ = $default_copy_if_needed$;\n");
624 }
625
626 void AccessorPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const627 GenerateMergingCode(io::Printer* printer) const {
628 printer->Print(variables_,
629 "$name$_ = input.read$capitalized_type$();\n"
630 "$set_has$;\n");
631 }
632
633 void AccessorPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const634 GenerateSerializationCode(io::Printer* printer) const {
635 printer->Print(variables_,
636 "if ($get_has$) {\n"
637 " output.write$capitalized_type$($number$, $name$_);\n"
638 "}\n");
639 }
640
641 void AccessorPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const642 GenerateSerializedSizeCode(io::Printer* printer) const {
643 printer->Print(variables_,
644 "if ($get_has$) {\n"
645 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
646 " .compute$capitalized_type$Size($number$, $name$_);\n"
647 "}\n");
648 }
649
650 void AccessorPrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const651 GenerateEqualsCode(io::Printer* printer) const {
652 switch (GetJavaType(descriptor_)) {
653 // For all Java primitive types below, the equality checks match the
654 // results of BoxedType.valueOf(primitiveValue).equals(otherValue).
655 case JAVATYPE_FLOAT:
656 printer->Print(variables_,
657 "if ($different_has$\n"
658 " || java.lang.Float.floatToIntBits($name$_)\n"
659 " != java.lang.Float.floatToIntBits(other.$name$_)) {\n"
660 " return false;\n"
661 "}\n");
662 break;
663 case JAVATYPE_DOUBLE:
664 printer->Print(variables_,
665 "if ($different_has$\n"
666 " || java.lang.Double.doubleToLongBits($name$_)\n"
667 " != java.lang.Double.doubleToLongBits(other.$name$_)) {\n"
668 " return false;\n"
669 "}\n");
670 break;
671 case JAVATYPE_INT:
672 case JAVATYPE_LONG:
673 case JAVATYPE_BOOLEAN:
674 printer->Print(variables_,
675 "if ($different_has$\n"
676 " || $name$_ != other.$name$_) {\n"
677 " return false;\n"
678 "}\n");
679 break;
680 case JAVATYPE_STRING:
681 // Accessor style would guarantee $name$_ non-null
682 printer->Print(variables_,
683 "if ($different_has$\n"
684 " || !$name$_.equals(other.$name$_)) {\n"
685 " return false;\n"
686 "}\n");
687 break;
688 case JAVATYPE_BYTES:
689 // Accessor style would guarantee $name$_ non-null
690 printer->Print(variables_,
691 "if ($different_has$\n"
692 " || !java.util.Arrays.equals($name$_, other.$name$_)) {\n"
693 " return false;\n"
694 "}\n");
695 break;
696 default:
697 GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
698 break;
699 }
700 }
701
702 void AccessorPrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer * printer) const703 GenerateHashCodeCode(io::Printer* printer) const {
704 switch (GetJavaType(descriptor_)) {
705 // For all Java primitive types below, the hash codes match the
706 // results of BoxedType.valueOf(primitiveValue).hashCode().
707 case JAVATYPE_INT:
708 printer->Print(variables_,
709 "result = 31 * result + $name$_;\n");
710 break;
711 case JAVATYPE_LONG:
712 printer->Print(variables_,
713 "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n");
714 break;
715 case JAVATYPE_FLOAT:
716 printer->Print(variables_,
717 "result = 31 * result +\n"
718 " java.lang.Float.floatToIntBits($name$_);\n");
719 break;
720 case JAVATYPE_DOUBLE:
721 printer->Print(variables_,
722 "{\n"
723 " long v = java.lang.Double.doubleToLongBits($name$_);\n"
724 " result = 31 * result + (int) (v ^ (v >>> 32));\n"
725 "}\n");
726 break;
727 case JAVATYPE_BOOLEAN:
728 printer->Print(variables_,
729 "result = 31 * result + ($name$_ ? 1231 : 1237);\n");
730 break;
731 case JAVATYPE_STRING:
732 // Accessor style would guarantee $name$_ non-null
733 printer->Print(variables_,
734 "result = 31 * result + $name$_.hashCode();\n");
735 break;
736 case JAVATYPE_BYTES:
737 // Accessor style would guarantee $name$_ non-null
738 printer->Print(variables_,
739 "result = 31 * result + java.util.Arrays.hashCode($name$_);\n");
740 break;
741 default:
742 GOOGLE_LOG(ERROR) << "unknown java type for primitive field";
743 break;
744 }
745 }
746
747 // ===================================================================
748
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,const Params & params)749 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
750 const FieldDescriptor* descriptor, const Params& params)
751 : FieldGenerator(params), descriptor_(descriptor) {
752 SetPrimitiveVariables(descriptor, params, &variables_);
753 SetCommonOneofVariables(descriptor, &variables_);
754 }
755
~PrimitiveOneofFieldGenerator()756 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
757
GenerateMembers(io::Printer * printer,bool) const758 void PrimitiveOneofFieldGenerator::GenerateMembers(
759 io::Printer* printer, bool /*unused lazy_init*/) const {
760 printer->Print(variables_,
761 "public boolean has$capitalized_name$() {\n"
762 " return $has_oneof_case$;\n"
763 "}\n"
764 "public $type$ get$capitalized_name$() {\n"
765 " if ($has_oneof_case$) {\n"
766 " return ($type$) ($boxed_type$) this.$oneof_name$_;\n"
767 " }\n"
768 " return $default$;\n"
769 "}\n"
770 "public $message_name$ set$capitalized_name$($type$ value) {\n"
771 " $set_oneof_case$;\n"
772 " this.$oneof_name$_ = value;\n"
773 " return this;\n"
774 "}\n");
775 }
776
GenerateClearCode(io::Printer * printer) const777 void PrimitiveOneofFieldGenerator::GenerateClearCode(
778 io::Printer* printer) const {
779 // No clear method for oneof fields.
780 }
781
GenerateMergingCode(io::Printer * printer) const782 void PrimitiveOneofFieldGenerator::GenerateMergingCode(
783 io::Printer* printer) const {
784 printer->Print(variables_,
785 "this.$oneof_name$_ = input.read$capitalized_type$();\n"
786 "$set_oneof_case$;\n");
787 }
788
GenerateSerializationCode(io::Printer * printer) const789 void PrimitiveOneofFieldGenerator::GenerateSerializationCode(
790 io::Printer* printer) const {
791 printer->Print(variables_,
792 "if ($has_oneof_case$) {\n"
793 " output.write$capitalized_type$(\n"
794 " $number$, ($boxed_type$) this.$oneof_name$_);\n"
795 "}\n");
796 }
797
GenerateSerializedSizeCode(io::Printer * printer) const798 void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
799 io::Printer* printer) const {
800 printer->Print(variables_,
801 "if ($has_oneof_case$) {\n"
802 " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
803 " .compute$capitalized_type$Size(\n"
804 " $number$, ($boxed_type$) this.$oneof_name$_);\n"
805 "}\n");
806 }
807
GenerateEqualsCode(io::Printer * printer) const808 void PrimitiveOneofFieldGenerator::GenerateEqualsCode(
809 io::Printer* printer) const {
810 GenerateOneofFieldEquals(descriptor_, variables_, printer);
811 }
812
GenerateHashCodeCode(io::Printer * printer) const813 void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(
814 io::Printer* printer) const {
815 GenerateOneofFieldHashCode(descriptor_, variables_, printer);
816 }
817
818 // ===================================================================
819
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Params & params)820 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
821 const FieldDescriptor* descriptor, const Params& params)
822 : FieldGenerator(params), descriptor_(descriptor) {
823 SetPrimitiveVariables(descriptor, params, &variables_);
824 }
825
~RepeatedPrimitiveFieldGenerator()826 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
827
828 void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer * printer,bool) const829 GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const {
830 printer->Print(variables_,
831 "public $type$[] $name$;\n");
832 }
833
834 void RepeatedPrimitiveFieldGenerator::
GenerateClearCode(io::Printer * printer) const835 GenerateClearCode(io::Printer* printer) const {
836 printer->Print(variables_,
837 "$name$ = $default$;\n");
838 }
839
840 void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const841 GenerateMergingCode(io::Printer* printer) const {
842 // First, figure out the length of the array, then parse.
843 printer->Print(variables_,
844 "int arrayLength = com.google.protobuf.nano.WireFormatNano\n"
845 " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
846 "int i = this.$name$ == null ? 0 : this.$name$.length;\n");
847
848 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
849 printer->Print(variables_,
850 "byte[][] newArray = new byte[i + arrayLength][];\n");
851 } else {
852 printer->Print(variables_,
853 "$type$[] newArray = new $type$[i + arrayLength];\n");
854 }
855 printer->Print(variables_,
856 "if (i != 0) {\n"
857 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
858 "}\n"
859 "for (; i < newArray.length - 1; i++) {\n"
860 " newArray[i] = input.read$capitalized_type$();\n"
861 " input.readTag();\n"
862 "}\n"
863 "// Last one without readTag.\n"
864 "newArray[i] = input.read$capitalized_type$();\n"
865 "this.$name$ = newArray;\n");
866 }
867
868 void RepeatedPrimitiveFieldGenerator::
GenerateMergingCodeFromPacked(io::Printer * printer) const869 GenerateMergingCodeFromPacked(io::Printer* printer) const {
870 printer->Print(
871 "int length = input.readRawVarint32();\n"
872 "int limit = input.pushLimit(length);\n");
873
874 // If we know the elements will all be of the same size, the arrayLength
875 // can be calculated much more easily. However, FixedSize() returns 1 for
876 // repeated bool fields, which are guaranteed to have the fixed size of
877 // 1 byte per value only if we control the output. On the wire they can
878 // legally appear as variable-size integers, so we need to use the slow
879 // way for repeated bool fields.
880 if (descriptor_->type() == FieldDescriptor::TYPE_BOOL
881 || FixedSize(descriptor_->type()) == -1) {
882 printer->Print(variables_,
883 "// First pass to compute array length.\n"
884 "int arrayLength = 0;\n"
885 "int startPos = input.getPosition();\n"
886 "while (input.getBytesUntilLimit() > 0) {\n"
887 " input.read$capitalized_type$();\n"
888 " arrayLength++;\n"
889 "}\n"
890 "input.rewindToPosition(startPos);\n");
891 } else {
892 printer->Print(variables_,
893 "int arrayLength = length / $fixed_size$;\n");
894 }
895
896 printer->Print(variables_,
897 "int i = this.$name$ == null ? 0 : this.$name$.length;\n"
898 "$type$[] newArray = new $type$[i + arrayLength];\n"
899 "if (i != 0) {\n"
900 " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
901 "}\n"
902 "for (; i < newArray.length; i++) {\n"
903 " newArray[i] = input.read$capitalized_type$();\n"
904 "}\n"
905 "this.$name$ = newArray;\n"
906 "input.popLimit(limit);\n");
907 }
908
909 void RepeatedPrimitiveFieldGenerator::
GenerateRepeatedDataSizeCode(io::Printer * printer) const910 GenerateRepeatedDataSizeCode(io::Printer* printer) const {
911 // Creates a variable dataSize and puts the serialized size in there.
912 // If the element type is a Java reference type, also generates
913 // dataCount which stores the number of non-null elements in the field.
914 if (IsReferenceType(GetJavaType(descriptor_))) {
915 printer->Print(variables_,
916 "int dataCount = 0;\n"
917 "int dataSize = 0;\n"
918 "for (int i = 0; i < this.$name$.length; i++) {\n"
919 " $type$ element = this.$name$[i];\n"
920 " if (element != null) {\n"
921 " dataCount++;\n"
922 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
923 " .compute$capitalized_type$SizeNoTag(element);\n"
924 " }\n"
925 "}\n");
926 } else if (FixedSize(descriptor_->type()) == -1) {
927 printer->Print(variables_,
928 "int dataSize = 0;\n"
929 "for (int i = 0; i < this.$name$.length; i++) {\n"
930 " $type$ element = this.$name$[i];\n"
931 " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
932 " .compute$capitalized_type$SizeNoTag(element);\n"
933 "}\n");
934 } else {
935 printer->Print(variables_,
936 "int dataSize = $fixed_size$ * this.$name$.length;\n");
937 }
938 }
939
940 void RepeatedPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const941 GenerateSerializationCode(io::Printer* printer) const {
942 printer->Print(variables_,
943 "if (this.$name$ != null && this.$name$.length > 0) {\n");
944 printer->Indent();
945
946 if (descriptor_->is_packable() && descriptor_->options().packed()) {
947 GenerateRepeatedDataSizeCode(printer);
948 printer->Print(variables_,
949 "output.writeRawVarint32($tag$);\n"
950 "output.writeRawVarint32(dataSize);\n"
951 "for (int i = 0; i < this.$name$.length; i++) {\n"
952 " output.write$capitalized_type$NoTag(this.$name$[i]);\n"
953 "}\n");
954 } else if (IsReferenceType(GetJavaType(descriptor_))) {
955 printer->Print(variables_,
956 "for (int i = 0; i < this.$name$.length; i++) {\n"
957 " $type$ element = this.$name$[i];\n"
958 " if (element != null) {\n"
959 " output.write$capitalized_type$($number$, element);\n"
960 " }\n"
961 "}\n");
962 } else {
963 printer->Print(variables_,
964 "for (int i = 0; i < this.$name$.length; i++) {\n"
965 " output.write$capitalized_type$($number$, this.$name$[i]);\n"
966 "}\n");
967 }
968
969 printer->Outdent();
970 printer->Print("}\n");
971 }
972
973 void RepeatedPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const974 GenerateSerializedSizeCode(io::Printer* printer) const {
975 printer->Print(variables_,
976 "if (this.$name$ != null && this.$name$.length > 0) {\n");
977 printer->Indent();
978
979 GenerateRepeatedDataSizeCode(printer);
980
981 printer->Print(
982 "size += dataSize;\n");
983 if (descriptor_->is_packable() && descriptor_->options().packed()) {
984 printer->Print(variables_,
985 "size += $tag_size$;\n"
986 "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
987 " .computeRawVarint32Size(dataSize);\n");
988 } else if (IsReferenceType(GetJavaType(descriptor_))) {
989 printer->Print(variables_,
990 "size += $tag_size$ * dataCount;\n");
991 } else {
992 printer->Print(variables_,
993 "size += $tag_size$ * this.$name$.length;\n");
994 }
995
996 printer->Outdent();
997
998 printer->Print(
999 "}\n");
1000 }
1001
1002 void RepeatedPrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const1003 GenerateEqualsCode(io::Printer* printer) const {
1004 printer->Print(variables_,
1005 "if (!com.google.protobuf.nano.InternalNano.equals(\n"
1006 " this.$name$, other.$name$)) {\n"
1007 " return false;\n"
1008 "}\n");
1009 }
1010
1011 void RepeatedPrimitiveFieldGenerator::
GenerateHashCodeCode(io::Printer * printer) const1012 GenerateHashCodeCode(io::Printer* printer) const {
1013 printer->Print(variables_,
1014 "result = 31 * result\n"
1015 " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
1016 }
1017
1018 } // namespace javanano
1019 } // namespace compiler
1020 } // namespace protobuf
1021 } // namespace google
1022