Line data Source code
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 <map>
36 : #include <string>
37 :
38 : #include <google/protobuf/compiler/javanano/javanano_enum_field.h>
39 : #include <google/protobuf/stubs/common.h>
40 : #include <google/protobuf/compiler/javanano/javanano_helpers.h>
41 : #include <google/protobuf/io/printer.h>
42 : #include <google/protobuf/wire_format.h>
43 : #include <google/protobuf/stubs/strutil.h>
44 :
45 : namespace google {
46 : namespace protobuf {
47 : namespace compiler {
48 : namespace javanano {
49 :
50 : namespace {
51 :
52 : // TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
53 : // repeat code between this and the other field types.
54 0 : void SetEnumVariables(const Params& params,
55 0 : const FieldDescriptor* descriptor, map<string, string>* variables) {
56 0 : (*variables)["name"] =
57 : RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
58 0 : (*variables)["capitalized_name"] =
59 : RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
60 0 : (*variables)["number"] = SimpleItoa(descriptor->number());
61 0 : if (params.use_reference_types_for_primitives()
62 0 : && !params.reftypes_primitive_enums()
63 0 : && !descriptor->is_repeated()) {
64 0 : (*variables)["type"] = "java.lang.Integer";
65 0 : (*variables)["default"] = "null";
66 : } else {
67 0 : (*variables)["type"] = "int";
68 0 : (*variables)["default"] = DefaultValue(params, descriptor);
69 : }
70 0 : (*variables)["repeated_default"] =
71 : "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
72 0 : (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
73 0 : (*variables)["tag_size"] = SimpleItoa(
74 : internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
75 0 : (*variables)["non_packed_tag"] = SimpleItoa(
76 : internal::WireFormatLite::MakeTag(descriptor->number(),
77 : internal::WireFormat::WireTypeForFieldType(descriptor->type())));
78 0 : (*variables)["message_name"] = descriptor->containing_type()->name();
79 0 : const EnumDescriptor* enum_type = descriptor->enum_type();
80 0 : (*variables)["message_type_intdef"] = "@"
81 0 : + ToJavaName(params, enum_type->name(), true,
82 : enum_type->containing_type(), enum_type->file());
83 0 : }
84 :
85 0 : void LoadEnumValues(const Params& params,
86 0 : const EnumDescriptor* enum_descriptor, vector<string>* canonical_values) {
87 0 : string enum_class_name = ClassName(params, enum_descriptor);
88 0 : for (int i = 0; i < enum_descriptor->value_count(); i++) {
89 0 : const EnumValueDescriptor* value = enum_descriptor->value(i);
90 : const EnumValueDescriptor* canonical_value =
91 0 : enum_descriptor->FindValueByNumber(value->number());
92 0 : if (value == canonical_value) {
93 : canonical_values->push_back(
94 0 : enum_class_name + "." + RenameJavaKeywords(value->name()));
95 : }
96 : }
97 0 : }
98 :
99 0 : void PrintCaseLabels(
100 0 : io::Printer* printer, const vector<string>& canonical_values) {
101 0 : for (int i = 0; i < canonical_values.size(); i++) {
102 : printer->Print(
103 : " case $value$:\n",
104 0 : "value", canonical_values[i]);
105 : }
106 0 : }
107 :
108 : } // namespace
109 :
110 : // ===================================================================
111 :
112 0 : EnumFieldGenerator::
113 0 : EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
114 0 : : FieldGenerator(params), descriptor_(descriptor) {
115 0 : SetEnumVariables(params, descriptor, &variables_);
116 0 : LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
117 0 : }
118 :
119 0 : EnumFieldGenerator::~EnumFieldGenerator() {}
120 :
121 0 : void EnumFieldGenerator::
122 : GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
123 0 : if (params_.generate_intdefs()) {
124 0 : printer->Print(variables_, "$message_type_intdef$\n");
125 : }
126 0 : printer->Print(variables_, "public $type$ $name$;\n");
127 :
128 0 : if (params_.generate_has()) {
129 : printer->Print(variables_,
130 0 : "public boolean has$capitalized_name$;\n");
131 : }
132 0 : }
133 :
134 0 : void EnumFieldGenerator::
135 : GenerateClearCode(io::Printer* printer) const {
136 : printer->Print(variables_,
137 0 : "$name$ = $default$;\n");
138 :
139 0 : if (params_.generate_has()) {
140 : printer->Print(variables_,
141 0 : "has$capitalized_name$ = false;\n");
142 : }
143 0 : }
144 :
145 0 : void EnumFieldGenerator::
146 : GenerateMergingCode(io::Printer* printer) const {
147 : printer->Print(variables_,
148 : "int value = input.readInt32();\n"
149 0 : "switch (value) {\n");
150 0 : PrintCaseLabels(printer, canonical_values_);
151 : printer->Print(variables_,
152 0 : " this.$name$ = value;\n");
153 0 : if (params_.generate_has()) {
154 : printer->Print(variables_,
155 0 : " has$capitalized_name$ = true;\n");
156 : }
157 : printer->Print(
158 : " break;\n"
159 0 : "}\n");
160 : // No default case: in case of invalid value from the wire, preserve old
161 : // field value. Also we are not storing the invalid value into the unknown
162 : // fields, because there is no way to get the value out.
163 0 : }
164 :
165 0 : void EnumFieldGenerator::
166 : GenerateSerializationCode(io::Printer* printer) const {
167 0 : if (descriptor_->is_required() && !params_.generate_has()) {
168 : // Always serialize a required field if we don't have the 'has' signal.
169 : printer->Print(variables_,
170 0 : "output.writeInt32($number$, this.$name$);\n");
171 : } else {
172 0 : if (params_.generate_has()) {
173 : printer->Print(variables_,
174 0 : "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
175 : } else {
176 : printer->Print(variables_,
177 0 : "if (this.$name$ != $default$) {\n");
178 : }
179 : printer->Print(variables_,
180 : " output.writeInt32($number$, this.$name$);\n"
181 0 : "}\n");
182 : }
183 0 : }
184 :
185 0 : void EnumFieldGenerator::
186 : GenerateSerializedSizeCode(io::Printer* printer) const {
187 0 : if (descriptor_->is_required() && !params_.generate_has()) {
188 : printer->Print(variables_,
189 : "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
190 0 : " .computeInt32Size($number$, this.$name$);\n");
191 : } else {
192 0 : if (params_.generate_has()) {
193 : printer->Print(variables_,
194 0 : "if (this.$name$ != $default$ || has$capitalized_name$) {\n");
195 : } else {
196 : printer->Print(variables_,
197 0 : "if (this.$name$ != $default$) {\n");
198 : }
199 : printer->Print(variables_,
200 : " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
201 : " .computeInt32Size($number$, this.$name$);\n"
202 0 : "}\n");
203 : }
204 0 : }
205 :
206 0 : void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const {
207 0 : if (params_.use_reference_types_for_primitives()
208 0 : && !params_.reftypes_primitive_enums()) {
209 : printer->Print(variables_,
210 : "if (this.$name$ == null) {\n"
211 : " if (other.$name$ != null) {\n"
212 : " return false;\n"
213 : " }\n"
214 : "} else if (!this.$name$.equals(other.$name$)) {\n"
215 : " return false;"
216 0 : "}\n");
217 : } else {
218 : // We define equality as serialized form equality. If generate_has(),
219 : // then if the field value equals the default value in both messages,
220 : // but one's 'has' field is set and the other's is not, the serialized
221 : // forms are different and we should return false.
222 : printer->Print(variables_,
223 0 : "if (this.$name$ != other.$name$");
224 0 : if (params_.generate_has()) {
225 : printer->Print(variables_,
226 : "\n"
227 : " || (this.$name$ == $default$\n"
228 0 : " && this.has$capitalized_name$ != other.has$capitalized_name$)");
229 : }
230 : printer->Print(") {\n"
231 : " return false;\n"
232 0 : "}\n");
233 : }
234 0 : }
235 :
236 0 : void EnumFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const {
237 : printer->Print(
238 0 : "result = 31 * result + ");
239 0 : if (params_.use_reference_types_for_primitives()
240 0 : && !params_.reftypes_primitive_enums()) {
241 : printer->Print(variables_,
242 0 : "(this.$name$ == null ? 0 : this.$name$)");
243 : } else {
244 : printer->Print(variables_,
245 0 : "this.$name$");
246 : }
247 0 : printer->Print(";\n");
248 0 : }
249 :
250 : // ===================================================================
251 :
252 0 : AccessorEnumFieldGenerator::
253 0 : AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
254 : const Params& params, int has_bit_index)
255 0 : : FieldGenerator(params), descriptor_(descriptor) {
256 0 : SetEnumVariables(params, descriptor, &variables_);
257 0 : LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
258 0 : SetBitOperationVariables("has", has_bit_index, &variables_);
259 0 : }
260 :
261 0 : AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
262 :
263 0 : void AccessorEnumFieldGenerator::
264 : GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
265 0 : printer->Print(variables_, "private int $name$_;\n");
266 0 : if (params_.generate_intdefs()) {
267 0 : printer->Print(variables_, "$message_type_intdef$\n");
268 : }
269 : printer->Print(variables_,
270 : "public int get$capitalized_name$() {\n"
271 : " return $name$_;\n"
272 : "}\n"
273 0 : "public $message_name$ set$capitalized_name$(");
274 0 : if (params_.generate_intdefs()) {
275 : printer->Print(variables_,
276 : "\n"
277 0 : " $message_type_intdef$ ");
278 : }
279 : printer->Print(variables_,
280 : "int value) {\n"
281 : " $name$_ = value;\n"
282 : " $set_has$;\n"
283 : " return this;\n"
284 : "}\n"
285 : "public boolean has$capitalized_name$() {\n"
286 : " return $get_has$;\n"
287 : "}\n"
288 : "public $message_name$ clear$capitalized_name$() {\n"
289 : " $name$_ = $default$;\n"
290 : " $clear_has$;\n"
291 : " return this;\n"
292 0 : "}\n");
293 0 : }
294 :
295 0 : void AccessorEnumFieldGenerator::
296 : GenerateClearCode(io::Printer* printer) const {
297 : printer->Print(variables_,
298 0 : "$name$_ = $default$;\n");
299 0 : }
300 :
301 0 : void AccessorEnumFieldGenerator::
302 : GenerateMergingCode(io::Printer* printer) const {
303 : printer->Print(variables_,
304 : "int value = input.readInt32();\n"
305 0 : "switch (value) {\n");
306 0 : PrintCaseLabels(printer, canonical_values_);
307 : printer->Print(variables_,
308 : " $name$_ = value;\n"
309 : " $set_has$;\n"
310 : " break;\n"
311 0 : "}\n");
312 : // No default case: in case of invalid value from the wire, preserve old
313 : // field value. Also we are not storing the invalid value into the unknown
314 : // fields, because there is no way to get the value out.
315 0 : }
316 :
317 0 : void AccessorEnumFieldGenerator::
318 : GenerateSerializationCode(io::Printer* printer) const {
319 : printer->Print(variables_,
320 : "if ($get_has$) {\n"
321 : " output.writeInt32($number$, $name$_);\n"
322 0 : "}\n");
323 0 : }
324 :
325 0 : void AccessorEnumFieldGenerator::
326 : GenerateSerializedSizeCode(io::Printer* printer) const {
327 : printer->Print(variables_,
328 : "if ($get_has$) {\n"
329 : " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
330 : " .computeInt32Size($number$, $name$_);\n"
331 0 : "}\n");
332 0 : }
333 :
334 0 : void AccessorEnumFieldGenerator::
335 : GenerateEqualsCode(io::Printer* printer) const {
336 : printer->Print(variables_,
337 : "if ($different_has$\n"
338 : " || $name$_ != other.$name$_) {\n"
339 : " return false;\n"
340 0 : "}\n");
341 0 : }
342 :
343 0 : void AccessorEnumFieldGenerator::
344 : GenerateHashCodeCode(io::Printer* printer) const {
345 : printer->Print(variables_,
346 0 : "result = 31 * result + $name$_;\n");
347 0 : }
348 :
349 : // ===================================================================
350 :
351 0 : RepeatedEnumFieldGenerator::
352 0 : RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
353 0 : : FieldGenerator(params), descriptor_(descriptor) {
354 0 : SetEnumVariables(params, descriptor, &variables_);
355 0 : LoadEnumValues(params, descriptor->enum_type(), &canonical_values_);
356 0 : }
357 :
358 0 : RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
359 :
360 0 : void RepeatedEnumFieldGenerator::
361 : GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
362 : printer->Print(variables_,
363 0 : "public $type$[] $name$;\n");
364 0 : }
365 :
366 0 : void RepeatedEnumFieldGenerator::
367 : GenerateClearCode(io::Printer* printer) const {
368 : printer->Print(variables_,
369 0 : "$name$ = $repeated_default$;\n");
370 0 : }
371 :
372 0 : void RepeatedEnumFieldGenerator::
373 : GenerateMergingCode(io::Printer* printer) const {
374 : // First, figure out the maximum length of the array, then parse,
375 : // and finally copy the valid values to the field.
376 : printer->Print(variables_,
377 : "int length = com.google.protobuf.nano.WireFormatNano\n"
378 : " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n"
379 : "int[] validValues = new int[length];\n"
380 : "int validCount = 0;\n"
381 : "for (int i = 0; i < length; i++) {\n"
382 : " if (i != 0) { // tag for first value already consumed.\n"
383 : " input.readTag();\n"
384 : " }\n"
385 : " int value = input.readInt32();\n"
386 0 : " switch (value) {\n");
387 0 : printer->Indent();
388 0 : PrintCaseLabels(printer, canonical_values_);
389 0 : printer->Outdent();
390 : printer->Print(variables_,
391 : " validValues[validCount++] = value;\n"
392 : " break;\n"
393 : " }\n"
394 : "}\n"
395 : "if (validCount != 0) {\n"
396 : " int i = this.$name$ == null ? 0 : this.$name$.length;\n"
397 : " if (i == 0 && validCount == validValues.length) {\n"
398 : " this.$name$ = validValues;\n"
399 : " } else {\n"
400 : " int[] newArray = new int[i + validCount];\n"
401 : " if (i != 0) {\n"
402 : " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
403 : " }\n"
404 : " java.lang.System.arraycopy(validValues, 0, newArray, i, validCount);\n"
405 : " this.$name$ = newArray;\n"
406 : " }\n"
407 0 : "}\n");
408 0 : }
409 :
410 0 : void RepeatedEnumFieldGenerator::
411 : GenerateMergingCodeFromPacked(io::Printer* printer) const {
412 : printer->Print(variables_,
413 : "int bytes = input.readRawVarint32();\n"
414 : "int limit = input.pushLimit(bytes);\n"
415 : "// First pass to compute array length.\n"
416 : "int arrayLength = 0;\n"
417 : "int startPos = input.getPosition();\n"
418 : "while (input.getBytesUntilLimit() > 0) {\n"
419 0 : " switch (input.readInt32()) {\n");
420 0 : printer->Indent();
421 0 : PrintCaseLabels(printer, canonical_values_);
422 0 : printer->Outdent();
423 : printer->Print(variables_,
424 : " arrayLength++;\n"
425 : " break;\n"
426 : " }\n"
427 : "}\n"
428 : "if (arrayLength != 0) {\n"
429 : " input.rewindToPosition(startPos);\n"
430 : " int i = this.$name$ == null ? 0 : this.$name$.length;\n"
431 : " int[] newArray = new int[i + arrayLength];\n"
432 : " if (i != 0) {\n"
433 : " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n"
434 : " }\n"
435 : " while (input.getBytesUntilLimit() > 0) {\n"
436 : " int value = input.readInt32();\n"
437 0 : " switch (value) {\n");
438 0 : printer->Indent();
439 0 : printer->Indent();
440 0 : PrintCaseLabels(printer, canonical_values_);
441 0 : printer->Outdent();
442 0 : printer->Outdent();
443 : printer->Print(variables_,
444 : " newArray[i++] = value;\n"
445 : " break;\n"
446 : " }\n"
447 : " }\n"
448 : " this.$name$ = newArray;\n"
449 : "}\n"
450 0 : "input.popLimit(limit);\n");
451 0 : }
452 :
453 0 : void RepeatedEnumFieldGenerator::
454 : GenerateRepeatedDataSizeCode(io::Printer* printer) const {
455 : // Creates a variable dataSize and puts the serialized size in there.
456 : printer->Print(variables_,
457 : "int dataSize = 0;\n"
458 : "for (int i = 0; i < this.$name$.length; i++) {\n"
459 : " int element = this.$name$[i];\n"
460 : " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
461 : " .computeInt32SizeNoTag(element);\n"
462 0 : "}\n");
463 0 : }
464 :
465 0 : void RepeatedEnumFieldGenerator::
466 : GenerateSerializationCode(io::Printer* printer) const {
467 : printer->Print(variables_,
468 0 : "if (this.$name$ != null && this.$name$.length > 0) {\n");
469 0 : printer->Indent();
470 :
471 0 : if (descriptor_->options().packed()) {
472 0 : GenerateRepeatedDataSizeCode(printer);
473 : printer->Print(variables_,
474 : "output.writeRawVarint32($tag$);\n"
475 : "output.writeRawVarint32(dataSize);\n"
476 : "for (int i = 0; i < this.$name$.length; i++) {\n"
477 : " output.writeRawVarint32(this.$name$[i]);\n"
478 0 : "}\n");
479 : } else {
480 : printer->Print(variables_,
481 : "for (int i = 0; i < this.$name$.length; i++) {\n"
482 : " output.writeInt32($number$, this.$name$[i]);\n"
483 0 : "}\n");
484 : }
485 :
486 0 : printer->Outdent();
487 : printer->Print(variables_,
488 0 : "}\n");
489 0 : }
490 :
491 0 : void RepeatedEnumFieldGenerator::
492 : GenerateSerializedSizeCode(io::Printer* printer) const {
493 : printer->Print(variables_,
494 0 : "if (this.$name$ != null && this.$name$.length > 0) {\n");
495 0 : printer->Indent();
496 :
497 0 : GenerateRepeatedDataSizeCode(printer);
498 :
499 : printer->Print(
500 0 : "size += dataSize;\n");
501 0 : if (descriptor_->options().packed()) {
502 : printer->Print(variables_,
503 : "size += $tag_size$;\n"
504 : "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
505 0 : " .computeRawVarint32Size(dataSize);\n");
506 : } else {
507 : printer->Print(variables_,
508 0 : "size += $tag_size$ * this.$name$.length;\n");
509 : }
510 :
511 0 : printer->Outdent();
512 :
513 : printer->Print(
514 0 : "}\n");
515 0 : }
516 :
517 0 : void RepeatedEnumFieldGenerator::
518 : GenerateFixClonedCode(io::Printer* printer) const {
519 : printer->Print(variables_,
520 : "if (this.$name$ != null && this.$name$.length > 0) {\n"
521 : " cloned.$name$ = this.$name$.clone();\n"
522 0 : "}\n");
523 0 : }
524 :
525 0 : void RepeatedEnumFieldGenerator::
526 : GenerateEqualsCode(io::Printer* printer) const {
527 : printer->Print(variables_,
528 : "if (!com.google.protobuf.nano.InternalNano.equals(\n"
529 : " this.$name$, other.$name$)) {\n"
530 : " return false;\n"
531 0 : "}\n");
532 0 : }
533 :
534 0 : void RepeatedEnumFieldGenerator::
535 : GenerateHashCodeCode(io::Printer* printer) const {
536 : printer->Print(variables_,
537 : "result = 31 * result\n"
538 0 : " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
539 0 : }
540 :
541 : } // namespace javanano
542 : } // namespace compiler
543 : } // namespace protobuf
544 : } // namespace google
|