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