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