1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
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/stubs/logging.h>
39 #include <google/protobuf/stubs/common.h>
40 #include <google/protobuf/compiler/java/java_context.h>
41 #include <google/protobuf/compiler/java/java_doc_comment.h>
42 #include <google/protobuf/compiler/java/java_helpers.h>
43 #include <google/protobuf/compiler/java/java_name_resolver.h>
44 #include <google/protobuf/compiler/java/java_primitive_field.h>
45 #include <google/protobuf/io/printer.h>
46 #include <google/protobuf/wire_format.h>
47 #include <google/protobuf/stubs/strutil.h>
48
49 namespace google {
50 namespace protobuf {
51 namespace compiler {
52 namespace java {
53
54 using internal::WireFormat;
55 using internal::WireFormatLite;
56
57 namespace {
58
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables)59 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
60 int messageBitIndex, int builderBitIndex,
61 const FieldGeneratorInfo* info,
62 ClassNameResolver* name_resolver,
63 std::map<std::string, std::string>* variables) {
64 SetCommonFieldVariables(descriptor, info, variables);
65 JavaType javaType = GetJavaType(descriptor);
66
67 (*variables)["type"] = PrimitiveTypeName(javaType);
68 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
69 (*variables)["field_type"] = (*variables)["type"];
70
71 if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
72 javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT ||
73 javaType == JAVATYPE_LONG) {
74 std::string capitalized_type = UnderscoresToCamelCase(
75 PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
76 (*variables)["field_list_type"] =
77 "com.google.protobuf.Internal." + capitalized_type + "List";
78 (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
79 (*variables)["create_list"] = "new" + capitalized_type + "List()";
80 (*variables)["mutable_copy_list"] =
81 "mutableCopy(" + (*variables)["name"] + "_)";
82 (*variables)["name_make_immutable"] =
83 (*variables)["name"] + "_.makeImmutable()";
84 (*variables)["repeated_get"] =
85 (*variables)["name"] + "_.get" + capitalized_type;
86 (*variables)["repeated_add"] =
87 (*variables)["name"] + "_.add" + capitalized_type;
88 (*variables)["repeated_set"] =
89 (*variables)["name"] + "_.set" + capitalized_type;
90 } else {
91 (*variables)["field_list_type"] =
92 "java.util.List<" + (*variables)["boxed_type"] + ">";
93 (*variables)["create_list"] =
94 "new java.util.ArrayList<" + (*variables)["boxed_type"] + ">()";
95 (*variables)["mutable_copy_list"] = "new java.util.ArrayList<" +
96 (*variables)["boxed_type"] + ">(" +
97 (*variables)["name"] + "_)";
98 (*variables)["empty_list"] = "java.util.Collections.emptyList()";
99 (*variables)["name_make_immutable"] =
100 (*variables)["name"] + "_ = java.util.Collections.unmodifiableList(" +
101 (*variables)["name"] + "_)";
102 (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
103 (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
104 (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
105 }
106
107 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
108 (*variables)["default_init"] =
109 IsDefaultValueJavaDefault(descriptor)
110 ? ""
111 : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
112 (*variables)["capitalized_type"] =
113 GetCapitalizedType(descriptor, /* immutable = */ true);
114 (*variables)["tag"] =
115 StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
116 (*variables)["tag_size"] = StrCat(
117 WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
118 if (IsReferenceType(GetJavaType(descriptor))) {
119 (*variables)["null_check"] =
120 " if (value == null) {\n"
121 " throw new NullPointerException();\n"
122 " }\n";
123 } else {
124 (*variables)["null_check"] = "";
125 }
126 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
127 // by the proto compiler
128 (*variables)["deprecation"] =
129 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
130 int fixed_size = FixedSize(GetType(descriptor));
131 if (fixed_size != -1) {
132 (*variables)["fixed_size"] = StrCat(fixed_size);
133 }
134 (*variables)["on_changed"] = "onChanged();";
135
136 if (SupportFieldPresence(descriptor)) {
137 // For singular messages and builders, one bit is used for the hasField bit.
138 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
139 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
140
141 // Note that these have a trailing ";".
142 (*variables)["set_has_field_bit_message"] =
143 GenerateSetBit(messageBitIndex) + ";";
144 (*variables)["set_has_field_bit_builder"] =
145 GenerateSetBit(builderBitIndex) + ";";
146 (*variables)["clear_has_field_bit_builder"] =
147 GenerateClearBit(builderBitIndex) + ";";
148
149 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
150 } else {
151 (*variables)["set_has_field_bit_message"] = "";
152 (*variables)["set_has_field_bit_builder"] = "";
153 (*variables)["clear_has_field_bit_builder"] = "";
154
155 if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
156 (*variables)["is_field_present_message"] =
157 "!" + (*variables)["name"] + "_.isEmpty()";
158 } else {
159 (*variables)["is_field_present_message"] =
160 (*variables)["name"] + "_ != " + (*variables)["default"];
161 }
162 }
163
164 // For repeated builders, one bit is used for whether the array is immutable.
165 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
166 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
167 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
168
169 // For repeated fields, one bit is used for whether the array is immutable
170 // in the parsing constructor.
171 (*variables)["get_mutable_bit_parser"] =
172 GenerateGetBitMutableLocal(builderBitIndex);
173 (*variables)["set_mutable_bit_parser"] =
174 GenerateSetBitMutableLocal(builderBitIndex);
175
176 (*variables)["get_has_field_bit_from_local"] =
177 GenerateGetBitFromLocal(builderBitIndex);
178 (*variables)["set_has_field_bit_to_local"] =
179 GenerateSetBitToLocal(messageBitIndex);
180 }
181
182 } // namespace
183
184 // ===================================================================
185
ImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)186 ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator(
187 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
188 Context* context)
189 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
190 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
191 context->GetFieldGeneratorInfo(descriptor),
192 name_resolver_, &variables_);
193 }
194
~ImmutablePrimitiveFieldGenerator()195 ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
196
GetNumBitsForMessage() const197 int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
198 return SupportFieldPresence(descriptor_) ? 1 : 0;
199 }
200
GetNumBitsForBuilder() const201 int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
202 return GetNumBitsForMessage();
203 }
204
GenerateInterfaceMembers(io::Printer * printer) const205 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
206 io::Printer* printer) const {
207 if (SupportFieldPresence(descriptor_)) {
208 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
209 printer->Print(variables_,
210 "$deprecation$boolean has$capitalized_name$();\n");
211 }
212 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
213 printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
214 }
215
GenerateMembers(io::Printer * printer) const216 void ImmutablePrimitiveFieldGenerator::GenerateMembers(
217 io::Printer* printer) const {
218 printer->Print(variables_, "private $field_type$ $name$_;\n");
219 PrintExtraFieldInfo(variables_, printer);
220 if (SupportFieldPresence(descriptor_)) {
221 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
222 printer->Print(
223 variables_,
224 "@java.lang.Override\n"
225 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
226 " return $get_has_field_bit_message$;\n"
227 "}\n");
228 printer->Annotate("{", "}", descriptor_);
229 }
230
231 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
232 printer->Print(variables_,
233 "@java.lang.Override\n"
234 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
235 " return $name$_;\n"
236 "}\n");
237 printer->Annotate("{", "}", descriptor_);
238 }
239
GenerateBuilderMembers(io::Printer * printer) const240 void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
241 io::Printer* printer) const {
242 printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
243
244 if (SupportFieldPresence(descriptor_)) {
245 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
246 printer->Print(
247 variables_,
248 "@java.lang.Override\n"
249 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
250 " return $get_has_field_bit_builder$;\n"
251 "}\n");
252 printer->Annotate("{", "}", descriptor_);
253 }
254
255 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
256 printer->Print(variables_,
257 "@java.lang.Override\n"
258 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
259 " return $name$_;\n"
260 "}\n");
261 printer->Annotate("{", "}", descriptor_);
262
263 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
264 /* builder */ true);
265 printer->Print(variables_,
266 "$deprecation$public Builder "
267 "${$set$capitalized_name$$}$($type$ value) {\n"
268 "$null_check$"
269 " $set_has_field_bit_builder$\n"
270 " $name$_ = value;\n"
271 " $on_changed$\n"
272 " return this;\n"
273 "}\n");
274 printer->Annotate("{", "}", descriptor_);
275
276 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
277 /* builder */ true);
278 printer->Print(
279 variables_,
280 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
281 " $clear_has_field_bit_builder$\n");
282 printer->Annotate("{", "}", descriptor_);
283 JavaType type = GetJavaType(descriptor_);
284 if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
285 // The default value is not a simple literal so we want to avoid executing
286 // it multiple times. Instead, get the default out of the default instance.
287 printer->Print(
288 variables_,
289 " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
290 } else {
291 printer->Print(variables_, " $name$_ = $default$;\n");
292 }
293 printer->Print(variables_,
294 " $on_changed$\n"
295 " return this;\n"
296 "}\n");
297 }
298
299
GenerateFieldBuilderInitializationCode(io::Printer * printer) const300 void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
301 io::Printer* printer) const {
302 // noop for primitives
303 }
304
GenerateInitializationCode(io::Printer * printer) const305 void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
306 io::Printer* printer) const {
307 if (!IsDefaultValueJavaDefault(descriptor_)) {
308 printer->Print(variables_, "$name$_ = $default$;\n");
309 }
310 }
311
GenerateBuilderClearCode(io::Printer * printer) const312 void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
313 io::Printer* printer) const {
314 printer->Print(variables_,
315 "$name$_ = $default$;\n"
316 "$clear_has_field_bit_builder$\n");
317 }
318
GenerateMergingCode(io::Printer * printer) const319 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
320 io::Printer* printer) const {
321 if (SupportFieldPresence(descriptor_)) {
322 printer->Print(variables_,
323 "if (other.has$capitalized_name$()) {\n"
324 " set$capitalized_name$(other.get$capitalized_name$());\n"
325 "}\n");
326 } else {
327 printer->Print(variables_,
328 "if (other.get$capitalized_name$() != $default$) {\n"
329 " set$capitalized_name$(other.get$capitalized_name$());\n"
330 "}\n");
331 }
332 }
333
GenerateBuildingCode(io::Printer * printer) const334 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
335 io::Printer* printer) const {
336 if (SupportFieldPresence(descriptor_)) {
337 if (IsDefaultValueJavaDefault(descriptor_)) {
338 printer->Print(variables_,
339 "if ($get_has_field_bit_from_local$) {\n"
340 " result.$name$_ = $name$_;\n"
341 " $set_has_field_bit_to_local$;\n"
342 "}\n");
343 } else {
344 printer->Print(variables_,
345 "if ($get_has_field_bit_from_local$) {\n"
346 " $set_has_field_bit_to_local$;\n"
347 "}\n"
348 "result.$name$_ = $name$_;\n");
349 }
350 } else {
351 printer->Print(variables_, "result.$name$_ = $name$_;\n");
352 }
353 }
354
GenerateParsingCode(io::Printer * printer) const355 void ImmutablePrimitiveFieldGenerator::GenerateParsingCode(
356 io::Printer* printer) const {
357 printer->Print(variables_,
358 "$set_has_field_bit_message$\n"
359 "$name$_ = input.read$capitalized_type$();\n");
360 }
361
GenerateParsingDoneCode(io::Printer * printer) const362 void ImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode(
363 io::Printer* printer) const {
364 // noop for primitives.
365 }
366
GenerateSerializationCode(io::Printer * printer) const367 void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
368 io::Printer* printer) const {
369 printer->Print(variables_,
370 "if ($is_field_present_message$) {\n"
371 " output.write$capitalized_type$($number$, $name$_);\n"
372 "}\n");
373 }
374
GenerateSerializedSizeCode(io::Printer * printer) const375 void ImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
376 io::Printer* printer) const {
377 printer->Print(variables_,
378 "if ($is_field_present_message$) {\n"
379 " size += com.google.protobuf.CodedOutputStream\n"
380 " .compute$capitalized_type$Size($number$, $name$_);\n"
381 "}\n");
382 }
383
GenerateEqualsCode(io::Printer * printer) const384 void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
385 io::Printer* printer) const {
386 switch (GetJavaType(descriptor_)) {
387 case JAVATYPE_INT:
388 case JAVATYPE_LONG:
389 case JAVATYPE_BOOLEAN:
390 printer->Print(variables_,
391 "if (get$capitalized_name$()\n"
392 " != other.get$capitalized_name$()) return false;\n");
393 break;
394
395 case JAVATYPE_FLOAT:
396 printer->Print(
397 variables_,
398 "if (java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
399 " != java.lang.Float.floatToIntBits(\n"
400 " other.get$capitalized_name$())) return false;\n");
401 break;
402
403 case JAVATYPE_DOUBLE:
404 printer->Print(
405 variables_,
406 "if (java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
407 " != java.lang.Double.doubleToLongBits(\n"
408 " other.get$capitalized_name$())) return false;\n");
409 break;
410
411 case JAVATYPE_STRING:
412 case JAVATYPE_BYTES:
413 printer->Print(
414 variables_,
415 "if (!get$capitalized_name$()\n"
416 " .equals(other.get$capitalized_name$())) return false;\n");
417 break;
418
419 case JAVATYPE_ENUM:
420 case JAVATYPE_MESSAGE:
421 default:
422 GOOGLE_LOG(FATAL) << "Can't get here.";
423 break;
424 }
425 }
426
GenerateHashCode(io::Printer * printer) const427 void ImmutablePrimitiveFieldGenerator::GenerateHashCode(
428 io::Printer* printer) const {
429 printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
430 switch (GetJavaType(descriptor_)) {
431 case JAVATYPE_INT:
432 printer->Print(variables_,
433 "hash = (53 * hash) + get$capitalized_name$();\n");
434 break;
435
436 case JAVATYPE_LONG:
437 printer->Print(
438 variables_,
439 "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
440 " get$capitalized_name$());\n");
441 break;
442
443 case JAVATYPE_BOOLEAN:
444 printer->Print(
445 variables_,
446 "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
447 " get$capitalized_name$());\n");
448 break;
449
450 case JAVATYPE_FLOAT:
451 printer->Print(variables_,
452 "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
453 " get$capitalized_name$());\n");
454 break;
455
456 case JAVATYPE_DOUBLE:
457 printer->Print(
458 variables_,
459 "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
460 " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
461 break;
462
463 case JAVATYPE_STRING:
464 case JAVATYPE_BYTES:
465 printer->Print(
466 variables_,
467 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
468 break;
469
470 case JAVATYPE_ENUM:
471 case JAVATYPE_MESSAGE:
472 default:
473 GOOGLE_LOG(FATAL) << "Can't get here.";
474 break;
475 }
476 }
477
GetBoxedType() const478 std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
479 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
480 }
481
482 // ===================================================================
483
ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)484 ImmutablePrimitiveOneofFieldGenerator::ImmutablePrimitiveOneofFieldGenerator(
485 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
486 Context* context)
487 : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
488 builderBitIndex, context) {
489 const OneofGeneratorInfo* info =
490 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
491 SetCommonOneofVariables(descriptor, info, &variables_);
492 }
493
494 ImmutablePrimitiveOneofFieldGenerator::
~ImmutablePrimitiveOneofFieldGenerator()495 ~ImmutablePrimitiveOneofFieldGenerator() {}
496
GenerateMembers(io::Printer * printer) const497 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
498 io::Printer* printer) const {
499 PrintExtraFieldInfo(variables_, printer);
500 if (SupportFieldPresence(descriptor_)) {
501 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
502 printer->Print(
503 variables_,
504 "@java.lang.Override\n"
505 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
506 " return $has_oneof_case_message$;\n"
507 "}\n");
508 printer->Annotate("{", "}", descriptor_);
509 }
510
511 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
512 printer->Print(variables_,
513 "@java.lang.Override\n"
514 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
515 " if ($has_oneof_case_message$) {\n"
516 " return ($boxed_type$) $oneof_name$_;\n"
517 " }\n"
518 " return $default$;\n"
519 "}\n");
520 printer->Annotate("{", "}", descriptor_);
521 }
522
GenerateBuilderMembers(io::Printer * printer) const523 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
524 io::Printer* printer) const {
525 if (SupportFieldPresence(descriptor_)) {
526 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
527 printer->Print(
528 variables_,
529 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
530 " return $has_oneof_case_message$;\n"
531 "}\n");
532 printer->Annotate("{", "}", descriptor_);
533 }
534
535 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
536 printer->Print(variables_,
537 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
538 " if ($has_oneof_case_message$) {\n"
539 " return ($boxed_type$) $oneof_name$_;\n"
540 " }\n"
541 " return $default$;\n"
542 "}\n");
543 printer->Annotate("{", "}", descriptor_);
544
545 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
546 /* builder */ true);
547 printer->Print(variables_,
548 "$deprecation$public Builder "
549 "${$set$capitalized_name$$}$($type$ value) {\n"
550 "$null_check$"
551 " $set_oneof_case_message$;\n"
552 " $oneof_name$_ = value;\n"
553 " $on_changed$\n"
554 " return this;\n"
555 "}\n");
556 printer->Annotate("{", "}", descriptor_);
557
558 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
559 /* builder */ true);
560 printer->Print(
561 variables_,
562 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
563 " if ($has_oneof_case_message$) {\n"
564 " $clear_oneof_case_message$;\n"
565 " $oneof_name$_ = null;\n"
566 " $on_changed$\n"
567 " }\n"
568 " return this;\n"
569 "}\n");
570 printer->Annotate("{", "}", descriptor_);
571 }
572
GenerateBuildingCode(io::Printer * printer) const573 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode(
574 io::Printer* printer) const {
575 printer->Print(variables_,
576 "if ($has_oneof_case_message$) {\n"
577 " result.$oneof_name$_ = $oneof_name$_;\n"
578 "}\n");
579 }
580
GenerateMergingCode(io::Printer * printer) const581 void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
582 io::Printer* printer) const {
583 printer->Print(variables_,
584 "set$capitalized_name$(other.get$capitalized_name$());\n");
585 }
586
GenerateParsingCode(io::Printer * printer) const587 void ImmutablePrimitiveOneofFieldGenerator::GenerateParsingCode(
588 io::Printer* printer) const {
589 printer->Print(variables_,
590 "$set_oneof_case_message$;\n"
591 "$oneof_name$_ = input.read$capitalized_type$();\n");
592 }
593
GenerateSerializationCode(io::Printer * printer) const594 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode(
595 io::Printer* printer) const {
596 printer->Print(variables_,
597 "if ($has_oneof_case_message$) {\n"
598 " output.write$capitalized_type$(\n");
599 // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
600 // do redundant casts.
601 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
602 printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n");
603 } else {
604 printer->Print(
605 variables_,
606 " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
607 }
608 printer->Print("}\n");
609 }
610
GenerateSerializedSizeCode(io::Printer * printer) const611 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
612 io::Printer* printer) const {
613 printer->Print(variables_,
614 "if ($has_oneof_case_message$) {\n"
615 " size += com.google.protobuf.CodedOutputStream\n"
616 " .compute$capitalized_type$Size(\n");
617 // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
618 // do redundant casts.
619 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
620 printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n");
621 } else {
622 printer->Print(
623 variables_,
624 " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
625 }
626 printer->Print("}\n");
627 }
628
629 // ===================================================================
630
631 RepeatedImmutablePrimitiveFieldGenerator::
RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)632 RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
633 int messageBitIndex,
634 int builderBitIndex,
635 Context* context)
636 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
637 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
638 context->GetFieldGeneratorInfo(descriptor),
639 name_resolver_, &variables_);
640 }
641
642 RepeatedImmutablePrimitiveFieldGenerator::
~RepeatedImmutablePrimitiveFieldGenerator()643 ~RepeatedImmutablePrimitiveFieldGenerator() {}
644
GetNumBitsForMessage() const645 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
646 return 0;
647 }
648
GetNumBitsForBuilder() const649 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
650 return 1;
651 }
652
GenerateInterfaceMembers(io::Printer * printer) const653 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
654 io::Printer* printer) const {
655 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
656 printer->Print(variables_,
657 "$deprecation$java.util.List<$boxed_type$> "
658 "get$capitalized_name$List();\n");
659 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
660 printer->Print(variables_,
661 "$deprecation$int get$capitalized_name$Count();\n");
662 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
663 printer->Print(variables_,
664 "$deprecation$$type$ get$capitalized_name$(int index);\n");
665 }
666
GenerateMembers(io::Printer * printer) const667 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
668 io::Printer* printer) const {
669 printer->Print(variables_, "private $field_list_type$ $name$_;\n");
670 PrintExtraFieldInfo(variables_, printer);
671 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
672 printer->Print(variables_,
673 "@java.lang.Override\n"
674 "$deprecation$public java.util.List<$boxed_type$>\n"
675 " ${$get$capitalized_name$List$}$() {\n"
676 " return $name$_;\n" // note: unmodifiable list
677 "}\n");
678 printer->Annotate("{", "}", descriptor_);
679 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
680 printer->Print(
681 variables_,
682 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
683 " return $name$_.size();\n"
684 "}\n");
685 printer->Annotate("{", "}", descriptor_);
686 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
687 printer->Print(
688 variables_,
689 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
690 " return $repeated_get$(index);\n"
691 "}\n");
692 printer->Annotate("{", "}", descriptor_);
693
694 if (descriptor_->is_packed()) {
695 printer->Print(variables_,
696 "private int $name$MemoizedSerializedSize = -1;\n");
697 }
698 }
699
GenerateBuilderMembers(io::Printer * printer) const700 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
701 io::Printer* printer) const {
702 // One field is the list and the bit field keeps track of whether the
703 // list is immutable. If it's immutable, the invariant is that it must
704 // either an instance of Collections.emptyList() or it's an ArrayList
705 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
706 // a refererence to the underlying ArrayList. This invariant allows us to
707 // share instances of lists between protocol buffers avoiding expensive
708 // memory allocations. Note, immutable is a strong guarantee here -- not
709 // just that the list cannot be modified via the reference but that the
710 // list can never be modified.
711 printer->Print(variables_,
712 "private $field_list_type$ $name$_ = $empty_list$;\n");
713
714 printer->Print(variables_,
715 "private void ensure$capitalized_name$IsMutable() {\n"
716 " if (!$get_mutable_bit_builder$) {\n"
717 " $name$_ = $mutable_copy_list$;\n"
718 " $set_mutable_bit_builder$;\n"
719 " }\n"
720 "}\n");
721
722 // Note: We return an unmodifiable list because otherwise the caller
723 // could hold on to the returned list and modify it after the message
724 // has been built, thus mutating the message which is supposed to be
725 // immutable.
726 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
727 printer->Print(
728 variables_,
729 "$deprecation$public java.util.List<$boxed_type$>\n"
730 " ${$get$capitalized_name$List$}$() {\n"
731 " return $get_mutable_bit_builder$ ?\n"
732 " java.util.Collections.unmodifiableList($name$_) : $name$_;\n"
733 "}\n");
734 printer->Annotate("{", "}", descriptor_);
735 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
736 printer->Print(
737 variables_,
738 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
739 " return $name$_.size();\n"
740 "}\n");
741 printer->Annotate("{", "}", descriptor_);
742 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
743 printer->Print(
744 variables_,
745 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
746 " return $repeated_get$(index);\n"
747 "}\n");
748 printer->Annotate("{", "}", descriptor_);
749 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
750 /* builder */ true);
751 printer->Print(variables_,
752 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
753 " int index, $type$ value) {\n"
754 "$null_check$"
755 " ensure$capitalized_name$IsMutable();\n"
756 " $repeated_set$(index, value);\n"
757 " $on_changed$\n"
758 " return this;\n"
759 "}\n");
760 printer->Annotate("{", "}", descriptor_);
761 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
762 /* builder */ true);
763 printer->Print(variables_,
764 "$deprecation$public Builder "
765 "${$add$capitalized_name$$}$($type$ value) {\n"
766 "$null_check$"
767 " ensure$capitalized_name$IsMutable();\n"
768 " $repeated_add$(value);\n"
769 " $on_changed$\n"
770 " return this;\n"
771 "}\n");
772 printer->Annotate("{", "}", descriptor_);
773 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
774 /* builder */ true);
775 printer->Print(variables_,
776 "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
777 " java.lang.Iterable<? extends $boxed_type$> values) {\n"
778 " ensure$capitalized_name$IsMutable();\n"
779 " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
780 " values, $name$_);\n"
781 " $on_changed$\n"
782 " return this;\n"
783 "}\n");
784 printer->Annotate("{", "}", descriptor_);
785 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
786 /* builder */ true);
787 printer->Print(
788 variables_,
789 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
790 " $name$_ = $empty_list$;\n"
791 " $clear_mutable_bit_builder$;\n"
792 " $on_changed$\n"
793 " return this;\n"
794 "}\n");
795 printer->Annotate("{", "}", descriptor_);
796 }
797
798 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const799 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
800 // noop for primitives
801 }
802
GenerateInitializationCode(io::Printer * printer) const803 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
804 io::Printer* printer) const {
805 printer->Print(variables_, "$name$_ = $empty_list$;\n");
806 }
807
GenerateBuilderClearCode(io::Printer * printer) const808 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
809 io::Printer* printer) const {
810 printer->Print(variables_,
811 "$name$_ = $empty_list$;\n"
812 "$clear_mutable_bit_builder$;\n");
813 }
814
GenerateMergingCode(io::Printer * printer) const815 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode(
816 io::Printer* printer) const {
817 // The code below does two optimizations:
818 // 1. If the other list is empty, there's nothing to do. This ensures we
819 // don't allocate a new array if we already have an immutable one.
820 // 2. If the other list is non-empty and our current list is empty, we can
821 // reuse the other list which is guaranteed to be immutable.
822 printer->Print(variables_,
823 "if (!other.$name$_.isEmpty()) {\n"
824 " if ($name$_.isEmpty()) {\n"
825 " $name$_ = other.$name$_;\n"
826 " $clear_mutable_bit_builder$;\n"
827 " } else {\n"
828 " ensure$capitalized_name$IsMutable();\n"
829 " $name$_.addAll(other.$name$_);\n"
830 " }\n"
831 " $on_changed$\n"
832 "}\n");
833 }
834
GenerateBuildingCode(io::Printer * printer) const835 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
836 io::Printer* printer) const {
837 // The code below ensures that the result has an immutable list. If our
838 // list is immutable, we can just reuse it. If not, we make it immutable.
839 printer->Print(variables_,
840 "if ($get_mutable_bit_builder$) {\n"
841 " $name_make_immutable$;\n"
842 " $clear_mutable_bit_builder$;\n"
843 "}\n"
844 "result.$name$_ = $name$_;\n");
845 }
846
GenerateParsingCode(io::Printer * printer) const847 void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCode(
848 io::Printer* printer) const {
849 printer->Print(variables_,
850 "if (!$get_mutable_bit_parser$) {\n"
851 " $name$_ = $create_list$;\n"
852 " $set_mutable_bit_parser$;\n"
853 "}\n"
854 "$repeated_add$(input.read$capitalized_type$());\n");
855 }
856
GenerateParsingCodeFromPacked(io::Printer * printer) const857 void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCodeFromPacked(
858 io::Printer* printer) const {
859 printer->Print(
860 variables_,
861 "int length = input.readRawVarint32();\n"
862 "int limit = input.pushLimit(length);\n"
863 "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
864 " $name$_ = $create_list$;\n"
865 " $set_mutable_bit_parser$;\n"
866 "}\n"
867 "while (input.getBytesUntilLimit() > 0) {\n"
868 " $repeated_add$(input.read$capitalized_type$());\n"
869 "}\n"
870 "input.popLimit(limit);\n");
871 }
872
GenerateParsingDoneCode(io::Printer * printer) const873 void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode(
874 io::Printer* printer) const {
875 printer->Print(variables_,
876 "if ($get_mutable_bit_parser$) {\n"
877 " $name_make_immutable$; // C\n"
878 "}\n");
879 }
880
GenerateSerializationCode(io::Printer * printer) const881 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
882 io::Printer* printer) const {
883 if (descriptor_->is_packed()) {
884 // We invoke getSerializedSize in writeTo for messages that have packed
885 // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
886 // That makes it safe to rely on the memoized size here.
887 printer->Print(variables_,
888 "if (get$capitalized_name$List().size() > 0) {\n"
889 " output.writeUInt32NoTag($tag$);\n"
890 " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
891 "}\n"
892 "for (int i = 0; i < $name$_.size(); i++) {\n"
893 " output.write$capitalized_type$NoTag($repeated_get$(i));\n"
894 "}\n");
895 } else {
896 printer->Print(
897 variables_,
898 "for (int i = 0; i < $name$_.size(); i++) {\n"
899 " output.write$capitalized_type$($number$, $repeated_get$(i));\n"
900 "}\n");
901 }
902 }
903
GenerateSerializedSizeCode(io::Printer * printer) const904 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
905 io::Printer* printer) const {
906 printer->Print(variables_,
907 "{\n"
908 " int dataSize = 0;\n");
909 printer->Indent();
910
911 if (FixedSize(GetType(descriptor_)) == -1) {
912 printer->Print(
913 variables_,
914 "for (int i = 0; i < $name$_.size(); i++) {\n"
915 " dataSize += com.google.protobuf.CodedOutputStream\n"
916 " .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
917 "}\n");
918 } else {
919 printer->Print(
920 variables_,
921 "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
922 }
923
924 printer->Print("size += dataSize;\n");
925
926 if (descriptor_->is_packed()) {
927 printer->Print(variables_,
928 "if (!get$capitalized_name$List().isEmpty()) {\n"
929 " size += $tag_size$;\n"
930 " size += com.google.protobuf.CodedOutputStream\n"
931 " .computeInt32SizeNoTag(dataSize);\n"
932 "}\n");
933 } else {
934 printer->Print(
935 variables_,
936 "size += $tag_size$ * get$capitalized_name$List().size();\n");
937 }
938
939 // cache the data size for packed fields.
940 if (descriptor_->is_packed()) {
941 printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
942 }
943
944 printer->Outdent();
945 printer->Print("}\n");
946 }
947
GenerateEqualsCode(io::Printer * printer) const948 void RepeatedImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
949 io::Printer* printer) const {
950 printer->Print(
951 variables_,
952 "if (!get$capitalized_name$List()\n"
953 " .equals(other.get$capitalized_name$List())) return false;\n");
954 }
955
GenerateHashCode(io::Printer * printer) const956 void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode(
957 io::Printer* printer) const {
958 printer->Print(
959 variables_,
960 "if (get$capitalized_name$Count() > 0) {\n"
961 " hash = (37 * hash) + $constant_name$;\n"
962 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
963 "}\n");
964 }
965
GetBoxedType() const966 std::string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
967 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
968 }
969
970 } // namespace java
971 } // namespace compiler
972 } // namespace protobuf
973 } // namespace google
974