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