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
47 namespace google {
48 namespace protobuf {
49 namespace compiler {
50 namespace javanano {
51
52 using internal::WireFormat;
53 using internal::WireFormatLite;
54
55 namespace {
56
57 struct FieldOrderingByNumber {
operator ()google::protobuf::compiler::javanano::__anon039cca180111::FieldOrderingByNumber58 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.
SortFieldsByNumber(const Descriptor * descriptor)66 const 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
MessageGenerator(const Descriptor * descriptor,const Params & params)81 MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
82 : params_(params),
83 descriptor_(descriptor),
84 field_generators_(descriptor, params) {
85 }
86
~MessageGenerator()87 MessageGenerator::~MessageGenerator() {}
88
GenerateStaticVariables(io::Printer * printer)89 void 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
GenerateStaticVariableInitializers(io::Printer * printer)98 void 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
Generate(io::Printer * printer)108 void 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
279 void MessageGenerator::
GenerateMessageSerializationMethods(io::Printer * printer)280 GenerateMessageSerializationMethods(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
GenerateMergeFromMethods(io::Printer * printer)328 void 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
417 void MessageGenerator::
GenerateParseFromMethods(io::Printer * printer)418 GenerateParseFromMethods(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
GenerateSerializeOneField(io::Printer * printer,const FieldDescriptor * field)437 void MessageGenerator::GenerateSerializeOneField(
438 io::Printer* printer, const FieldDescriptor* field) {
439 field_generators_.get(field).GenerateSerializationCode(printer);
440 }
441
GenerateClear(io::Printer * printer)442 void 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
GenerateEquals(io::Printer * printer)474 void 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 "return unknownFieldDataEquals(other);\n");
505 } else {
506 printer->Print(
507 "return true;\n");
508 }
509
510 printer->Outdent();
511 printer->Print("}\n");
512 }
513
GenerateHashCode(io::Printer * printer)514 void MessageGenerator::GenerateHashCode(io::Printer* printer) {
515 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
516 return;
517 }
518
519 printer->Print(
520 "\n"
521 "@Override\n"
522 "public int hashCode() {\n");
523 printer->Indent();
524
525 printer->Print("int result = 17;\n");
526 for (int i = 0; i < descriptor_->field_count(); i++) {
527 const FieldDescriptor* field = descriptor_->field(i);
528 field_generators_.get(field).GenerateHashCodeCode(printer);
529 }
530
531 if (params_.store_unknown_fields()) {
532 printer->Print(
533 "result = 31 * result + unknownFieldDataHashCode();\n");
534 }
535
536 printer->Print("return result;\n");
537
538 printer->Outdent();
539 printer->Print("}\n");
540 }
541
542 // ===================================================================
543
544 } // namespace javanano
545 } // namespace compiler
546 } // namespace protobuf
547 } // namespace google
548