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