javanano_message.cc revision ccc48faf20dbf3b3cddcffe78d198876d543529b
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
57void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
58  // Print the field's proto-syntax definition as a comment.  We don't want to
59  // print group bodies so we cut off after the first line.
60  string def = field->DebugString();
61  printer->Print("// $def$\n",
62    "def", def.substr(0, def.find_first_of('\n')));
63}
64
65struct FieldOrderingByNumber {
66  inline bool operator()(const FieldDescriptor* a,
67                         const FieldDescriptor* b) const {
68    return a->number() < b->number();
69  }
70};
71
72// Sort the fields of the given Descriptor by number into a new[]'d array
73// and return it.
74const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
75  const FieldDescriptor** fields =
76    new const FieldDescriptor*[descriptor->field_count()];
77  for (int i = 0; i < descriptor->field_count(); i++) {
78    fields[i] = descriptor->field(i);
79  }
80  sort(fields, fields + descriptor->field_count(),
81       FieldOrderingByNumber());
82  return fields;
83}
84
85// Get an identifier that uniquely identifies this type within the file.
86// This is used to declare static variables related to this type at the
87// outermost file scope.
88string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
89  return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
90}
91
92}  // namespace
93
94// ===================================================================
95
96MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
97  : params_(params),
98    descriptor_(descriptor),
99    field_generators_(descriptor, params) {
100}
101
102MessageGenerator::~MessageGenerator() {}
103
104void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
105  // Generate static members for all nested types.
106  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
107    // TODO(kenton):  Reuse MessageGenerator objects?
108    MessageGenerator(descriptor_->nested_type(i), params_)
109      .GenerateStaticVariables(printer);
110  }
111}
112
113void MessageGenerator::GenerateStaticVariableInitializers(
114    io::Printer* printer) {
115  // Generate static member initializers for all nested types.
116  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
117   // TODO(kenton):  Reuse MessageGenerator objects?
118    MessageGenerator(descriptor_->nested_type(i), params_)
119      .GenerateStaticVariableInitializers(printer);
120  }
121}
122
123void MessageGenerator::Generate(io::Printer* printer) {
124  if (!params_.store_unknown_fields() &&
125      (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
126    GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
127        "'store_unknown_fields' generator option is 'true'\n";
128  }
129
130  const string& file_name = descriptor_->file()->name();
131  bool is_own_file =
132    params_.java_multiple_files(file_name)
133      && descriptor_->containing_type() == NULL;
134
135  if (is_own_file) {
136    // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
137    // may have the same names as constants in the nested classes. This causes Java warnings, but
138    // is not fatal, so we suppress those warnings here in the top-most class declaration.
139    printer->Print(
140      "\n"
141      "@SuppressWarnings(\"hiding\")\n"
142      "public final class $classname$ extends\n"
143      "    com.google.protobuf.nano.MessageNano {\n",
144      "classname", descriptor_->name());
145  } else {
146    printer->Print(
147      "\n"
148      "public static final class $classname$ extends\n"
149      "    com.google.protobuf.nano.MessageNano {\n",
150      "classname", descriptor_->name());
151  }
152  printer->Indent();
153  printer->Print(
154    "\n"
155    "public static final $classname$[] EMPTY_ARRAY = {};\n"
156    "\n"
157    "public $classname$() {\n"
158    "  clear();\n"
159    "}\n",
160    "classname", descriptor_->name());
161
162  if (params_.store_unknown_fields()) {
163    printer->Print(
164        "\n"
165        "private java.util.List<com.google.protobuf.nano.UnknownFieldData>\n"
166        "    unknownFieldData;\n");
167  }
168
169  // Nested types and extensions
170  for (int i = 0; i < descriptor_->extension_count(); i++) {
171    ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
172  }
173
174  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
175    EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
176  }
177
178  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
179    MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
180  }
181
182  // Integers for bit fields
183  int totalInts = (field_generators_.total_bits() + 31) / 32;
184  if (totalInts > 0) {
185    printer->Print("\n");
186    for (int i = 0; i < totalInts; i++) {
187      printer->Print("private int $bit_field_name$;\n",
188        "bit_field_name", GetBitFieldName(i));
189    }
190  }
191
192  // Fields
193  for (int i = 0; i < descriptor_->field_count(); i++) {
194    printer->Print("\n");
195    PrintFieldComment(printer, descriptor_->field(i));
196    field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
197  }
198
199  GenerateClear(printer);
200
201  if (params_.generate_equals()) {
202    GenerateEquals(printer);
203    GenerateHashCode(printer);
204  }
205
206  // If we have an extension range, generate accessors for extensions.
207  if (params_.store_unknown_fields()
208      && descriptor_->extension_range_count() > 0) {
209    printer->Print(
210      "\n"
211      "public <T> T getExtension(com.google.protobuf.nano.Extension<T> extension) {\n"
212      "  return com.google.protobuf.nano.WireFormatNano.getExtension(\n"
213      "      extension, unknownFieldData);\n"
214      "}\n"
215      "\n"
216      "public <T> void setExtension(com.google.protobuf.nano.Extension<T> extension, T value) {\n"
217      "  if (unknownFieldData == null) {\n"
218      "    unknownFieldData =\n"
219      "        new java.util.ArrayList<com.google.protobuf.nano.UnknownFieldData>();\n"
220      "  }\n"
221      "  com.google.protobuf.nano.WireFormatNano.setExtension(\n"
222      "      extension, value, unknownFieldData);\n"
223      "}\n");
224  }
225  GenerateMessageSerializationMethods(printer);
226  GenerateMergeFromMethods(printer);
227  GenerateParseFromMethods(printer);
228
229  printer->Outdent();
230  printer->Print("}\n");
231}
232
233// ===================================================================
234
235void MessageGenerator::
236GenerateMessageSerializationMethods(io::Printer* printer) {
237  scoped_array<const FieldDescriptor*> sorted_fields(
238    SortFieldsByNumber(descriptor_));
239
240  // writeTo only throws an exception if it contains one or more fields to write
241  if (descriptor_->field_count() > 0 || params_.store_unknown_fields()) {
242    printer->Print(
243      "\n"
244      "@Override\n"
245      "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
246      "    throws java.io.IOException {\n");
247  } else {
248    printer->Print(
249      "\n"
250      "@Override\n"
251      "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output) {\n");
252  }
253  printer->Indent();
254
255  // Output the fields in sorted order
256  for (int i = 0; i < descriptor_->field_count(); i++) {
257    GenerateSerializeOneField(printer, sorted_fields[i]);
258  }
259
260  // Write unknown fields.
261  if (params_.store_unknown_fields()) {
262    printer->Print(
263      "com.google.protobuf.nano.WireFormatNano.writeUnknownFields(\n"
264      "    unknownFieldData, output);\n");
265  }
266
267  printer->Outdent();
268  printer->Print(
269    "}\n"
270    "\n"
271    "private int cachedSize;\n"
272    "@Override\n"
273    "public int getCachedSize() {\n"
274    "  if (cachedSize < 0) {\n"
275    "    // getSerializedSize sets cachedSize\n"
276    "    getSerializedSize();\n"
277    "  }\n"
278    "  return cachedSize;\n"
279    "}\n"
280    "\n"
281    "@Override\n"
282    "public int getSerializedSize() {\n"
283    "  int size = 0;\n");
284  printer->Indent();
285
286  for (int i = 0; i < descriptor_->field_count(); i++) {
287    field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
288  }
289
290  if (params_.store_unknown_fields()) {
291    printer->Print(
292      "size += com.google.protobuf.nano.WireFormatNano.computeWireSize(unknownFieldData);\n");
293  }
294
295  printer->Outdent();
296  printer->Print(
297    "  cachedSize = size;\n"
298    "  return size;\n"
299    "}\n");
300}
301
302void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
303  scoped_array<const FieldDescriptor*> sorted_fields(
304    SortFieldsByNumber(descriptor_));
305
306  printer->Print(
307    "\n"
308    "@Override\n"
309    "public $classname$ mergeFrom(\n"
310    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
311    "    throws java.io.IOException {\n",
312    "classname", descriptor_->name());
313
314  printer->Indent();
315
316  printer->Print(
317    "while (true) {\n");
318  printer->Indent();
319
320  printer->Print(
321    "int tag = input.readTag();\n"
322    "switch (tag) {\n");
323  printer->Indent();
324
325  printer->Print(
326    "case 0:\n"          // zero signals EOF / limit reached
327    "  return this;\n"
328    "default: {\n");
329
330  printer->Indent();
331  if (params_.store_unknown_fields()) {
332    printer->Print(
333        "if (unknownFieldData == null) {\n"
334        "  unknownFieldData =\n"
335        "      new java.util.ArrayList<com.google.protobuf.nano.UnknownFieldData>();\n"
336        "}\n"
337        "if (!com.google.protobuf.nano.WireFormatNano.storeUnknownField(\n"
338        "    unknownFieldData, input, tag)) {\n"
339        "  return this;\n"
340        "}\n");
341  } else {
342    printer->Print(
343        "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
344        "  return this;\n"   // it's an endgroup tag
345        "}\n");
346  }
347  printer->Print("break;\n");
348  printer->Outdent();
349  printer->Print("}\n");
350
351  for (int i = 0; i < descriptor_->field_count(); i++) {
352    const FieldDescriptor* field = sorted_fields[i];
353    uint32 tag = WireFormatLite::MakeTag(field->number(),
354      WireFormat::WireTypeForField(field));
355
356    printer->Print(
357      "case $tag$: {\n",
358      "tag", SimpleItoa(tag));
359    printer->Indent();
360
361    field_generators_.get(field).GenerateMergingCode(printer);
362
363    printer->Outdent();
364    printer->Print(
365      "  break;\n"
366      "}\n");
367  }
368
369  printer->Outdent();
370  printer->Outdent();
371  printer->Outdent();
372  printer->Print(
373    "    }\n"     // switch (tag)
374    "  }\n"       // while (true)
375    "}\n");
376}
377
378void MessageGenerator::
379GenerateParseFromMethods(io::Printer* printer) {
380  // Note:  These are separate from GenerateMessageSerializationMethods()
381  //   because they need to be generated even for messages that are optimized
382  //   for code size.
383  printer->Print(
384    "\n"
385    "public static $classname$ parseFrom(byte[] data)\n"
386    "    throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
387    "  return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
388    "}\n"
389    "\n"
390    "public static $classname$ parseFrom(\n"
391    "        com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
392    "    throws java.io.IOException {\n"
393    "  return new $classname$().mergeFrom(input);\n"
394    "}\n",
395    "classname", descriptor_->name());
396}
397
398void MessageGenerator::GenerateSerializeOneField(
399    io::Printer* printer, const FieldDescriptor* field) {
400  field_generators_.get(field).GenerateSerializationCode(printer);
401}
402
403void MessageGenerator::GenerateClear(io::Printer* printer) {
404  printer->Print(
405    "\n"
406    "public $classname$ clear() {\n",
407    "classname", descriptor_->name());
408  printer->Indent();
409
410  // Clear bit fields.
411  int totalInts = (field_generators_.total_bits() + 31) / 32;
412  for (int i = 0; i < totalInts; i++) {
413    printer->Print("$bit_field_name$ = 0;\n",
414      "bit_field_name", GetBitFieldName(i));
415  }
416
417  // Call clear for all of the fields.
418  for (int i = 0; i < descriptor_->field_count(); i++) {
419    const FieldDescriptor* field = descriptor_->field(i);
420    field_generators_.get(field).GenerateClearCode(printer);
421  }
422
423  // Clear unknown fields.
424  if (params_.store_unknown_fields()) {
425    printer->Print("unknownFieldData = null;\n");
426  }
427
428  printer->Outdent();
429  printer->Print(
430    "  cachedSize = -1;\n"
431    "  return this;\n"
432    "}\n");
433}
434
435void MessageGenerator::GenerateEquals(io::Printer* printer) {
436  // Don't override if there are no fields. We could generate an
437  // equals method that compares types, but often empty messages
438  // are used as namespaces.
439  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
440    return;
441  }
442
443  printer->Print(
444    "\n"
445    "@Override\n"
446    "public boolean equals(Object o) {\n");
447  printer->Indent();
448  printer->Print(
449    "if (o == this) {\n"
450    "  return true;\n"
451    "}\n"
452    "if (!(o instanceof $classname$)) {\n"
453    "  return false;\n"
454    "}\n"
455    "$classname$ other = ($classname$) o;\n",
456    "classname", descriptor_->name());
457
458  for (int i = 0; i < descriptor_->field_count(); i++) {
459    const FieldDescriptor* field = descriptor_->field(i);
460    field_generators_.get(field).GenerateEqualsCode(printer);
461  }
462
463  if (params_.store_unknown_fields()) {
464    printer->Print(
465      "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
466      "  return other.unknownFieldData == null || other.unknownFieldData.isEmpty();"
467      "} else {\n"
468      "  return unknownFieldData.equals(other.unknownFieldData);\n"
469      "}\n");
470  } else {
471    printer->Print(
472      "return true;\n");
473  }
474
475  printer->Outdent();
476  printer->Print("}\n");
477}
478
479void MessageGenerator::GenerateHashCode(io::Printer* printer) {
480  if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
481    return;
482  }
483
484  printer->Print(
485    "\n"
486    "@Override\n"
487    "public int hashCode() {\n");
488  printer->Indent();
489
490  printer->Print("int result = 17;\n");
491  for (int i = 0; i < descriptor_->field_count(); i++) {
492    const FieldDescriptor* field = descriptor_->field(i);
493    field_generators_.get(field).GenerateHashCodeCode(printer);
494  }
495
496  if (params_.store_unknown_fields()) {
497    printer->Print(
498      "result = 31 * result + (unknownFieldData == null || unknownFieldData.isEmpty()\n"
499      "    ? 0 : unknownFieldData.hashCode());\n");
500  }
501
502  printer->Print("return result;\n");
503
504  printer->Outdent();
505  printer->Print("}\n");
506}
507
508// ===================================================================
509
510}  // namespace javanano
511}  // namespace compiler
512}  // namespace protobuf
513}  // namespace google
514