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/java/java_enum_field.h>
39 #include <google/protobuf/compiler/java/java_doc_comment.h>
40 #include <google/protobuf/stubs/common.h>
41 #include <google/protobuf/compiler/java/java_helpers.h>
42 #include <google/protobuf/io/printer.h>
43 #include <google/protobuf/wire_format.h>
44 #include <google/protobuf/stubs/strutil.h>
45
46 namespace google {
47 namespace protobuf {
48 namespace compiler {
49 namespace java {
50
51 namespace {
52
53 // TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
54 // repeat code between this and the other field types.
SetEnumVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,map<string,string> * variables)55 void SetEnumVariables(const FieldDescriptor* descriptor,
56 int messageBitIndex,
57 int builderBitIndex,
58 map<string, string>* variables) {
59 (*variables)["name"] =
60 UnderscoresToCamelCase(descriptor);
61 (*variables)["capitalized_name"] =
62 UnderscoresToCapitalizedCamelCase(descriptor);
63 (*variables)["constant_name"] = FieldConstantName(descriptor);
64 (*variables)["number"] = SimpleItoa(descriptor->number());
65 (*variables)["type"] = ClassName(descriptor->enum_type());
66 (*variables)["default"] = DefaultValue(descriptor);
67 (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
68 (*variables)["tag_size"] = SimpleItoa(
69 internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
70 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
71 // by the proto compiler
72 (*variables)["deprecation"] = descriptor->options().deprecated()
73 ? "@java.lang.Deprecated " : "";
74 (*variables)["on_changed"] =
75 HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
76
77 // For singular messages and builders, one bit is used for the hasField bit.
78 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
79 (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
80
81 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
82 (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
83 (*variables)["clear_has_field_bit_builder"] =
84 GenerateClearBit(builderBitIndex);
85
86 // For repated builders, one bit is used for whether the array is immutable.
87 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
88 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
89 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
90
91 // For repeated fields, one bit is used for whether the array is immutable
92 // in the parsing constructor.
93 (*variables)["get_mutable_bit_parser"] =
94 GenerateGetBitMutableLocal(builderBitIndex);
95 (*variables)["set_mutable_bit_parser"] =
96 GenerateSetBitMutableLocal(builderBitIndex);
97
98 (*variables)["get_has_field_bit_from_local"] =
99 GenerateGetBitFromLocal(builderBitIndex);
100 (*variables)["set_has_field_bit_to_local"] =
101 GenerateSetBitToLocal(messageBitIndex);
102 }
103
104 } // namespace
105
106 // ===================================================================
107
108 EnumFieldGenerator::
EnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex)109 EnumFieldGenerator(const FieldDescriptor* descriptor,
110 int messageBitIndex,
111 int builderBitIndex)
112 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
113 builderBitIndex_(builderBitIndex) {
114 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
115 }
116
~EnumFieldGenerator()117 EnumFieldGenerator::~EnumFieldGenerator() {}
118
GetNumBitsForMessage() const119 int EnumFieldGenerator::GetNumBitsForMessage() const {
120 return 1;
121 }
122
GetNumBitsForBuilder() const123 int EnumFieldGenerator::GetNumBitsForBuilder() const {
124 return 1;
125 }
126
127 void EnumFieldGenerator::
GenerateInterfaceMembers(io::Printer * printer) const128 GenerateInterfaceMembers(io::Printer* printer) const {
129 WriteFieldDocComment(printer, descriptor_);
130 printer->Print(variables_,
131 "$deprecation$boolean has$capitalized_name$();\n");
132 WriteFieldDocComment(printer, descriptor_);
133 printer->Print(variables_,
134 "$deprecation$$type$ get$capitalized_name$();\n");
135 }
136
137 void EnumFieldGenerator::
GenerateMembers(io::Printer * printer) const138 GenerateMembers(io::Printer* printer) const {
139 printer->Print(variables_,
140 "private $type$ $name$_;\n");
141 WriteFieldDocComment(printer, descriptor_);
142 printer->Print(variables_,
143 "$deprecation$public boolean has$capitalized_name$() {\n"
144 " return $get_has_field_bit_message$;\n"
145 "}\n");
146 WriteFieldDocComment(printer, descriptor_);
147 printer->Print(variables_,
148 "$deprecation$public $type$ get$capitalized_name$() {\n"
149 " return $name$_;\n"
150 "}\n");
151 }
152
153 void EnumFieldGenerator::
GenerateBuilderMembers(io::Printer * printer) const154 GenerateBuilderMembers(io::Printer* printer) const {
155 printer->Print(variables_,
156 "private $type$ $name$_ = $default$;\n");
157 WriteFieldDocComment(printer, descriptor_);
158 printer->Print(variables_,
159 "$deprecation$public boolean has$capitalized_name$() {\n"
160 " return $get_has_field_bit_builder$;\n"
161 "}\n");
162 WriteFieldDocComment(printer, descriptor_);
163 printer->Print(variables_,
164 "$deprecation$public $type$ get$capitalized_name$() {\n"
165 " return $name$_;\n"
166 "}\n");
167 WriteFieldDocComment(printer, descriptor_);
168 printer->Print(variables_,
169 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
170 " if (value == null) {\n"
171 " throw new NullPointerException();\n"
172 " }\n"
173 " $set_has_field_bit_builder$;\n"
174 " $name$_ = value;\n"
175 " $on_changed$\n"
176 " return this;\n"
177 "}\n");
178 WriteFieldDocComment(printer, descriptor_);
179 printer->Print(variables_,
180 "$deprecation$public Builder clear$capitalized_name$() {\n"
181 " $clear_has_field_bit_builder$;\n"
182 " $name$_ = $default$;\n"
183 " $on_changed$\n"
184 " return this;\n"
185 "}\n");
186 }
187
188 void EnumFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const189 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
190 // noop for enums
191 }
192
193 void EnumFieldGenerator::
GenerateInitializationCode(io::Printer * printer) const194 GenerateInitializationCode(io::Printer* printer) const {
195 printer->Print(variables_, "$name$_ = $default$;\n");
196 }
197
198 void EnumFieldGenerator::
GenerateBuilderClearCode(io::Printer * printer) const199 GenerateBuilderClearCode(io::Printer* printer) const {
200 printer->Print(variables_,
201 "$name$_ = $default$;\n"
202 "$clear_has_field_bit_builder$;\n");
203 }
204
205 void EnumFieldGenerator::
GenerateMergingCode(io::Printer * printer) const206 GenerateMergingCode(io::Printer* printer) const {
207 printer->Print(variables_,
208 "if (other.has$capitalized_name$()) {\n"
209 " set$capitalized_name$(other.get$capitalized_name$());\n"
210 "}\n");
211 }
212
213 void EnumFieldGenerator::
GenerateBuildingCode(io::Printer * printer) const214 GenerateBuildingCode(io::Printer* printer) const {
215 printer->Print(variables_,
216 "if ($get_has_field_bit_from_local$) {\n"
217 " $set_has_field_bit_to_local$;\n"
218 "}\n"
219 "result.$name$_ = $name$_;\n");
220 }
221
222 void EnumFieldGenerator::
GenerateParsingCode(io::Printer * printer) const223 GenerateParsingCode(io::Printer* printer) const {
224 printer->Print(variables_,
225 "int rawValue = input.readEnum();\n"
226 "$type$ value = $type$.valueOf(rawValue);\n");
227 if (HasUnknownFields(descriptor_->containing_type())) {
228 printer->Print(variables_,
229 "if (value == null) {\n"
230 " unknownFields.mergeVarintField($number$, rawValue);\n"
231 "} else {\n");
232 } else {
233 printer->Print(variables_,
234 "if (value != null) {\n");
235 }
236 printer->Print(variables_,
237 " $set_has_field_bit_message$;\n"
238 " $name$_ = value;\n"
239 "}\n");
240 }
241
242 void EnumFieldGenerator::
GenerateParsingDoneCode(io::Printer * printer) const243 GenerateParsingDoneCode(io::Printer* printer) const {
244 // noop for enums
245 }
246
247 void EnumFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const248 GenerateSerializationCode(io::Printer* printer) const {
249 printer->Print(variables_,
250 "if ($get_has_field_bit_message$) {\n"
251 " output.writeEnum($number$, $name$_.getNumber());\n"
252 "}\n");
253 }
254
255 void EnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const256 GenerateSerializedSizeCode(io::Printer* printer) const {
257 printer->Print(variables_,
258 "if ($get_has_field_bit_message$) {\n"
259 " size += com.google.protobuf.CodedOutputStream\n"
260 " .computeEnumSize($number$, $name$_.getNumber());\n"
261 "}\n");
262 }
263
264 void EnumFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const265 GenerateEqualsCode(io::Printer* printer) const {
266 printer->Print(variables_,
267 "result = result &&\n"
268 " (get$capitalized_name$() == other.get$capitalized_name$());\n");
269 }
270
271 void EnumFieldGenerator::
GenerateHashCode(io::Printer * printer) const272 GenerateHashCode(io::Printer* printer) const {
273 printer->Print(variables_,
274 "hash = (37 * hash) + $constant_name$;\n"
275 "hash = (53 * hash) + hashEnum(get$capitalized_name$());\n");
276 }
277
GetBoxedType() const278 string EnumFieldGenerator::GetBoxedType() const {
279 return ClassName(descriptor_->enum_type());
280 }
281
282 // ===================================================================
283
284 RepeatedEnumFieldGenerator::
RepeatedEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex)285 RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
286 int messageBitIndex,
287 int builderBitIndex)
288 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
289 builderBitIndex_(builderBitIndex) {
290 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
291 }
292
~RepeatedEnumFieldGenerator()293 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
294
GetNumBitsForMessage() const295 int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const {
296 return 0;
297 }
298
GetNumBitsForBuilder() const299 int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const {
300 return 1;
301 }
302
303 void RepeatedEnumFieldGenerator::
GenerateInterfaceMembers(io::Printer * printer) const304 GenerateInterfaceMembers(io::Printer* printer) const {
305 WriteFieldDocComment(printer, descriptor_);
306 printer->Print(variables_,
307 "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
308 WriteFieldDocComment(printer, descriptor_);
309 printer->Print(variables_,
310 "$deprecation$int get$capitalized_name$Count();\n");
311 WriteFieldDocComment(printer, descriptor_);
312 printer->Print(variables_,
313 "$deprecation$$type$ get$capitalized_name$(int index);\n");
314 }
315
316 void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer * printer) const317 GenerateMembers(io::Printer* printer) const {
318 printer->Print(variables_,
319 "private java.util.List<$type$> $name$_;\n");
320 WriteFieldDocComment(printer, descriptor_);
321 printer->Print(variables_,
322 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
323 " return $name$_;\n" // note: unmodifiable list
324 "}\n");
325 WriteFieldDocComment(printer, descriptor_);
326 printer->Print(variables_,
327 "$deprecation$public int get$capitalized_name$Count() {\n"
328 " return $name$_.size();\n"
329 "}\n");
330 WriteFieldDocComment(printer, descriptor_);
331 printer->Print(variables_,
332 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
333 " return $name$_.get(index);\n"
334 "}\n");
335
336 if (descriptor_->options().packed() &&
337 HasGeneratedMethods(descriptor_->containing_type())) {
338 printer->Print(variables_,
339 "private int $name$MemoizedSerializedSize;\n");
340 }
341 }
342
343 void RepeatedEnumFieldGenerator::
GenerateBuilderMembers(io::Printer * printer) const344 GenerateBuilderMembers(io::Printer* printer) const {
345 printer->Print(variables_,
346 // One field is the list and the other field keeps track of whether the
347 // list is immutable. If it's immutable, the invariant is that it must
348 // either an instance of Collections.emptyList() or it's an ArrayList
349 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
350 // a refererence to the underlying ArrayList. This invariant allows us to
351 // share instances of lists between protocol buffers avoiding expensive
352 // memory allocations. Note, immutable is a strong guarantee here -- not
353 // just that the list cannot be modified via the reference but that the
354 // list can never be modified.
355 "private java.util.List<$type$> $name$_ =\n"
356 " java.util.Collections.emptyList();\n"
357
358 "private void ensure$capitalized_name$IsMutable() {\n"
359 " if (!$get_mutable_bit_builder$) {\n"
360 " $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
361 " $set_mutable_bit_builder$;\n"
362 " }\n"
363 "}\n");
364
365 WriteFieldDocComment(printer, descriptor_);
366 printer->Print(variables_,
367 // Note: We return an unmodifiable list because otherwise the caller
368 // could hold on to the returned list and modify it after the message
369 // has been built, thus mutating the message which is supposed to be
370 // immutable.
371 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
372 " return java.util.Collections.unmodifiableList($name$_);\n"
373 "}\n");
374 WriteFieldDocComment(printer, descriptor_);
375 printer->Print(variables_,
376 "$deprecation$public int get$capitalized_name$Count() {\n"
377 " return $name$_.size();\n"
378 "}\n");
379 WriteFieldDocComment(printer, descriptor_);
380 printer->Print(variables_,
381 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
382 " return $name$_.get(index);\n"
383 "}\n");
384 WriteFieldDocComment(printer, descriptor_);
385 printer->Print(variables_,
386 "$deprecation$public Builder set$capitalized_name$(\n"
387 " int index, $type$ value) {\n"
388 " if (value == null) {\n"
389 " throw new NullPointerException();\n"
390 " }\n"
391 " ensure$capitalized_name$IsMutable();\n"
392 " $name$_.set(index, value);\n"
393 " $on_changed$\n"
394 " return this;\n"
395 "}\n");
396 WriteFieldDocComment(printer, descriptor_);
397 printer->Print(variables_,
398 "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
399 " if (value == null) {\n"
400 " throw new NullPointerException();\n"
401 " }\n"
402 " ensure$capitalized_name$IsMutable();\n"
403 " $name$_.add(value);\n"
404 " $on_changed$\n"
405 " return this;\n"
406 "}\n");
407 WriteFieldDocComment(printer, descriptor_);
408 printer->Print(variables_,
409 "$deprecation$public Builder addAll$capitalized_name$(\n"
410 " java.lang.Iterable<? extends $type$> values) {\n"
411 " ensure$capitalized_name$IsMutable();\n"
412 " super.addAll(values, $name$_);\n"
413 " $on_changed$\n"
414 " return this;\n"
415 "}\n");
416 WriteFieldDocComment(printer, descriptor_);
417 printer->Print(variables_,
418 "$deprecation$public Builder clear$capitalized_name$() {\n"
419 " $name$_ = java.util.Collections.emptyList();\n"
420 " $clear_mutable_bit_builder$;\n"
421 " $on_changed$\n"
422 " return this;\n"
423 "}\n");
424 }
425
426 void RepeatedEnumFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const427 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
428 // noop for enums
429 }
430
431 void RepeatedEnumFieldGenerator::
GenerateInitializationCode(io::Printer * printer) const432 GenerateInitializationCode(io::Printer* printer) const {
433 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
434 }
435
436 void RepeatedEnumFieldGenerator::
GenerateBuilderClearCode(io::Printer * printer) const437 GenerateBuilderClearCode(io::Printer* printer) const {
438 printer->Print(variables_,
439 "$name$_ = java.util.Collections.emptyList();\n"
440 "$clear_mutable_bit_builder$;\n");
441 }
442
443 void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer * printer) const444 GenerateMergingCode(io::Printer* printer) const {
445 // The code below does two optimizations:
446 // 1. If the other list is empty, there's nothing to do. This ensures we
447 // don't allocate a new array if we already have an immutable one.
448 // 2. If the other list is non-empty and our current list is empty, we can
449 // reuse the other list which is guaranteed to be immutable.
450 printer->Print(variables_,
451 "if (!other.$name$_.isEmpty()) {\n"
452 " if ($name$_.isEmpty()) {\n"
453 " $name$_ = other.$name$_;\n"
454 " $clear_mutable_bit_builder$;\n"
455 " } else {\n"
456 " ensure$capitalized_name$IsMutable();\n"
457 " $name$_.addAll(other.$name$_);\n"
458 " }\n"
459 " $on_changed$\n"
460 "}\n");
461 }
462
463 void RepeatedEnumFieldGenerator::
GenerateBuildingCode(io::Printer * printer) const464 GenerateBuildingCode(io::Printer* printer) const {
465 // The code below ensures that the result has an immutable list. If our
466 // list is immutable, we can just reuse it. If not, we make it immutable.
467 printer->Print(variables_,
468 "if ($get_mutable_bit_builder$) {\n"
469 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
470 " $clear_mutable_bit_builder$;\n"
471 "}\n"
472 "result.$name$_ = $name$_;\n");
473 }
474
475 void RepeatedEnumFieldGenerator::
GenerateParsingCode(io::Printer * printer) const476 GenerateParsingCode(io::Printer* printer) const {
477 // Read and store the enum
478 printer->Print(variables_,
479 "int rawValue = input.readEnum();\n"
480 "$type$ value = $type$.valueOf(rawValue);\n");
481 if (HasUnknownFields(descriptor_->containing_type())) {
482 printer->Print(variables_,
483 "if (value == null) {\n"
484 " unknownFields.mergeVarintField($number$, rawValue);\n"
485 "} else {\n");
486 } else {
487 printer->Print(variables_,
488 "if (value != null) {\n");
489 }
490 printer->Print(variables_,
491 " if (!$get_mutable_bit_parser$) {\n"
492 " $name$_ = new java.util.ArrayList<$type$>();\n"
493 " $set_mutable_bit_parser$;\n"
494 " }\n"
495 " $name$_.add(value);\n"
496 "}\n");
497 }
498
499 void RepeatedEnumFieldGenerator::
GenerateParsingCodeFromPacked(io::Printer * printer) const500 GenerateParsingCodeFromPacked(io::Printer* printer) const {
501 // Wrap GenerateParsingCode's contents with a while loop.
502
503 printer->Print(variables_,
504 "int length = input.readRawVarint32();\n"
505 "int oldLimit = input.pushLimit(length);\n"
506 "while(input.getBytesUntilLimit() > 0) {\n");
507 printer->Indent();
508
509 GenerateParsingCode(printer);
510
511 printer->Outdent();
512 printer->Print(variables_,
513 "}\n"
514 "input.popLimit(oldLimit);\n");
515 }
516
517 void RepeatedEnumFieldGenerator::
GenerateParsingDoneCode(io::Printer * printer) const518 GenerateParsingDoneCode(io::Printer* printer) const {
519 printer->Print(variables_,
520 "if ($get_mutable_bit_parser$) {\n"
521 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
522 "}\n");
523 }
524
525 void RepeatedEnumFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const526 GenerateSerializationCode(io::Printer* printer) const {
527 if (descriptor_->options().packed()) {
528 printer->Print(variables_,
529 "if (get$capitalized_name$List().size() > 0) {\n"
530 " output.writeRawVarint32($tag$);\n"
531 " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
532 "}\n"
533 "for (int i = 0; i < $name$_.size(); i++) {\n"
534 " output.writeEnumNoTag($name$_.get(i).getNumber());\n"
535 "}\n");
536 } else {
537 printer->Print(variables_,
538 "for (int i = 0; i < $name$_.size(); i++) {\n"
539 " output.writeEnum($number$, $name$_.get(i).getNumber());\n"
540 "}\n");
541 }
542 }
543
544 void RepeatedEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const545 GenerateSerializedSizeCode(io::Printer* printer) const {
546 printer->Print(variables_,
547 "{\n"
548 " int dataSize = 0;\n");
549 printer->Indent();
550
551 printer->Print(variables_,
552 "for (int i = 0; i < $name$_.size(); i++) {\n"
553 " dataSize += com.google.protobuf.CodedOutputStream\n"
554 " .computeEnumSizeNoTag($name$_.get(i).getNumber());\n"
555 "}\n");
556 printer->Print(
557 "size += dataSize;\n");
558 if (descriptor_->options().packed()) {
559 printer->Print(variables_,
560 "if (!get$capitalized_name$List().isEmpty()) {"
561 " size += $tag_size$;\n"
562 " size += com.google.protobuf.CodedOutputStream\n"
563 " .computeRawVarint32Size(dataSize);\n"
564 "}");
565 } else {
566 printer->Print(variables_,
567 "size += $tag_size$ * $name$_.size();\n");
568 }
569
570 // cache the data size for packed fields.
571 if (descriptor_->options().packed()) {
572 printer->Print(variables_,
573 "$name$MemoizedSerializedSize = dataSize;\n");
574 }
575
576 printer->Outdent();
577 printer->Print("}\n");
578 }
579
580 void RepeatedEnumFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const581 GenerateEqualsCode(io::Printer* printer) const {
582 printer->Print(variables_,
583 "result = result && get$capitalized_name$List()\n"
584 " .equals(other.get$capitalized_name$List());\n");
585 }
586
587 void RepeatedEnumFieldGenerator::
GenerateHashCode(io::Printer * printer) const588 GenerateHashCode(io::Printer* printer) const {
589 printer->Print(variables_,
590 "if (get$capitalized_name$Count() > 0) {\n"
591 " hash = (37 * hash) + $constant_name$;\n"
592 " hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n"
593 "}\n");
594 }
595
GetBoxedType() const596 string RepeatedEnumFieldGenerator::GetBoxedType() const {
597 return ClassName(descriptor_->enum_type());
598 }
599
600 } // namespace java
601 } // namespace compiler
602 } // namespace protobuf
603 } // namespace google
604