blob: 72caa10b5dce172f7efc22f383e90e3f66d7f6f6 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
temporal40ee5512008-07-10 02:12:20 +00003// http://code.google.com/p/protobuf/
4//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
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/stubs/common.h>
40#include <google/protobuf/compiler/java/java_helpers.h>
41#include <google/protobuf/io/printer.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000042#include <google/protobuf/wire_format.h>
temporal40ee5512008-07-10 02:12:20 +000043#include <google/protobuf/stubs/strutil.h>
44
45namespace google {
46namespace protobuf {
47namespace compiler {
48namespace java {
49
50namespace {
51
52// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
53// repeat code between this and the other field types.
54void SetEnumVariables(const FieldDescriptor* descriptor,
liujisi@google.com33165fe2010-11-02 13:14:58 +000055 int messageBitIndex,
56 int builderBitIndex,
temporal40ee5512008-07-10 02:12:20 +000057 map<string, string>* variables) {
temporal40ee5512008-07-10 02:12:20 +000058 (*variables)["name"] =
59 UnderscoresToCamelCase(descriptor);
60 (*variables)["capitalized_name"] =
61 UnderscoresToCapitalizedCamelCase(descriptor);
liujisi@google.com33165fe2010-11-02 13:14:58 +000062 (*variables)["constant_name"] = FieldConstantName(descriptor);
temporal40ee5512008-07-10 02:12:20 +000063 (*variables)["number"] = SimpleItoa(descriptor->number());
kenton@google.com80b1d622009-07-29 01:13:20 +000064 (*variables)["type"] = ClassName(descriptor->enum_type());
65 (*variables)["default"] = DefaultValue(descriptor);
kenton@google.com2d6daa72009-01-22 01:27:00 +000066 (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
67 (*variables)["tag_size"] = SimpleItoa(
kenton@google.comfccb1462009-12-18 02:11:36 +000068 internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
liujisi@google.com33165fe2010-11-02 13:14:58 +000069 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
70 // by the proto compiler
71 (*variables)["deprecation"] = descriptor->options().deprecated()
72 ? "@java.lang.Deprecated " : "";
73 (*variables)["on_changed"] =
74 HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
75
76 // For singular messages and builders, one bit is used for the hasField bit.
77 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
78
79 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
80 (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
81 (*variables)["clear_has_field_bit_builder"] =
82 GenerateClearBit(builderBitIndex);
83
84 // For repated builders, one bit is used for whether the array is immutable.
85 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
86 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
87 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
88
89 (*variables)["get_has_field_bit_from_local"] =
90 GenerateGetBitFromLocal(builderBitIndex);
91 (*variables)["set_has_field_bit_to_local"] =
92 GenerateSetBitToLocal(messageBitIndex);
temporal40ee5512008-07-10 02:12:20 +000093}
94
95} // namespace
96
97// ===================================================================
98
99EnumFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000100EnumFieldGenerator(const FieldDescriptor* descriptor,
101 int messageBitIndex,
102 int builderBitIndex)
103 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
104 builderBitIndex_(builderBitIndex) {
105 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
temporal40ee5512008-07-10 02:12:20 +0000106}
107
108EnumFieldGenerator::~EnumFieldGenerator() {}
109
liujisi@google.com33165fe2010-11-02 13:14:58 +0000110int EnumFieldGenerator::GetNumBitsForMessage() const {
111 return 1;
112}
113
114int EnumFieldGenerator::GetNumBitsForBuilder() const {
115 return 1;
116}
117
118void EnumFieldGenerator::
119GenerateInterfaceMembers(io::Printer* printer) const {
120 printer->Print(variables_,
121 "$deprecation$boolean has$capitalized_name$();\n"
122 "$deprecation$$type$ get$capitalized_name$();\n");
123}
124
temporal40ee5512008-07-10 02:12:20 +0000125void EnumFieldGenerator::
126GenerateMembers(io::Printer* printer) const {
127 printer->Print(variables_,
kenton@google.comfccb1462009-12-18 02:11:36 +0000128 "private $type$ $name$_;\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000129 "$deprecation$public boolean has$capitalized_name$() {\n"
130 " return $get_has_field_bit_message$;\n"
131 "}\n"
132 "$deprecation$public $type$ get$capitalized_name$() {\n"
133 " return $name$_;\n"
134 "}\n");
temporal40ee5512008-07-10 02:12:20 +0000135}
136
137void EnumFieldGenerator::
138GenerateBuilderMembers(io::Printer* printer) const {
139 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000140 "private $type$ $name$_ = $default$;\n"
141 "$deprecation$public boolean has$capitalized_name$() {\n"
142 " return $get_has_field_bit_builder$;\n"
temporal40ee5512008-07-10 02:12:20 +0000143 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000144 "$deprecation$public $type$ get$capitalized_name$() {\n"
145 " return $name$_;\n"
temporal40ee5512008-07-10 02:12:20 +0000146 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000147 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000148 " if (value == null) {\n"
149 " throw new NullPointerException();\n"
150 " }\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000151 " $set_has_field_bit_builder$;\n"
152 " $name$_ = value;\n"
153 " $on_changed$\n"
temporal40ee5512008-07-10 02:12:20 +0000154 " return this;\n"
155 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000156 "$deprecation$public Builder clear$capitalized_name$() {\n"
157 " $clear_has_field_bit_builder$;\n"
158 " $name$_ = $default$;\n"
159 " $on_changed$\n"
temporal40ee5512008-07-10 02:12:20 +0000160 " return this;\n"
161 "}\n");
162}
163
164void EnumFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000165GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
166 // noop for enums
167}
168
169void EnumFieldGenerator::
kenton@google.comfccb1462009-12-18 02:11:36 +0000170GenerateInitializationCode(io::Printer* printer) const {
171 printer->Print(variables_, "$name$_ = $default$;\n");
172}
173
174void EnumFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000175GenerateBuilderClearCode(io::Printer* printer) const {
176 printer->Print(variables_,
177 "$name$_ = $default$;\n"
178 "$clear_has_field_bit_builder$;\n");
179}
180
181void EnumFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000182GenerateMergingCode(io::Printer* printer) const {
183 printer->Print(variables_,
184 "if (other.has$capitalized_name$()) {\n"
185 " set$capitalized_name$(other.get$capitalized_name$());\n"
186 "}\n");
187}
188
189void EnumFieldGenerator::
190GenerateBuildingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000191 printer->Print(variables_,
192 "if ($get_has_field_bit_from_local$) {\n"
193 " $set_has_field_bit_to_local$;\n"
194 "}\n"
195 "result.$name$_ = $name$_;\n");
temporal40ee5512008-07-10 02:12:20 +0000196}
197
198void EnumFieldGenerator::
199GenerateParsingCode(io::Printer* printer) const {
200 printer->Print(variables_,
201 "int rawValue = input.readEnum();\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000202 "$type$ value = $type$.valueOf(rawValue);\n");
203 if (HasUnknownFields(descriptor_->containing_type())) {
204 printer->Print(variables_,
205 "if (value == null) {\n"
206 " unknownFields.mergeVarintField($number$, rawValue);\n"
207 "} else {\n");
208 } else {
209 printer->Print(variables_,
210 "if (value != null) {\n");
211 }
212 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000213 " $set_has_field_bit_builder$;\n"
214 " $name$_ = value;\n"
temporal40ee5512008-07-10 02:12:20 +0000215 "}\n");
216}
217
218void EnumFieldGenerator::
219GenerateSerializationCode(io::Printer* printer) const {
220 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000221 "if ($get_has_field_bit_message$) {\n"
222 " output.writeEnum($number$, $name$_.getNumber());\n"
temporal40ee5512008-07-10 02:12:20 +0000223 "}\n");
224}
225
226void EnumFieldGenerator::
227GenerateSerializedSizeCode(io::Printer* printer) const {
228 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000229 "if ($get_has_field_bit_message$) {\n"
temporal40ee5512008-07-10 02:12:20 +0000230 " size += com.google.protobuf.CodedOutputStream\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000231 " .computeEnumSize($number$, $name$_.getNumber());\n"
temporal40ee5512008-07-10 02:12:20 +0000232 "}\n");
233}
234
liujisi@google.com33165fe2010-11-02 13:14:58 +0000235void EnumFieldGenerator::
236GenerateEqualsCode(io::Printer* printer) const {
237 printer->Print(variables_,
238 "result = result &&\n"
239 " (get$capitalized_name$() == other.get$capitalized_name$());\n");
240}
241
242void EnumFieldGenerator::
243GenerateHashCode(io::Printer* printer) const {
244 printer->Print(variables_,
245 "hash = (37 * hash) + $constant_name$;\n"
246 "hash = (53 * hash) + hashEnum(get$capitalized_name$());\n");
247}
248
temporal40ee5512008-07-10 02:12:20 +0000249string EnumFieldGenerator::GetBoxedType() const {
250 return ClassName(descriptor_->enum_type());
251}
252
253// ===================================================================
254
255RepeatedEnumFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000256RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
257 int messageBitIndex,
258 int builderBitIndex)
259 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
260 builderBitIndex_(builderBitIndex) {
261 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
temporal40ee5512008-07-10 02:12:20 +0000262}
263
264RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
265
liujisi@google.com33165fe2010-11-02 13:14:58 +0000266int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const {
267 return 0;
268}
269
270int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const {
271 return 1;
272}
273
274void RepeatedEnumFieldGenerator::
275GenerateInterfaceMembers(io::Printer* printer) const {
276 printer->Print(variables_,
277 "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"
278 "$deprecation$int get$capitalized_name$Count();\n"
279 "$deprecation$$type$ get$capitalized_name$(int index);\n");
280}
281
temporal40ee5512008-07-10 02:12:20 +0000282void RepeatedEnumFieldGenerator::
283GenerateMembers(io::Printer* printer) const {
284 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000285 "private java.util.List<$type$> $name$_;\n"
286 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
temporal40ee5512008-07-10 02:12:20 +0000287 " return $name$_;\n" // note: unmodifiable list
288 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000289 "$deprecation$public int get$capitalized_name$Count() {\n"
290 " return $name$_.size();\n"
291 "}\n"
292 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
temporal40ee5512008-07-10 02:12:20 +0000293 " return $name$_.get(index);\n"
294 "}\n");
kenton@google.com2d6daa72009-01-22 01:27:00 +0000295
296 if (descriptor_->options().packed() &&
kenton@google.com80b1d622009-07-29 01:13:20 +0000297 HasGeneratedMethods(descriptor_->containing_type())) {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000298 printer->Print(variables_,
299 "private int $name$MemoizedSerializedSize;\n");
300 }
temporal40ee5512008-07-10 02:12:20 +0000301}
302
303void RepeatedEnumFieldGenerator::
304GenerateBuilderMembers(io::Printer* printer) const {
305 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000306 // One field is the list and the other field keeps track of whether the
307 // list is immutable. If it's immutable, the invariant is that it must
308 // either an instance of Collections.emptyList() or it's an ArrayList
309 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
310 // a refererence to the underlying ArrayList. This invariant allows us to
311 // share instances of lists between protocol buffers avoiding expensive
312 // memory allocations. Note, immutable is a strong guarantee here -- not
313 // just that the list cannot be modified via the reference but that the
314 // list can never be modified.
315 "private java.util.List<$type$> $name$_ =\n"
316 " java.util.Collections.emptyList();\n"
317
318 "private void ensure$capitalized_name$IsMutable() {\n"
319 " if (!$get_mutable_bit_builder$) {\n"
320 " $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
321 " $set_mutable_bit_builder$;\n"
322 " }\n"
323 "}\n"
324
temporal40ee5512008-07-10 02:12:20 +0000325 // Note: We return an unmodifiable list because otherwise the caller
326 // could hold on to the returned list and modify it after the message
327 // has been built, thus mutating the message which is supposed to be
328 // immutable.
liujisi@google.com33165fe2010-11-02 13:14:58 +0000329 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
330 " return java.util.Collections.unmodifiableList($name$_);\n"
temporal40ee5512008-07-10 02:12:20 +0000331 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000332 "$deprecation$public int get$capitalized_name$Count() {\n"
333 " return $name$_.size();\n"
temporal40ee5512008-07-10 02:12:20 +0000334 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000335 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
336 " return $name$_.get(index);\n"
temporal40ee5512008-07-10 02:12:20 +0000337 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000338 "$deprecation$public Builder set$capitalized_name$(\n"
339 " int index, $type$ value) {\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000340 " if (value == null) {\n"
341 " throw new NullPointerException();\n"
342 " }\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000343 " ensure$capitalized_name$IsMutable();\n"
344 " $name$_.set(index, value);\n"
345 " $on_changed$\n"
temporal40ee5512008-07-10 02:12:20 +0000346 " return this;\n"
347 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000348 "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000349 " if (value == null) {\n"
350 " throw new NullPointerException();\n"
351 " }\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000352 " ensure$capitalized_name$IsMutable();\n"
353 " $name$_.add(value);\n"
354 " $on_changed$\n"
temporal40ee5512008-07-10 02:12:20 +0000355 " return this;\n"
356 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000357 "$deprecation$public Builder addAll$capitalized_name$(\n"
temporal40ee5512008-07-10 02:12:20 +0000358 " java.lang.Iterable<? extends $type$> values) {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000359 " ensure$capitalized_name$IsMutable();\n"
360 " super.addAll(values, $name$_);\n"
361 " $on_changed$\n"
temporal40ee5512008-07-10 02:12:20 +0000362 " return this;\n"
363 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000364 "$deprecation$public Builder clear$capitalized_name$() {\n"
365 " $name$_ = java.util.Collections.emptyList();\n"
366 " $clear_mutable_bit_builder$;\n"
367 " $on_changed$\n"
temporal40ee5512008-07-10 02:12:20 +0000368 " return this;\n"
369 "}\n");
370}
371
372void RepeatedEnumFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000373GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
374 // noop for enums
375}
376
377void RepeatedEnumFieldGenerator::
kenton@google.comfccb1462009-12-18 02:11:36 +0000378GenerateInitializationCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000379 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
380}
381
382void RepeatedEnumFieldGenerator::
383GenerateBuilderClearCode(io::Printer* printer) const {
384 printer->Print(variables_,
385 "$name$_ = java.util.Collections.emptyList();\n"
386 "$clear_mutable_bit_builder$;\n");
kenton@google.comfccb1462009-12-18 02:11:36 +0000387}
388
389void RepeatedEnumFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000390GenerateMergingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000391 // The code below does two optimizations:
392 // 1. If the other list is empty, there's nothing to do. This ensures we
393 // don't allocate a new array if we already have an immutable one.
394 // 2. If the other list is non-empty and our current list is empty, we can
395 // reuse the other list which is guaranteed to be immutable.
temporal40ee5512008-07-10 02:12:20 +0000396 printer->Print(variables_,
397 "if (!other.$name$_.isEmpty()) {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000398 " if ($name$_.isEmpty()) {\n"
399 " $name$_ = other.$name$_;\n"
400 " $clear_mutable_bit_builder$;\n"
401 " } else {\n"
402 " ensure$capitalized_name$IsMutable();\n"
403 " $name$_.addAll(other.$name$_);\n"
temporal40ee5512008-07-10 02:12:20 +0000404 " }\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000405 " $on_changed$\n"
temporal40ee5512008-07-10 02:12:20 +0000406 "}\n");
407}
408
409void RepeatedEnumFieldGenerator::
410GenerateBuildingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000411 // The code below ensures that the result has an immutable list. If our
412 // list is immutable, we can just reuse it. If not, we make it immutable.
temporal40ee5512008-07-10 02:12:20 +0000413 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000414 "if ($get_mutable_bit_builder$) {\n"
415 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
416 " $clear_mutable_bit_builder$;\n"
417 "}\n"
418 "result.$name$_ = $name$_;\n");
temporal40ee5512008-07-10 02:12:20 +0000419}
420
421void RepeatedEnumFieldGenerator::
422GenerateParsingCode(io::Printer* printer) const {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000423 // Read and store the enum
temporal40ee5512008-07-10 02:12:20 +0000424 printer->Print(variables_,
425 "int rawValue = input.readEnum();\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000426 "$type$ value = $type$.valueOf(rawValue);\n");
427 if (HasUnknownFields(descriptor_->containing_type())) {
428 printer->Print(variables_,
429 "if (value == null) {\n"
430 " unknownFields.mergeVarintField($number$, rawValue);\n"
431 "} else {\n");
432 } else {
433 printer->Print(variables_,
434 "if (value != null) {\n");
435 }
436 printer->Print(variables_,
temporal40ee5512008-07-10 02:12:20 +0000437 " add$capitalized_name$(value);\n"
438 "}\n");
kenton@google.comfccb1462009-12-18 02:11:36 +0000439}
kenton@google.com2d6daa72009-01-22 01:27:00 +0000440
kenton@google.comfccb1462009-12-18 02:11:36 +0000441void RepeatedEnumFieldGenerator::
442GenerateParsingCodeFromPacked(io::Printer* printer) const {
443 // Wrap GenerateParsingCode's contents with a while loop.
444
445 printer->Print(variables_,
446 "int length = input.readRawVarint32();\n"
447 "int oldLimit = input.pushLimit(length);\n"
448 "while(input.getBytesUntilLimit() > 0) {\n");
449 printer->Indent();
450
451 GenerateParsingCode(printer);
452
453 printer->Outdent();
454 printer->Print(variables_,
455 "}\n"
456 "input.popLimit(oldLimit);\n");
temporal40ee5512008-07-10 02:12:20 +0000457}
458
459void RepeatedEnumFieldGenerator::
460GenerateSerializationCode(io::Printer* printer) const {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000461 if (descriptor_->options().packed()) {
462 printer->Print(variables_,
463 "if (get$capitalized_name$List().size() > 0) {\n"
464 " output.writeRawVarint32($tag$);\n"
465 " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
466 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000467 "for (int i = 0; i < $name$_.size(); i++) {\n"
468 " output.writeEnumNoTag($name$_.get(i).getNumber());\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000469 "}\n");
470 } else {
471 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000472 "for (int i = 0; i < $name$_.size(); i++) {\n"
473 " output.writeEnum($number$, $name$_.get(i).getNumber());\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000474 "}\n");
475 }
temporal40ee5512008-07-10 02:12:20 +0000476}
477
478void RepeatedEnumFieldGenerator::
479GenerateSerializedSizeCode(io::Printer* printer) const {
480 printer->Print(variables_,
kenton@google.com2d6daa72009-01-22 01:27:00 +0000481 "{\n"
482 " int dataSize = 0;\n");
483 printer->Indent();
484
485 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000486 "for (int i = 0; i < $name$_.size(); i++) {\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000487 " dataSize += com.google.protobuf.CodedOutputStream\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000488 " .computeEnumSizeNoTag($name$_.get(i).getNumber());\n"
temporal40ee5512008-07-10 02:12:20 +0000489 "}\n");
kenton@google.com2d6daa72009-01-22 01:27:00 +0000490 printer->Print(
491 "size += dataSize;\n");
492 if (descriptor_->options().packed()) {
493 printer->Print(variables_,
494 "if (!get$capitalized_name$List().isEmpty()) {"
495 " size += $tag_size$;\n"
496 " size += com.google.protobuf.CodedOutputStream\n"
497 " .computeRawVarint32Size(dataSize);\n"
498 "}");
499 } else {
500 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000501 "size += $tag_size$ * $name$_.size();\n");
kenton@google.com2d6daa72009-01-22 01:27:00 +0000502 }
503
504 // cache the data size for packed fields.
505 if (descriptor_->options().packed()) {
506 printer->Print(variables_,
507 "$name$MemoizedSerializedSize = dataSize;\n");
508 }
509
510 printer->Outdent();
511 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000512}
513
liujisi@google.com33165fe2010-11-02 13:14:58 +0000514void RepeatedEnumFieldGenerator::
515GenerateEqualsCode(io::Printer* printer) const {
516 printer->Print(variables_,
517 "result = result && get$capitalized_name$List()\n"
518 " .equals(other.get$capitalized_name$List());\n");
519}
520
521void RepeatedEnumFieldGenerator::
522GenerateHashCode(io::Printer* printer) const {
523 printer->Print(variables_,
524 "if (get$capitalized_name$Count() > 0) {\n"
525 " hash = (37 * hash) + $constant_name$;\n"
526 " hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n"
527 "}\n");
528}
529
temporal40ee5512008-07-10 02:12:20 +0000530string RepeatedEnumFieldGenerator::GetBoxedType() const {
531 return ClassName(descriptor_->enum_type());
532}
533
534} // namespace java
535} // namespace compiler
536} // namespace protobuf
537} // namespace google