javanano_message.cc revision 721ea491a8e3e9ea5a130965dc5761fc335c3e61
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
47namespace google {
48namespace protobuf {
49namespace compiler {
50namespace javanano {
51
52using internal::WireFormat;
53using internal::WireFormatLite;
54
55namespace {
56
57struct FieldOrderingByNumber {
58  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.
66const 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
81MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
82  : params_(params),
83    descriptor_(descriptor),
84    field_generators_(descriptor, params) {
85}
86
87MessageGenerator::~MessageGenerator() {}
88
89void 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
98void 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
108void 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$> {\n",
138      "classname", descriptor_->name());
139  } else if (params_.store_unknown_fields()) {
140    printer->Print(
141      "    com.google.protobuf.nano.ExtendableMessageNano<$classname$> {\n",
142      "classname", descriptor_->name());
143  } else if (params_.parcelable_messages()) {
144    printer->Print(
145      "    com.google.protobuf.nano.android.ParcelableMessageNano {\n");
146  } else {
147    printer->Print(
148      "    com.google.protobuf.nano.MessageNano {\n");
149  }
150  printer->Indent();
151
152  // Nested types and extensions
153  for (int i = 0; i < descriptor_->extension_count(); i++) {
154    ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
155  }
156
157  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
158    EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
159  }
160
161  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
162    MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
163  }
164
165  // Lazy initialization of otherwise static final fields can help prevent the
166  // class initializer from being generated. We want to prevent it because it
167  // stops ProGuard from inlining any methods in this class into call sites and
168  // therefore reducing the method count. However, extensions are best kept as
169  // public static final fields with initializers, so with their existence we
170  // won't bother with lazy initialization.
171  bool lazy_init = descriptor_->extension_count() == 0;
172
173  // Empty array
174  if (lazy_init) {
175    printer->Print(
176      "\n"
177      "private static volatile $classname$[] _emptyArray;\n"
178      "public static $classname$[] emptyArray() {\n"
179      "  // Lazily initializes the empty array\n"
180      "  if (_emptyArray == null) {\n"
181      "    synchronized (\n"
182      "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
183      "      if (_emptyArray == null) {\n"
184      "        _emptyArray = new $classname$[0];\n"
185      "      }\n"
186      "    }\n"
187      "  }\n"
188      "  return _emptyArray;\n"
189      "}\n",
190      "classname", descriptor_->name());
191  } else {
192    printer->Print(
193      "\n"
194      "private static final $classname$[] EMPTY_ARRAY = {};\n"
195      "public static $classname$[] emptyArray() {\n"
196      "  return EMPTY_ARRAY;\n"
197      "}\n",
198      "classname", descriptor_->name());
199  }
200
201  // Integers for bit fields
202  int totalInts = (field_generators_.total_bits() + 31) / 32;
203  if (totalInts > 0) {
204    printer->Print("\n");
205    for (int i = 0; i < totalInts; i++) {
206      printer->Print("private int $bit_field_name$;\n",
207        "bit_field_name", GetBitFieldName(i));
208    }
209  }
210
211  // Fields and maybe their default values
212  for (int i = 0; i < descriptor_->field_count(); i++) {
213    printer->Print("\n");
214    PrintFieldComment(printer, descriptor_->field(i));
215    field_generators_.get(descriptor_->field(i)).GenerateMembers(
216        printer, lazy_init);
217  }
218
219  // Constructor, with lazy init code if needed
220  if (lazy_init && field_generators_.saved_defaults_needed()) {
221    printer->Print(
222      "\n"
223      "private static volatile boolean _classInitialized;\n"
224      "\n"
225      "public $classname$() {\n"
226      "  // Lazily initializes the field defaults\n"
227      "  if (!_classInitialized) {\n"
228      "    synchronized (\n"
229      "        com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
230      "      if (!_classInitialized) {\n",
231      "classname", descriptor_->name());
232    printer->Indent();
233    printer->Indent();
234    printer->Indent();
235    printer->Indent();
236    for (int i = 0; i < descriptor_->field_count(); i++) {
237      field_generators_.get(descriptor_->field(i))
238          .GenerateInitSavedDefaultCode(printer);
239    }
240    printer->Outdent();
241    printer->Outdent();
242    printer->Outdent();
243    printer->Outdent();
244    printer->Print(
245      "        _classInitialized = true;\n"
246      "      }\n"
247      "    }\n"
248      "  }\n"
249      "  clear();\n"
250      "}\n");
251  } else {
252    printer->Print(
253      "\n"
254      "public $classname$() {\n"
255      "  clear();\n"
256      "}\n",
257      "classname", descriptor_->name());
258  }
259
260  // Other methods in this class
261
262  GenerateClear(printer);
263
264  if (params_.generate_equals()) {
265    GenerateEquals(printer);
266    GenerateHashCode(printer);
267  }
268
269  GenerateMessageSerializationMethods(printer);
270  GenerateMergeFromMethods(printer);
271  GenerateParseFromMethods(printer);
272
273  printer->Outdent();
274  printer->Print("}\n");
275}
276
277// ===================================================================
278
279void MessageGenerator::
280GenerateMessageSerializationMethods(io::Printer* printer) {
281  // Rely on the parent implementations of writeTo() and getSerializedSize()
282  // if there are no fields to serialize in this message.
283  if (descriptor_->field_count() == 0) {
284    return;
285  }
286
287  scoped_array<const FieldDescriptor*> sorted_fields(
288    SortFieldsByNumber(descriptor_));
289
290  printer->Print(
291    "\n"
292    "@Override\n"
293    "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
294    "    throws java.io.IOException {\n");
295  printer->Indent();
296
297  // Output the fields in sorted order
298  for (int i = 0; i < descriptor_->field_count(); i++) {
299    GenerateSerializeOneField(printer, sorted_fields[i]);
300  }
301
302  // The parent implementation will write any unknown fields if necessary.
303  printer->Print(
304    "super.writeTo(output);\n");
305
306  printer->Outdent();
307  printer->Print("}\n");
308
309  // The parent implementation will get the serialized size for unknown
310  // fields if necessary.
311  printer->Print(
312    "\n"
313    "@Override\n"
314    "protected int computeSerializedSize() {\n"
315    "  int size = super.computeSerializedSize();\n");
316  printer->Indent();
317
318  for (int i = 0; i < descriptor_->field_count(); i++) {
319    field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
320  }
321
322  printer->Outdent();
323  printer->Print(
324    "  return size;\n"
325    "}\n");
326}
327
328void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
329  scoped_array<const FieldDescriptor*> sorted_fields(
330    SortFieldsByNumber(descriptor_));
331
332  printer->Print(
333    "\n"
334    "@Override\n"
335    "public $classname$ mergeFrom(\n"
336    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
337    "    throws java.io.IOException {\n",
338    "classname", descriptor_->name());
339
340  printer->Indent();
341
342  printer->Print(
343    "while (true) {\n");
344  printer->Indent();
345
346  printer->Print(
347    "int tag = input.readTag();\n"
348    "switch (tag) {\n");
349  printer->Indent();
350
351  printer->Print(
352    "case 0:\n"          // zero signals EOF / limit reached
353    "  return this;\n"
354    "default: {\n");
355
356  printer->Indent();
357  if (params_.store_unknown_fields()) {
358    printer->Print(
359        "if (!storeUnknownField(input, tag)) {\n"
360        "  return this;\n"
361        "}\n");
362  } else {
363    printer->Print(
364        "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
365        "  return this;\n"   // it's an endgroup tag
366        "}\n");
367  }
368  printer->Print("break;\n");
369  printer->Outdent();
370  printer->Print("}\n");
371
372  for (int i = 0; i < descriptor_->field_count(); i++) {
373    const FieldDescriptor* field = sorted_fields[i];
374    uint32 tag = WireFormatLite::MakeTag(field->number(),
375      WireFormat::WireTypeForFieldType(field->type()));
376
377    printer->Print(
378      "case $tag$: {\n",
379      "tag", SimpleItoa(tag));
380    printer->Indent();
381
382    field_generators_.get(field).GenerateMergingCode(printer);
383
384    printer->Outdent();
385    printer->Print(
386      "  break;\n"
387      "}\n");
388
389    if (field->is_packable()) {
390      // To make packed = true wire compatible, we generate parsing code from a
391      // packed version of this field regardless of field->options().packed().
392      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
393        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
394      printer->Print(
395        "case $tag$: {\n",
396        "tag", SimpleItoa(packed_tag));
397      printer->Indent();
398
399      field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
400
401      printer->Outdent();
402      printer->Print(
403        "  break;\n"
404        "}\n");
405    }
406  }
407
408  printer->Outdent();
409  printer->Outdent();
410  printer->Outdent();
411  printer->Print(
412    "    }\n"     // switch (tag)
413    "  }\n"       // while (true)
414    "}\n");
415}
416
417void MessageGenerator::
418GenerateParseFromMethods(io::Printer* printer) {
419  // Note:  These are separate from GenerateMessageSerializationMethods()
420  //   because they need to be generated even for messages that are optimized
421  //   for code size.
422  printer->Print(
423    "\n"
424    "public static $classname$ parseFrom(byte[] data)\n"
425    "    throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
426    "  return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
427    "}\n"
428    "\n"
429    "public static $classname$ parseFrom(\n"
430    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
431    "    throws java.io.IOException {\n"
432    "  return new $classname$().mergeFrom(input);\n"
433    "}\n",
434    "classname", descriptor_->name());
435}
436
437void MessageGenerator::GenerateSerializeOneField(
438    io::Printer* printer, const FieldDescriptor* field) {
439  field_generators_.get(field).GenerateSerializationCode(printer);
440}
441
442void MessageGenerator::GenerateClear(io::Printer* printer) {
443  printer->Print(
444    "\n"
445    "public $classname$ clear() {\n",
446    "classname", descriptor_->name());
447  printer->Indent();
448
449  // Clear bit fields.
450  int totalInts = (field_generators_.total_bits() + 31) / 32;
451  for (int i = 0; i < totalInts; i++) {
452    printer->Print("$bit_field_name$ = 0;\n",
453      "bit_field_name", GetBitFieldName(i));
454  }
455
456  // Call clear for all of the fields.
457  for (int i = 0; i < descriptor_->field_count(); i++) {
458    const FieldDescriptor* field = descriptor_->field(i);
459    field_generators_.get(field).GenerateClearCode(printer);
460  }
461
462  // Clear unknown fields.
463  if (params_.store_unknown_fields()) {
464    printer->Print("unknownFieldData = null;\n");
465  }
466
467  printer->Outdent();
468  printer->Print(
469    "  cachedSize = -1;\n"
470    "  return this;\n"
471    "}\n");
472}
473
474void MessageGenerator::GenerateEquals(io::Printer* printer) {
475  // Don't override if there are no fields. We could generate an
476  // equals method that compares types, but often empty messages
477  // are used as namespaces.
478  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
479    return;
480  }
481
482  printer->Print(
483    "\n"
484    "@Override\n"
485    "public boolean equals(Object o) {\n");
486  printer->Indent();
487  printer->Print(
488    "if (o == this) {\n"
489    "  return true;\n"
490    "}\n"
491    "if (!(o instanceof $classname$)) {\n"
492    "  return false;\n"
493    "}\n"
494    "$classname$ other = ($classname$) o;\n",
495    "classname", descriptor_->name());
496
497  for (int i = 0; i < descriptor_->field_count(); i++) {
498    const FieldDescriptor* field = descriptor_->field(i);
499    field_generators_.get(field).GenerateEqualsCode(printer);
500  }
501
502  if (params_.store_unknown_fields()) {
503    printer->Print(
504      "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
505      "  return other.unknownFieldData == null || other.unknownFieldData.isEmpty();"
506      "} else {\n"
507      "  return unknownFieldData.equals(other.unknownFieldData);\n"
508      "}\n");
509  } else {
510    printer->Print(
511      "return true;\n");
512  }
513
514  printer->Outdent();
515  printer->Print("}\n");
516}
517
518void MessageGenerator::GenerateHashCode(io::Printer* printer) {
519  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
520    return;
521  }
522
523  printer->Print(
524    "\n"
525    "@Override\n"
526    "public int hashCode() {\n");
527  printer->Indent();
528
529  printer->Print("int result = 17;\n");
530  for (int i = 0; i < descriptor_->field_count(); i++) {
531    const FieldDescriptor* field = descriptor_->field(i);
532    field_generators_.get(field).GenerateHashCodeCode(printer);
533  }
534
535  if (params_.store_unknown_fields()) {
536    printer->Print(
537      "result = 31 * result + (unknownFieldData == null || unknownFieldData.isEmpty()\n"
538      "    ? 0 : unknownFieldData.hashCode());\n");
539  }
540
541  printer->Print("return result;\n");
542
543  printer->Outdent();
544  printer->Print("}\n");
545}
546
547// ===================================================================
548
549}  // namespace javanano
550}  // namespace compiler
551}  // namespace protobuf
552}  // namespace google
553