1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
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>
53 // TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
54 // repeat code between this and the other field types.
55 void SetEnumVariables(const FieldDescriptor* descriptor,
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();" : "";
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);
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);
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);
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);
98 (*variables)["get_has_field_bit_from_local"] =
99 GenerateGetBitFromLocal(builderBitIndex);
100 (*variables)["set_has_field_bit_to_local"] =
101 GenerateSetBitToLocal(messageBitIndex);
106 // ===================================================================
109 EnumFieldGenerator(const FieldDescriptor* descriptor,
112 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
113 builderBitIndex_(builderBitIndex) {
114 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
117 EnumFieldGenerator::~EnumFieldGenerator() {}
119 int EnumFieldGenerator::GetNumBitsForMessage() const {
123 int EnumFieldGenerator::GetNumBitsForBuilder() const {
127 void EnumFieldGenerator::
128 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");
137 void EnumFieldGenerator::
138 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"
146 WriteFieldDocComment(printer, descriptor_);
147 printer->Print(variables_,
148 "$deprecation$public $type$ get$capitalized_name$() {\n"
153 void EnumFieldGenerator::
154 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"
162 WriteFieldDocComment(printer, descriptor_);
163 printer->Print(variables_,
164 "$deprecation$public $type$ get$capitalized_name$() {\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"
173 " $set_has_field_bit_builder$;\n"
174 " $name$_ = value;\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"
188 void EnumFieldGenerator::
189 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
193 void EnumFieldGenerator::
194 GenerateInitializationCode(io::Printer* printer) const {
195 printer->Print(variables_, "$name$_ = $default$;\n");
198 void EnumFieldGenerator::
199 GenerateBuilderClearCode(io::Printer* printer) const {
200 printer->Print(variables_,
201 "$name$_ = $default$;\n"
202 "$clear_has_field_bit_builder$;\n");
205 void EnumFieldGenerator::
206 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"
213 void EnumFieldGenerator::
214 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"
219 "result.$name$_ = $name$_;\n");
222 void EnumFieldGenerator::
223 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"
233 printer->Print(variables_,
234 "if (value != null) {\n");
236 printer->Print(variables_,
237 " $set_has_field_bit_message$;\n"
238 " $name$_ = value;\n"
242 void EnumFieldGenerator::
243 GenerateParsingDoneCode(io::Printer* printer) const {
247 void EnumFieldGenerator::
248 GenerateSerializationCode(io::Printer* printer) const {
249 printer->Print(variables_,
250 "if ($get_has_field_bit_message$) {\n"
251 " output.writeEnum($number$, $name$_.getNumber());\n"
255 void EnumFieldGenerator::
256 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"
264 void EnumFieldGenerator::
265 GenerateEqualsCode(io::Printer* printer) const {
266 printer->Print(variables_,
267 "result = result &&\n"
268 " (get$capitalized_name$() == other.get$capitalized_name$());\n");
271 void EnumFieldGenerator::
272 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");
278 string EnumFieldGenerator::GetBoxedType() const {
279 return ClassName(descriptor_->enum_type());
282 // ===================================================================
284 RepeatedEnumFieldGenerator::
285 RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
288 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
289 builderBitIndex_(builderBitIndex) {
290 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
293 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
295 int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const {
299 int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const {
303 void RepeatedEnumFieldGenerator::
304 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");
316 void RepeatedEnumFieldGenerator::
317 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
325 WriteFieldDocComment(printer, descriptor_);
326 printer->Print(variables_,
327 "$deprecation$public int get$capitalized_name$Count() {\n"
328 " return $name$_.size();\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"
336 if (descriptor_->options().packed() &&
337 HasGeneratedMethods(descriptor_->containing_type())) {
338 printer->Print(variables_,
339 "private int $name$MemoizedSerializedSize;\n");
343 void RepeatedEnumFieldGenerator::
344 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"
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"
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
371 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
372 " return java.util.Collections.unmodifiableList($name$_);\n"
374 WriteFieldDocComment(printer, descriptor_);
375 printer->Print(variables_,
376 "$deprecation$public int get$capitalized_name$Count() {\n"
377 " return $name$_.size();\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"
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"
391 " ensure$capitalized_name$IsMutable();\n"
392 " $name$_.set(index, value);\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"
402 " ensure$capitalized_name$IsMutable();\n"
403 " $name$_.add(value);\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"
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"
426 void RepeatedEnumFieldGenerator::
427 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
431 void RepeatedEnumFieldGenerator::
432 GenerateInitializationCode(io::Printer* printer) const {
433 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
436 void RepeatedEnumFieldGenerator::
437 GenerateBuilderClearCode(io::Printer* printer) const {
438 printer->Print(variables_,
439 "$name$_ = java.util.Collections.emptyList();\n"
440 "$clear_mutable_bit_builder$;\n");
443 void RepeatedEnumFieldGenerator::
444 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"
456 " ensure$capitalized_name$IsMutable();\n"
457 " $name$_.addAll(other.$name$_);\n"
463 void RepeatedEnumFieldGenerator::
464 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"
472 "result.$name$_ = $name$_;\n");
475 void RepeatedEnumFieldGenerator::
476 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"
487 printer->Print(variables_,
488 "if (value != null) {\n");
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"
495 " $name$_.add(value);\n"
499 void RepeatedEnumFieldGenerator::
500 GenerateParsingCodeFromPacked(io::Printer* printer) const {
501 // Wrap GenerateParsingCode's contents with a while loop.
503 printer->Print(variables_,
504 "int length = input.readRawVarint32();\n"
505 "int oldLimit = input.pushLimit(length);\n"
506 "while(input.getBytesUntilLimit() > 0) {\n");
509 GenerateParsingCode(printer);
512 printer->Print(variables_,
514 "input.popLimit(oldLimit);\n");
517 void RepeatedEnumFieldGenerator::
518 GenerateParsingDoneCode(io::Printer* printer) const {
519 printer->Print(variables_,
520 "if ($get_mutable_bit_parser$) {\n"
521 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
525 void RepeatedEnumFieldGenerator::
526 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"
533 "for (int i = 0; i < $name$_.size(); i++) {\n"
534 " output.writeEnumNoTag($name$_.get(i).getNumber());\n"
537 printer->Print(variables_,
538 "for (int i = 0; i < $name$_.size(); i++) {\n"
539 " output.writeEnum($number$, $name$_.get(i).getNumber());\n"
544 void RepeatedEnumFieldGenerator::
545 GenerateSerializedSizeCode(io::Printer* printer) const {
546 printer->Print(variables_,
548 " int dataSize = 0;\n");
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"
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"
566 printer->Print(variables_,
567 "size += $tag_size$ * $name$_.size();\n");
570 // cache the data size for packed fields.
571 if (descriptor_->options().packed()) {
572 printer->Print(variables_,
573 "$name$MemoizedSerializedSize = dataSize;\n");
577 printer->Print("}\n");
580 void RepeatedEnumFieldGenerator::
581 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");
587 void RepeatedEnumFieldGenerator::
588 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"
596 string RepeatedEnumFieldGenerator::GetBoxedType() const {
597 return ClassName(descriptor_->enum_type());
601 } // namespace compiler
602 } // namespace protobuf
603 } // namespace google