javanano_message.cc revision 382ddccb550e1c822ef26a0e65988998f7446624
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    "public int getSerializedSize() {\n"
308    "  int size = super.getSerializedSize();\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    "  cachedSize = size;\n"
318    "  return size;\n"
319    "}\n");
320}
321
322void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
323  scoped_array<const FieldDescriptor*> sorted_fields(
324    SortFieldsByNumber(descriptor_));
325
326  printer->Print(
327    "\n"
328    "@Override\n"
329    "public $classname$ mergeFrom(\n"
330    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
331    "    throws java.io.IOException {\n",
332    "classname", descriptor_->name());
333
334  printer->Indent();
335
336  printer->Print(
337    "while (true) {\n");
338  printer->Indent();
339
340  printer->Print(
341    "int tag = input.readTag();\n"
342    "switch (tag) {\n");
343  printer->Indent();
344
345  printer->Print(
346    "case 0:\n"          // zero signals EOF / limit reached
347    "  return this;\n"
348    "default: {\n");
349
350  printer->Indent();
351  if (params_.store_unknown_fields()) {
352    printer->Print(
353        "if (!storeUnknownField(input, tag)) {\n"
354        "  return this;\n"
355        "}\n");
356  } else {
357    printer->Print(
358        "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
359        "  return this;\n"   // it's an endgroup tag
360        "}\n");
361  }
362  printer->Print("break;\n");
363  printer->Outdent();
364  printer->Print("}\n");
365
366  for (int i = 0; i < descriptor_->field_count(); i++) {
367    const FieldDescriptor* field = sorted_fields[i];
368    uint32 tag = WireFormatLite::MakeTag(field->number(),
369      WireFormat::WireTypeForFieldType(field->type()));
370
371    printer->Print(
372      "case $tag$: {\n",
373      "tag", SimpleItoa(tag));
374    printer->Indent();
375
376    field_generators_.get(field).GenerateMergingCode(printer);
377
378    printer->Outdent();
379    printer->Print(
380      "  break;\n"
381      "}\n");
382
383    if (field->is_packable()) {
384      // To make packed = true wire compatible, we generate parsing code from a
385      // packed version of this field regardless of field->options().packed().
386      uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
387        WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
388      printer->Print(
389        "case $tag$: {\n",
390        "tag", SimpleItoa(packed_tag));
391      printer->Indent();
392
393      field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
394
395      printer->Outdent();
396      printer->Print(
397        "  break;\n"
398        "}\n");
399    }
400  }
401
402  printer->Outdent();
403  printer->Outdent();
404  printer->Outdent();
405  printer->Print(
406    "    }\n"     // switch (tag)
407    "  }\n"       // while (true)
408    "}\n");
409}
410
411void MessageGenerator::
412GenerateParseFromMethods(io::Printer* printer) {
413  // Note:  These are separate from GenerateMessageSerializationMethods()
414  //   because they need to be generated even for messages that are optimized
415  //   for code size.
416  printer->Print(
417    "\n"
418    "public static $classname$ parseFrom(byte[] data)\n"
419    "    throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
420    "  return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
421    "}\n"
422    "\n"
423    "public static $classname$ parseFrom(\n"
424    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
425    "    throws java.io.IOException {\n"
426    "  return new $classname$().mergeFrom(input);\n"
427    "}\n",
428    "classname", descriptor_->name());
429}
430
431void MessageGenerator::GenerateSerializeOneField(
432    io::Printer* printer, const FieldDescriptor* field) {
433  field_generators_.get(field).GenerateSerializationCode(printer);
434}
435
436void MessageGenerator::GenerateClear(io::Printer* printer) {
437  printer->Print(
438    "\n"
439    "public $classname$ clear() {\n",
440    "classname", descriptor_->name());
441  printer->Indent();
442
443  // Clear bit fields.
444  int totalInts = (field_generators_.total_bits() + 31) / 32;
445  for (int i = 0; i < totalInts; i++) {
446    printer->Print("$bit_field_name$ = 0;\n",
447      "bit_field_name", GetBitFieldName(i));
448  }
449
450  // Call clear for all of the fields.
451  for (int i = 0; i < descriptor_->field_count(); i++) {
452    const FieldDescriptor* field = descriptor_->field(i);
453    field_generators_.get(field).GenerateClearCode(printer);
454  }
455
456  // Clear unknown fields.
457  if (params_.store_unknown_fields()) {
458    printer->Print("unknownFieldData = null;\n");
459  }
460
461  printer->Outdent();
462  printer->Print(
463    "  cachedSize = -1;\n"
464    "  return this;\n"
465    "}\n");
466}
467
468void MessageGenerator::GenerateEquals(io::Printer* printer) {
469  // Don't override if there are no fields. We could generate an
470  // equals method that compares types, but often empty messages
471  // are used as namespaces.
472  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
473    return;
474  }
475
476  printer->Print(
477    "\n"
478    "@Override\n"
479    "public boolean equals(Object o) {\n");
480  printer->Indent();
481  printer->Print(
482    "if (o == this) {\n"
483    "  return true;\n"
484    "}\n"
485    "if (!(o instanceof $classname$)) {\n"
486    "  return false;\n"
487    "}\n"
488    "$classname$ other = ($classname$) o;\n",
489    "classname", descriptor_->name());
490
491  for (int i = 0; i < descriptor_->field_count(); i++) {
492    const FieldDescriptor* field = descriptor_->field(i);
493    field_generators_.get(field).GenerateEqualsCode(printer);
494  }
495
496  if (params_.store_unknown_fields()) {
497    printer->Print(
498      "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
499      "  return other.unknownFieldData == null || other.unknownFieldData.isEmpty();"
500      "} else {\n"
501      "  return unknownFieldData.equals(other.unknownFieldData);\n"
502      "}\n");
503  } else {
504    printer->Print(
505      "return true;\n");
506  }
507
508  printer->Outdent();
509  printer->Print("}\n");
510}
511
512void MessageGenerator::GenerateHashCode(io::Printer* printer) {
513  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
514    return;
515  }
516
517  printer->Print(
518    "\n"
519    "@Override\n"
520    "public int hashCode() {\n");
521  printer->Indent();
522
523  printer->Print("int result = 17;\n");
524  for (int i = 0; i < descriptor_->field_count(); i++) {
525    const FieldDescriptor* field = descriptor_->field(i);
526    field_generators_.get(field).GenerateHashCodeCode(printer);
527  }
528
529  if (params_.store_unknown_fields()) {
530    printer->Print(
531      "result = 31 * result + (unknownFieldData == null || unknownFieldData.isEmpty()\n"
532      "    ? 0 : unknownFieldData.hashCode());\n");
533  }
534
535  printer->Print("return result;\n");
536
537  printer->Outdent();
538  printer->Print("}\n");
539}
540
541// ===================================================================
542
543}  // namespace javanano
544}  // namespace compiler
545}  // namespace protobuf
546}  // namespace google
547