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 <algorithm>
36 #include <google/protobuf/stubs/hash.h>
37 #include <google/protobuf/compiler/javanano/javanano_message.h>
38 #include <google/protobuf/compiler/javanano/javanano_enum.h>
39 #include <google/protobuf/compiler/javanano/javanano_extension.h>
40 #include <google/protobuf/compiler/javanano/javanano_helpers.h>
41 #include <google/protobuf/stubs/strutil.h>
42 #include <google/protobuf/io/printer.h>
43 #include <google/protobuf/io/coded_stream.h>
44 #include <google/protobuf/wire_format.h>
45 #include <google/protobuf/descriptor.pb.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
57 struct FieldOrderingByNumber {
operator ()google::protobuf::compiler::javanano::__anon0aed76a10111::FieldOrderingByNumber58 inline bool operator()(const FieldDescriptor* a,
59 const FieldDescriptor* b) const {
60 return a->number() < b->number();
61 }
62 };
63
64 // Sort the fields of the given Descriptor by number into a new[]'d array
65 // and return it.
SortFieldsByNumber(const Descriptor * descriptor)66 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
67 const FieldDescriptor** fields =
68 new const FieldDescriptor*[descriptor->field_count()];
69 for (int i = 0; i < descriptor->field_count(); i++) {
70 fields[i] = descriptor->field(i);
71 }
72 sort(fields, fields + descriptor->field_count(),
73 FieldOrderingByNumber());
74 return fields;
75 }
76
77 } // namespace
78
79 // ===================================================================
80
MessageGenerator(const Descriptor * descriptor,const Params & params)81 MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
82 : params_(params),
83 descriptor_(descriptor),
84 field_generators_(descriptor, params) {
85 }
86
~MessageGenerator()87 MessageGenerator::~MessageGenerator() {}
88
GenerateStaticVariables(io::Printer * printer)89 void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
90 // Generate static members for all nested types.
91 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
92 // TODO(kenton): Reuse MessageGenerator objects?
93 MessageGenerator(descriptor_->nested_type(i), params_)
94 .GenerateStaticVariables(printer);
95 }
96 }
97
GenerateStaticVariableInitializers(io::Printer * printer)98 void MessageGenerator::GenerateStaticVariableInitializers(
99 io::Printer* printer) {
100 // Generate static member initializers for all nested types.
101 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
102 // TODO(kenton): Reuse MessageGenerator objects?
103 MessageGenerator(descriptor_->nested_type(i), params_)
104 .GenerateStaticVariableInitializers(printer);
105 }
106 }
107
Generate(io::Printer * printer)108 void MessageGenerator::Generate(io::Printer* printer) {
109 if (!params_.store_unknown_fields() &&
110 (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
111 GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
112 "'store_unknown_fields' generator option is 'true'\n";
113 }
114
115 const string& file_name = descriptor_->file()->name();
116 bool is_own_file =
117 params_.java_multiple_files(file_name)
118 && descriptor_->containing_type() == NULL;
119
120 if (is_own_file) {
121 // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
122 // may have the same names as constants in the nested classes. This causes Java warnings, but
123 // is not fatal, so we suppress those warnings here in the top-most class declaration.
124 printer->Print(
125 "\n"
126 "@SuppressWarnings(\"hiding\")\n"
127 "public final class $classname$ extends\n",
128 "classname", descriptor_->name());
129 } else {
130 printer->Print(
131 "\n"
132 "public static final class $classname$ extends\n",
133 "classname", descriptor_->name());
134 }
135 if (params_.store_unknown_fields() && params_.parcelable_messages()) {
136 printer->Print(
137 " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>",
138 "classname", descriptor_->name());
139 } else if (params_.store_unknown_fields()) {
140 printer->Print(
141 " com.google.protobuf.nano.ExtendableMessageNano<$classname$>",
142 "classname", descriptor_->name());
143 } else if (params_.parcelable_messages()) {
144 printer->Print(
145 " com.google.protobuf.nano.android.ParcelableMessageNano");
146 } else {
147 printer->Print(
148 " com.google.protobuf.nano.MessageNano");
149 }
150 if (params_.generate_clone()) {
151 printer->Print(" implements java.lang.Cloneable {\n");
152 } else {
153 printer->Print(" {\n");
154 }
155 printer->Indent();
156
157 if (params_.parcelable_messages()) {
158 printer->Print(
159 "\n"
160 "// Used by Parcelable\n"
161 "@SuppressWarnings({\"unused\"})\n"
162 "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n"
163 " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n"
164 " $classname$>($classname$.class);\n",
165 "classname", descriptor_->name());
166 }
167
168 // Nested types and extensions
169 for (int i = 0; i < descriptor_->extension_count(); i++) {
170 ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
171 }
172
173 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
174 EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
175 }
176
177 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
178 MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
179 }
180
181 // Lazy initialization of otherwise static final fields can help prevent the
182 // class initializer from being generated. We want to prevent it because it
183 // stops ProGuard from inlining any methods in this class into call sites and
184 // therefore reducing the method count. However, extensions are best kept as
185 // public static final fields with initializers, so with their existence we
186 // won't bother with lazy initialization.
187 bool lazy_init = descriptor_->extension_count() == 0;
188
189 // Empty array
190 if (lazy_init) {
191 printer->Print(
192 "\n"
193 "private static volatile $classname$[] _emptyArray;\n"
194 "public static $classname$[] emptyArray() {\n"
195 " // Lazily initializes the empty array\n"
196 " if (_emptyArray == null) {\n"
197 " synchronized (\n"
198 " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
199 " if (_emptyArray == null) {\n"
200 " _emptyArray = new $classname$[0];\n"
201 " }\n"
202 " }\n"
203 " }\n"
204 " return _emptyArray;\n"
205 "}\n",
206 "classname", descriptor_->name());
207 } else {
208 printer->Print(
209 "\n"
210 "private static final $classname$[] EMPTY_ARRAY = {};\n"
211 "public static $classname$[] emptyArray() {\n"
212 " return EMPTY_ARRAY;\n"
213 "}\n",
214 "classname", descriptor_->name());
215 }
216
217 // Integers for bit fields
218 int totalInts = (field_generators_.total_bits() + 31) / 32;
219 if (totalInts > 0) {
220 printer->Print("\n");
221 for (int i = 0; i < totalInts; i++) {
222 printer->Print("private int $bit_field_name$;\n",
223 "bit_field_name", GetBitFieldName(i));
224 }
225 }
226
227 // Fields and maybe their default values
228 for (int i = 0; i < descriptor_->field_count(); i++) {
229 printer->Print("\n");
230 PrintFieldComment(printer, descriptor_->field(i));
231 field_generators_.get(descriptor_->field(i)).GenerateMembers(
232 printer, lazy_init);
233 }
234
235 // Insertion point for proto compiler plugins
236 printer->Print("\n// @@protoc_insertion_point(class_scope:$classname$)\n",
237 "classname", descriptor_->full_name());
238
239 // Constructor, with lazy init code if needed
240 if (lazy_init && field_generators_.saved_defaults_needed()) {
241 printer->Print(
242 "\n"
243 "private static volatile boolean _classInitialized;\n"
244 "\n"
245 "public $classname$() {\n"
246 " // Lazily initializes the field defaults\n"
247 " if (!_classInitialized) {\n"
248 " synchronized (\n"
249 " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
250 " if (!_classInitialized) {\n",
251 "classname", descriptor_->name());
252 printer->Indent();
253 printer->Indent();
254 printer->Indent();
255 printer->Indent();
256 for (int i = 0; i < descriptor_->field_count(); i++) {
257 field_generators_.get(descriptor_->field(i))
258 .GenerateInitSavedDefaultCode(printer);
259 }
260 printer->Outdent();
261 printer->Outdent();
262 printer->Outdent();
263 printer->Outdent();
264 printer->Print(
265 " _classInitialized = true;\n"
266 " }\n"
267 " }\n"
268 " }\n");
269 if (params_.generate_clear()) {
270 printer->Print(" clear();\n");
271 }
272 printer->Print("}\n");
273 } else {
274 printer->Print(
275 "\n"
276 "public $classname$() {\n",
277 "classname", descriptor_->name());
278 if (params_.generate_clear()) {
279 printer->Print(" clear();\n");
280 } else {
281 printer->Indent();
282 GenerateFieldInitializers(printer);
283 printer->Outdent();
284 }
285 printer->Print("}\n");
286 }
287
288 // Other methods in this class
289
290 GenerateClear(printer);
291
292 if (params_.generate_clone()) {
293 GenerateClone(printer);
294 }
295
296 if (params_.generate_equals()) {
297 GenerateEquals(printer);
298 GenerateHashCode(printer);
299 }
300
301 GenerateMessageSerializationMethods(printer);
302 GenerateMergeFromMethods(printer);
303 GenerateParseFromMethods(printer);
304
305 printer->Outdent();
306 printer->Print("}\n");
307 }
308
309 // ===================================================================
310
311 void MessageGenerator::
GenerateMessageSerializationMethods(io::Printer * printer)312 GenerateMessageSerializationMethods(io::Printer* printer) {
313 // Rely on the parent implementations of writeTo() and getSerializedSize()
314 // if there are no fields to serialize in this message.
315 if (descriptor_->field_count() == 0) {
316 return;
317 }
318
319 scoped_array<const FieldDescriptor*> sorted_fields(
320 SortFieldsByNumber(descriptor_));
321
322 printer->Print(
323 "\n"
324 "@Override\n"
325 "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
326 " throws java.io.IOException {\n");
327 printer->Indent();
328
329 // Output the fields in sorted order
330 for (int i = 0; i < descriptor_->field_count(); i++) {
331 GenerateSerializeOneField(printer, sorted_fields[i]);
332 }
333
334 // The parent implementation will write any unknown fields if necessary.
335 printer->Print(
336 "super.writeTo(output);\n");
337
338 printer->Outdent();
339 printer->Print("}\n");
340
341 // The parent implementation will get the serialized size for unknown
342 // fields if necessary.
343 printer->Print(
344 "\n"
345 "@Override\n"
346 "protected int computeSerializedSize() {\n"
347 " int size = super.computeSerializedSize();\n");
348 printer->Indent();
349
350 for (int i = 0; i < descriptor_->field_count(); i++) {
351 field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
352 }
353
354 printer->Outdent();
355 printer->Print(
356 " return size;\n"
357 "}\n");
358 }
359
GenerateMergeFromMethods(io::Printer * printer)360 void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
361 scoped_array<const FieldDescriptor*> sorted_fields(
362 SortFieldsByNumber(descriptor_));
363
364 printer->Print(
365 "\n"
366 "@Override\n"
367 "public $classname$ mergeFrom(\n"
368 " com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
369 " throws java.io.IOException {\n",
370 "classname", descriptor_->name());
371
372 printer->Indent();
373
374 printer->Print(
375 "while (true) {\n");
376 printer->Indent();
377
378 printer->Print(
379 "int tag = input.readTag();\n"
380 "switch (tag) {\n");
381 printer->Indent();
382
383 printer->Print(
384 "case 0:\n" // zero signals EOF / limit reached
385 " return this;\n"
386 "default: {\n");
387
388 printer->Indent();
389 if (params_.store_unknown_fields()) {
390 printer->Print(
391 "if (!super.storeUnknownField(input, tag)) {\n"
392 " return this;\n"
393 "}\n");
394 } else {
395 printer->Print(
396 "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
397 " return this;\n" // it's an endgroup tag
398 "}\n");
399 }
400 printer->Print("break;\n");
401 printer->Outdent();
402 printer->Print("}\n");
403
404 for (int i = 0; i < descriptor_->field_count(); i++) {
405 const FieldDescriptor* field = sorted_fields[i];
406 uint32 tag = WireFormatLite::MakeTag(field->number(),
407 WireFormat::WireTypeForFieldType(field->type()));
408
409 printer->Print(
410 "case $tag$: {\n",
411 "tag", SimpleItoa(tag));
412 printer->Indent();
413
414 field_generators_.get(field).GenerateMergingCode(printer);
415
416 printer->Outdent();
417 printer->Print(
418 " break;\n"
419 "}\n");
420
421 if (field->is_packable()) {
422 // To make packed = true wire compatible, we generate parsing code from a
423 // packed version of this field regardless of field->options().packed().
424 uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
425 WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
426 printer->Print(
427 "case $tag$: {\n",
428 "tag", SimpleItoa(packed_tag));
429 printer->Indent();
430
431 field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
432
433 printer->Outdent();
434 printer->Print(
435 " break;\n"
436 "}\n");
437 }
438 }
439
440 printer->Outdent();
441 printer->Outdent();
442 printer->Outdent();
443 printer->Print(
444 " }\n" // switch (tag)
445 " }\n" // while (true)
446 "}\n");
447 }
448
449 void MessageGenerator::
GenerateParseFromMethods(io::Printer * printer)450 GenerateParseFromMethods(io::Printer* printer) {
451 // Note: These are separate from GenerateMessageSerializationMethods()
452 // because they need to be generated even for messages that are optimized
453 // for code size.
454 printer->Print(
455 "\n"
456 "public static $classname$ parseFrom(byte[] data)\n"
457 " throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
458 " return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
459 "}\n"
460 "\n"
461 "public static $classname$ parseFrom(\n"
462 " com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
463 " throws java.io.IOException {\n"
464 " return new $classname$().mergeFrom(input);\n"
465 "}\n",
466 "classname", descriptor_->name());
467 }
468
GenerateSerializeOneField(io::Printer * printer,const FieldDescriptor * field)469 void MessageGenerator::GenerateSerializeOneField(
470 io::Printer* printer, const FieldDescriptor* field) {
471 field_generators_.get(field).GenerateSerializationCode(printer);
472 }
473
GenerateClear(io::Printer * printer)474 void MessageGenerator::GenerateClear(io::Printer* printer) {
475 if (!params_.generate_clear()) {
476 return;
477 }
478 printer->Print(
479 "\n"
480 "public $classname$ clear() {\n",
481 "classname", descriptor_->name());
482 printer->Indent();
483
484 GenerateFieldInitializers(printer);
485
486 printer->Outdent();
487 printer->Print(
488 " return this;\n"
489 "}\n");
490 }
491
GenerateFieldInitializers(io::Printer * printer)492 void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) {
493 // Clear bit fields.
494 int totalInts = (field_generators_.total_bits() + 31) / 32;
495 for (int i = 0; i < totalInts; i++) {
496 printer->Print("$bit_field_name$ = 0;\n",
497 "bit_field_name", GetBitFieldName(i));
498 }
499
500 // Call clear for all of the fields.
501 for (int i = 0; i < descriptor_->field_count(); i++) {
502 const FieldDescriptor* field = descriptor_->field(i);
503 field_generators_.get(field).GenerateClearCode(printer);
504 }
505
506 // Clear unknown fields.
507 if (params_.store_unknown_fields()) {
508 printer->Print("unknownFieldData = null;\n");
509 }
510 printer->Print("cachedSize = -1;\n");
511 }
512
GenerateClone(io::Printer * printer)513 void MessageGenerator::GenerateClone(io::Printer* printer) {
514 printer->Print(
515 "@Override\n"
516 "public $classname$ clone() {\n",
517 "classname", descriptor_->name());
518 printer->Indent();
519
520 printer->Print(
521 "$classname$ cloned;\n"
522 "try {\n"
523 " cloned = ($classname$) super.clone();\n"
524 "} catch (java.lang.CloneNotSupportedException e) {\n"
525 " throw new java.lang.AssertionError(e);\n"
526 "}\n",
527 "classname", descriptor_->name());
528
529 for (int i = 0; i < descriptor_->field_count(); i++) {
530 field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer);
531 }
532
533 printer->Outdent();
534 printer->Print(
535 " return cloned;\n"
536 "}\n"
537 "\n");
538 }
539
GenerateEquals(io::Printer * printer)540 void MessageGenerator::GenerateEquals(io::Printer* printer) {
541 // Don't override if there are no fields. We could generate an
542 // equals method that compares types, but often empty messages
543 // are used as namespaces.
544 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
545 return;
546 }
547
548 printer->Print(
549 "\n"
550 "@Override\n"
551 "public boolean equals(Object o) {\n");
552 printer->Indent();
553 printer->Print(
554 "if (o == this) {\n"
555 " return true;\n"
556 "}\n"
557 "if (!(o instanceof $classname$)) {\n"
558 " return false;\n"
559 "}\n"
560 "$classname$ other = ($classname$) o;\n",
561 "classname", descriptor_->name());
562
563 for (int i = 0; i < descriptor_->field_count(); i++) {
564 const FieldDescriptor* field = descriptor_->field(i);
565 field_generators_.get(field).GenerateEqualsCode(printer);
566 }
567
568 if (params_.store_unknown_fields()) {
569 printer->Print(
570 "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
571 " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n"
572 "} else {\n"
573 " return unknownFieldData.equals(other.unknownFieldData);\n"
574 "}");
575 } else {
576 printer->Print(
577 "return true;\n");
578 }
579
580 printer->Outdent();
581 printer->Print("}\n");
582 }
583
GenerateHashCode(io::Printer * printer)584 void MessageGenerator::GenerateHashCode(io::Printer* printer) {
585 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
586 return;
587 }
588
589 printer->Print(
590 "\n"
591 "@Override\n"
592 "public int hashCode() {\n");
593 printer->Indent();
594
595 printer->Print("int result = 17;\n");
596 printer->Print("result = 31 * result + getClass().getName().hashCode();\n");
597 for (int i = 0; i < descriptor_->field_count(); i++) {
598 const FieldDescriptor* field = descriptor_->field(i);
599 field_generators_.get(field).GenerateHashCodeCode(printer);
600 }
601
602 if (params_.store_unknown_fields()) {
603 printer->Print(
604 "result = 31 * result + \n"
605 " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n"
606 " unknownFieldData.hashCode());\n");
607 }
608
609 printer->Print("return result;\n");
610
611 printer->Outdent();
612 printer->Print("}\n");
613 }
614
615 // ===================================================================
616
617 } // namespace javanano
618 } // namespace compiler
619 } // namespace protobuf
620 } // namespace google
621