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