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_lite.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,map<string,string> * variables)59 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
60 int messageBitIndex,
61 int builderBitIndex,
62 const FieldGeneratorInfo* info,
63 ClassNameResolver* name_resolver,
64 map<string, string>* variables) {
65 SetCommonFieldVariables(descriptor, info, variables);
66 JavaType javaType = GetJavaType(descriptor);
67 (*variables)["type"] = PrimitiveTypeName(javaType);
68 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
69 (*variables)["field_type"] = (*variables)["type"];
70 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
71 (*variables)["capitalized_type"] =
72 GetCapitalizedType(descriptor, /* immutable = */ true);
73 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
74 (*variables)["tag_size"] = SimpleItoa(
75 WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
76
77 string capitalized_type = UnderscoresToCamelCase(PrimitiveTypeName(javaType),
78 true /* cap_next_letter */);
79 switch (javaType) {
80 case JAVATYPE_INT:
81 case JAVATYPE_LONG:
82 case JAVATYPE_FLOAT:
83 case JAVATYPE_DOUBLE:
84 case JAVATYPE_BOOLEAN:
85 (*variables)["field_list_type"] =
86 "com.google.protobuf.Internal." + capitalized_type + "List";
87 (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
88 (*variables)["make_name_unmodifiable"] =
89 (*variables)["name"] + "_.makeImmutable()";
90 (*variables)["repeated_get"] =
91 (*variables)["name"] + "_.get" + capitalized_type;
92 (*variables)["repeated_add"] =
93 (*variables)["name"] + "_.add" + capitalized_type;
94 (*variables)["repeated_set"] =
95 (*variables)["name"] + "_.set" + capitalized_type;
96 (*variables)["visit_type"] = capitalized_type;
97 (*variables)["visit_type_list"] = "visit" + capitalized_type + "List";
98 break;
99 default:
100 (*variables)["field_list_type"] =
101 "com.google.protobuf.Internal.ProtobufList<" +
102 (*variables)["boxed_type"] + ">";
103 (*variables)["empty_list"] = "emptyProtobufList()";
104 (*variables)["make_name_unmodifiable"] =
105 (*variables)["name"] + "_.makeImmutable()";
106 (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
107 (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
108 (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
109 (*variables)["visit_type"] = "ByteString";
110 (*variables)["visit_type_list"] = "visitList";
111 }
112
113 if (javaType == JAVATYPE_BYTES) {
114 (*variables)["bytes_default"] =
115 ToUpper((*variables)["name"]) + "_DEFAULT_VALUE";
116 }
117
118 if (IsReferenceType(javaType)) {
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"] = descriptor->options().deprecated()
129 ? "@java.lang.Deprecated " : "";
130 int fixed_size = FixedSize(GetType(descriptor));
131 if (fixed_size != -1) {
132 (*variables)["fixed_size"] = SimpleItoa(fixed_size);
133 }
134
135 if (SupportFieldPresence(descriptor->file())) {
136 // For singular messages and builders, one bit is used for the hasField bit.
137 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
138
139 // Note that these have a trailing ";".
140 (*variables)["set_has_field_bit_message"] =
141 GenerateSetBit(messageBitIndex) + ";";
142 (*variables)["clear_has_field_bit_message"] =
143 GenerateClearBit(messageBitIndex) + ";";
144
145 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
146 } else {
147 (*variables)["set_has_field_bit_message"] = "";
148 (*variables)["set_has_field_bit_message"] = "";
149 (*variables)["clear_has_field_bit_message"] = "";
150
151 if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
152 (*variables)["is_field_present_message"] =
153 "!" + (*variables)["name"] + "_.isEmpty()";
154 } else {
155 (*variables)["is_field_present_message"] =
156 (*variables)["name"] + "_ != " + (*variables)["default"];
157 }
158 }
159
160 // For repeated builders, the underlying list tracks mutability state.
161 (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
162
163 (*variables)["get_has_field_bit_from_local"] =
164 GenerateGetBitFromLocal(builderBitIndex);
165 (*variables)["set_has_field_bit_to_local"] =
166 GenerateSetBitToLocal(messageBitIndex);
167 }
168
169 } // namespace
170
171 // ===================================================================
172
173 ImmutablePrimitiveFieldLiteGenerator::
ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)174 ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
175 int messageBitIndex,
176 int builderBitIndex,
177 Context* context)
178 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
179 builderBitIndex_(builderBitIndex), context_(context),
180 name_resolver_(context->GetNameResolver()) {
181 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
182 context->GetFieldGeneratorInfo(descriptor),
183 name_resolver_, &variables_);
184 }
185
~ImmutablePrimitiveFieldLiteGenerator()186 ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {}
187
GetNumBitsForMessage() const188 int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
189 return 1;
190 }
191
GetNumBitsForBuilder() const192 int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
193 return 0;
194 }
195
196 void ImmutablePrimitiveFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const197 GenerateInterfaceMembers(io::Printer* printer) const {
198 if (SupportFieldPresence(descriptor_->file())) {
199 WriteFieldDocComment(printer, descriptor_);
200 printer->Print(variables_,
201 "$deprecation$boolean has$capitalized_name$();\n");
202 }
203 WriteFieldDocComment(printer, descriptor_);
204 printer->Print(variables_,
205 "$deprecation$$type$ get$capitalized_name$();\n");
206 }
207
208 void ImmutablePrimitiveFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const209 GenerateMembers(io::Printer* printer) const {
210 if (IsByteStringWithCustomDefaultValue(descriptor_)) {
211 // allocate this once statically since we know ByteStrings are immutable
212 // values that can be reused.
213 printer->Print(
214 variables_,
215 "private static final $field_type$ $bytes_default$ = $default$;\n");
216 }
217 printer->Print(variables_,
218 "private $field_type$ $name$_;\n");
219 PrintExtraFieldInfo(variables_, printer);
220 if (SupportFieldPresence(descriptor_->file())) {
221 WriteFieldDocComment(printer, descriptor_);
222 printer->Print(variables_,
223 "$deprecation$public boolean has$capitalized_name$() {\n"
224 " return $get_has_field_bit_message$;\n"
225 "}\n");
226 }
227
228 WriteFieldDocComment(printer, descriptor_);
229 printer->Print(variables_,
230 "$deprecation$public $type$ get$capitalized_name$() {\n"
231 " return $name$_;\n"
232 "}\n");
233
234 WriteFieldDocComment(printer, descriptor_);
235 printer->Print(variables_,
236 "private void set$capitalized_name$($type$ value) {\n"
237 "$null_check$"
238 " $set_has_field_bit_message$\n"
239 " $name$_ = value;\n"
240 "}\n");
241
242 WriteFieldDocComment(printer, descriptor_);
243 printer->Print(variables_,
244 "private void clear$capitalized_name$() {\n"
245 " $clear_has_field_bit_message$\n");
246 JavaType type = GetJavaType(descriptor_);
247 if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
248 // The default value is not a simple literal so we want to avoid executing
249 // it multiple times. Instead, get the default out of the default instance.
250 printer->Print(variables_,
251 " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
252 } else {
253 printer->Print(variables_,
254 " $name$_ = $default$;\n");
255 }
256 printer->Print(variables_,
257 "}\n");
258 }
259
260 void ImmutablePrimitiveFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const261 GenerateBuilderMembers(io::Printer* printer) const {
262 if (SupportFieldPresence(descriptor_->file())) {
263 WriteFieldDocComment(printer, descriptor_);
264 printer->Print(variables_,
265 "$deprecation$public boolean has$capitalized_name$() {\n"
266 " return instance.has$capitalized_name$();\n"
267 "}\n");
268 }
269
270 WriteFieldDocComment(printer, descriptor_);
271 printer->Print(variables_,
272 "$deprecation$public $type$ get$capitalized_name$() {\n"
273 " return instance.get$capitalized_name$();\n"
274 "}\n");
275
276 WriteFieldDocComment(printer, descriptor_);
277 printer->Print(variables_,
278 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
279 " copyOnWrite();\n"
280 " instance.set$capitalized_name$(value);\n"
281 " return this;\n"
282 "}\n");
283
284 WriteFieldDocComment(printer, descriptor_);
285 printer->Print(variables_,
286 "$deprecation$public Builder clear$capitalized_name$() {\n"
287 " copyOnWrite();\n"
288 " instance.clear$capitalized_name$();\n"
289 " return this;\n"
290 "}\n");
291 }
292
293 void ImmutablePrimitiveFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const294 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
295 // noop for primitives
296 }
297
298 void ImmutablePrimitiveFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const299 GenerateInitializationCode(io::Printer* printer) const {
300 if (IsByteStringWithCustomDefaultValue(descriptor_)) {
301 printer->Print(variables_, "$name$_ = $bytes_default$;\n");
302 } else if (!IsDefaultValueJavaDefault(descriptor_)) {
303 printer->Print(variables_, "$name$_ = $default$;\n");
304 }
305 }
306
307 void ImmutablePrimitiveFieldLiteGenerator::
GenerateBuilderClearCode(io::Printer * printer) const308 GenerateBuilderClearCode(io::Printer* printer) const {
309 // noop for primitives
310 }
311
312 void ImmutablePrimitiveFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const313 GenerateVisitCode(io::Printer* printer) const {
314 if (SupportFieldPresence(descriptor_->file())) {
315 printer->Print(variables_,
316 "$name$_ = visitor.visit$visit_type$(\n"
317 " has$capitalized_name$(), $name$_,\n"
318 " other.has$capitalized_name$(), other.$name$_);\n");
319 } else {
320 printer->Print(variables_,
321 "$name$_ = visitor.visit$visit_type$($name$_ != $default$, $name$_,\n"
322 " other.$name$_ != $default$, other.$name$_);\n");
323 }
324 }
325
326 void ImmutablePrimitiveFieldLiteGenerator::
GenerateBuildingCode(io::Printer * printer) const327 GenerateBuildingCode(io::Printer* printer) const {
328 // noop for primitives
329 }
330
331 void ImmutablePrimitiveFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const332 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
333 // noop for scalars
334 }
335
336 void ImmutablePrimitiveFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const337 GenerateParsingCode(io::Printer* printer) const {
338 printer->Print(variables_,
339 "$set_has_field_bit_message$\n"
340 "$name$_ = input.read$capitalized_type$();\n");
341 }
342
343 void ImmutablePrimitiveFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const344 GenerateParsingDoneCode(io::Printer* printer) const {
345 // noop for primitives.
346 }
347
348 void ImmutablePrimitiveFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const349 GenerateSerializationCode(io::Printer* printer) const {
350 printer->Print(variables_,
351 "if ($is_field_present_message$) {\n"
352 " output.write$capitalized_type$($number$, $name$_);\n"
353 "}\n");
354 }
355
356 void ImmutablePrimitiveFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const357 GenerateSerializedSizeCode(io::Printer* printer) const {
358 printer->Print(variables_,
359 "if ($is_field_present_message$) {\n"
360 " size += com.google.protobuf.CodedOutputStream\n"
361 " .compute$capitalized_type$Size($number$, $name$_);\n"
362 "}\n");
363 }
364
365 void ImmutablePrimitiveFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const366 GenerateEqualsCode(io::Printer* printer) const {
367 switch (GetJavaType(descriptor_)) {
368 case JAVATYPE_INT:
369 case JAVATYPE_LONG:
370 case JAVATYPE_BOOLEAN:
371 printer->Print(variables_,
372 "result = result && (get$capitalized_name$()\n"
373 " == other.get$capitalized_name$());\n");
374 break;
375
376 case JAVATYPE_FLOAT:
377 printer->Print(variables_,
378 "result = result && (\n"
379 " java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
380 " == java.lang.Float.floatToIntBits(\n"
381 " other.get$capitalized_name$()));\n");
382 break;
383
384 case JAVATYPE_DOUBLE:
385 printer->Print(variables_,
386 "result = result && (\n"
387 " java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
388 " == java.lang.Double.doubleToLongBits(\n"
389 " other.get$capitalized_name$()));\n");
390 break;
391
392 case JAVATYPE_STRING:
393 case JAVATYPE_BYTES:
394 printer->Print(variables_,
395 "result = result && get$capitalized_name$()\n"
396 " .equals(other.get$capitalized_name$());\n");
397 break;
398
399 case JAVATYPE_ENUM:
400 case JAVATYPE_MESSAGE:
401 default:
402 GOOGLE_LOG(FATAL) << "Can't get here.";
403 break;
404 }
405 }
406
407 void ImmutablePrimitiveFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const408 GenerateHashCode(io::Printer* printer) const {
409 printer->Print(variables_,
410 "hash = (37 * hash) + $constant_name$;\n");
411 switch (GetJavaType(descriptor_)) {
412 case JAVATYPE_INT:
413 printer->Print(variables_,
414 "hash = (53 * hash) + get$capitalized_name$();\n");
415 break;
416
417 case JAVATYPE_LONG:
418 printer->Print(variables_,
419 "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
420 " get$capitalized_name$());\n");
421 break;
422
423 case JAVATYPE_BOOLEAN:
424 printer->Print(variables_,
425 "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
426 " get$capitalized_name$());\n");
427 break;
428
429 case JAVATYPE_FLOAT:
430 printer->Print(variables_,
431 "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
432 " get$capitalized_name$());\n");
433 break;
434
435 case JAVATYPE_DOUBLE:
436 printer->Print(variables_,
437 "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
438 " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
439 break;
440
441 case JAVATYPE_STRING:
442 case JAVATYPE_BYTES:
443 printer->Print(variables_,
444 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
445 break;
446
447 case JAVATYPE_ENUM:
448 case JAVATYPE_MESSAGE:
449 default:
450 GOOGLE_LOG(FATAL) << "Can't get here.";
451 break;
452 }
453 }
454
GetBoxedType() const455 string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
456 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
457 }
458
459 // ===================================================================
460
461 ImmutablePrimitiveOneofFieldLiteGenerator::
ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)462 ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
463 int messageBitIndex,
464 int builderBitIndex,
465 Context* context)
466 : ImmutablePrimitiveFieldLiteGenerator(
467 descriptor, messageBitIndex, builderBitIndex, context) {
468 const OneofGeneratorInfo* info =
469 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
470 SetCommonOneofVariables(descriptor, info, &variables_);
471 }
472
473 ImmutablePrimitiveOneofFieldLiteGenerator::
~ImmutablePrimitiveOneofFieldLiteGenerator()474 ~ImmutablePrimitiveOneofFieldLiteGenerator() {}
475
476 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const477 GenerateMembers(io::Printer* printer) const {
478 PrintExtraFieldInfo(variables_, printer);
479 if (SupportFieldPresence(descriptor_->file())) {
480 WriteFieldDocComment(printer, descriptor_);
481 printer->Print(variables_,
482 "$deprecation$public boolean has$capitalized_name$() {\n"
483 " return $has_oneof_case_message$;\n"
484 "}\n");
485 }
486
487 WriteFieldDocComment(printer, descriptor_);
488 printer->Print(variables_,
489 "$deprecation$public $type$ get$capitalized_name$() {\n"
490 " if ($has_oneof_case_message$) {\n"
491 " return ($boxed_type$) $oneof_name$_;\n"
492 " }\n"
493 " return $default$;\n"
494 "}\n");
495
496 WriteFieldDocComment(printer, descriptor_);
497 printer->Print(variables_,
498 "private void set$capitalized_name$($type$ value) {\n"
499 "$null_check$"
500 " $set_oneof_case_message$;\n"
501 " $oneof_name$_ = value;\n"
502 "}\n");
503
504 WriteFieldDocComment(printer, descriptor_);
505 printer->Print(variables_,
506 "private void clear$capitalized_name$() {\n"
507 " if ($has_oneof_case_message$) {\n"
508 " $clear_oneof_case_message$;\n"
509 " $oneof_name$_ = null;\n"
510 " }\n"
511 "}\n");
512 }
513
514
515 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const516 GenerateBuilderMembers(io::Printer* printer) const {
517 if (SupportFieldPresence(descriptor_->file())) {
518 WriteFieldDocComment(printer, descriptor_);
519 printer->Print(variables_,
520 "$deprecation$public boolean has$capitalized_name$() {\n"
521 " return instance.has$capitalized_name$();\n"
522 "}\n");
523 }
524
525 WriteFieldDocComment(printer, descriptor_);
526 printer->Print(variables_,
527 "$deprecation$public $type$ get$capitalized_name$() {\n"
528 " return instance.get$capitalized_name$();\n"
529 "}\n");
530
531 WriteFieldDocComment(printer, descriptor_);
532 printer->Print(variables_,
533 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
534 " copyOnWrite();\n"
535 " instance.set$capitalized_name$(value);\n"
536 " return this;\n"
537 "}\n");
538
539 WriteFieldDocComment(printer, descriptor_);
540 printer->Print(variables_,
541 "$deprecation$public Builder clear$capitalized_name$() {\n"
542 " copyOnWrite();\n"
543 " instance.clear$capitalized_name$();\n"
544 " return this;\n"
545 "}\n");
546 }
547
548 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateBuildingCode(io::Printer * printer) const549 GenerateBuildingCode(io::Printer* printer) const {
550 // noop for primitives
551 }
552
553 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const554 GenerateVisitCode(io::Printer* printer) const {
555 printer->Print(variables_,
556 "$oneof_name$_ = visitor.visitOneof$visit_type$(\n"
557 " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
558 }
559
560 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const561 GenerateParsingCode(io::Printer* printer) const {
562 printer->Print(variables_,
563 "$set_oneof_case_message$;\n"
564 "$oneof_name$_ = input.read$capitalized_type$();\n");
565 }
566
567 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const568 GenerateSerializationCode(io::Printer* printer) const {
569 printer->Print(variables_,
570 "if ($has_oneof_case_message$) {\n"
571 " output.write$capitalized_type$(\n"
572 " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
573 "}\n");
574 }
575
576 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const577 GenerateSerializedSizeCode(io::Printer* printer) const {
578 printer->Print(variables_,
579 "if ($has_oneof_case_message$) {\n"
580 " size += com.google.protobuf.CodedOutputStream\n"
581 " .compute$capitalized_type$Size(\n"
582 " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
583 "}\n");
584 }
585
586 // ===================================================================
587
588 RepeatedImmutablePrimitiveFieldLiteGenerator::
RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)589 RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
590 int messageBitIndex,
591 int builderBitIndex,
592 Context* context)
593 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
594 builderBitIndex_(builderBitIndex), context_(context),
595 name_resolver_(context->GetNameResolver()) {
596 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
597 context->GetFieldGeneratorInfo(descriptor),
598 name_resolver_, &variables_);
599 }
600
601 RepeatedImmutablePrimitiveFieldLiteGenerator::
~RepeatedImmutablePrimitiveFieldLiteGenerator()602 ~RepeatedImmutablePrimitiveFieldLiteGenerator() {}
603
GetNumBitsForMessage() const604 int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
605 return 0;
606 }
607
GetNumBitsForBuilder() const608 int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
609 return 0;
610 }
611
612 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const613 GenerateInterfaceMembers(io::Printer* printer) const {
614 WriteFieldDocComment(printer, descriptor_);
615 printer->Print(variables_,
616 "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
617 WriteFieldDocComment(printer, descriptor_);
618 printer->Print(variables_,
619 "$deprecation$int get$capitalized_name$Count();\n");
620 WriteFieldDocComment(printer, descriptor_);
621 printer->Print(variables_,
622 "$deprecation$$type$ get$capitalized_name$(int index);\n");
623 }
624
625
626 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const627 GenerateMembers(io::Printer* printer) const {
628 printer->Print(variables_,
629 "private $field_list_type$ $name$_;\n");
630 PrintExtraFieldInfo(variables_, printer);
631 WriteFieldDocComment(printer, descriptor_);
632 printer->Print(variables_,
633 "$deprecation$public java.util.List<$boxed_type$>\n"
634 " get$capitalized_name$List() {\n"
635 " return $name$_;\n" // note: unmodifiable list
636 "}\n");
637 WriteFieldDocComment(printer, descriptor_);
638 printer->Print(variables_,
639 "$deprecation$public int get$capitalized_name$Count() {\n"
640 " return $name$_.size();\n"
641 "}\n");
642 WriteFieldDocComment(printer, descriptor_);
643 printer->Print(variables_,
644 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
645 " return $repeated_get$(index);\n"
646 "}\n");
647
648 if (descriptor_->options().packed() &&
649 context_->HasGeneratedMethods(descriptor_->containing_type())) {
650 printer->Print(variables_,
651 "private int $name$MemoizedSerializedSize = -1;\n");
652 }
653
654 printer->Print(variables_,
655 "private void ensure$capitalized_name$IsMutable() {\n"
656 " if (!$is_mutable$) {\n"
657 " $name$_ =\n"
658 " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
659 " }\n"
660 "}\n");
661
662 WriteFieldDocComment(printer, descriptor_);
663 printer->Print(variables_,
664 "private void set$capitalized_name$(\n"
665 " int index, $type$ value) {\n"
666 "$null_check$"
667 " ensure$capitalized_name$IsMutable();\n"
668 " $repeated_set$(index, value);\n"
669 "}\n");
670 WriteFieldDocComment(printer, descriptor_);
671 printer->Print(variables_,
672 "private void add$capitalized_name$($type$ value) {\n"
673 "$null_check$"
674 " ensure$capitalized_name$IsMutable();\n"
675 " $repeated_add$(value);\n"
676 "}\n");
677 WriteFieldDocComment(printer, descriptor_);
678 printer->Print(variables_,
679 "private void addAll$capitalized_name$(\n"
680 " java.lang.Iterable<? extends $boxed_type$> values) {\n"
681 " ensure$capitalized_name$IsMutable();\n"
682 " com.google.protobuf.AbstractMessageLite.addAll(\n"
683 " values, $name$_);\n"
684 "}\n");
685 WriteFieldDocComment(printer, descriptor_);
686 printer->Print(variables_,
687 "private void clear$capitalized_name$() {\n"
688 " $name$_ = $empty_list$;\n"
689 "}\n");
690 }
691
692 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const693 GenerateBuilderMembers(io::Printer* printer) const {
694 WriteFieldDocComment(printer, descriptor_);
695 printer->Print(variables_,
696 "$deprecation$public java.util.List<$boxed_type$>\n"
697 " get$capitalized_name$List() {\n"
698 " return java.util.Collections.unmodifiableList(\n"
699 " instance.get$capitalized_name$List());\n"
700 "}\n");
701 WriteFieldDocComment(printer, descriptor_);
702 printer->Print(variables_,
703 "$deprecation$public int get$capitalized_name$Count() {\n"
704 " return instance.get$capitalized_name$Count();\n"
705 "}\n");
706 WriteFieldDocComment(printer, descriptor_);
707 printer->Print(variables_,
708 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
709 " return instance.get$capitalized_name$(index);\n"
710 "}\n");
711 WriteFieldDocComment(printer, descriptor_);
712 printer->Print(variables_,
713 "$deprecation$public Builder set$capitalized_name$(\n"
714 " int index, $type$ value) {\n"
715 " copyOnWrite();\n"
716 " instance.set$capitalized_name$(index, value);\n"
717 " return this;\n"
718 "}\n");
719 WriteFieldDocComment(printer, descriptor_);
720 printer->Print(variables_,
721 "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
722 " copyOnWrite();\n"
723 " instance.add$capitalized_name$(value);\n"
724 " return this;\n"
725 "}\n");
726 WriteFieldDocComment(printer, descriptor_);
727 printer->Print(variables_,
728 "$deprecation$public Builder addAll$capitalized_name$(\n"
729 " java.lang.Iterable<? extends $boxed_type$> values) {\n"
730 " copyOnWrite();\n"
731 " instance.addAll$capitalized_name$(values);\n"
732 " return this;\n"
733 "}\n");
734 WriteFieldDocComment(printer, descriptor_);
735 printer->Print(variables_,
736 "$deprecation$public Builder clear$capitalized_name$() {\n"
737 " copyOnWrite();\n"
738 " instance.clear$capitalized_name$();\n"
739 " return this;\n"
740 "}\n");
741 }
742
743 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const744 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
745 // noop for primitives
746 }
747
748 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const749 GenerateInitializationCode(io::Printer* printer) const {
750 printer->Print(variables_, "$name$_ = $empty_list$;\n");
751 }
752
753 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateBuilderClearCode(io::Printer * printer) const754 GenerateBuilderClearCode(io::Printer* printer) const {
755 // noop for primitives
756 }
757
758 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const759 GenerateVisitCode(io::Printer* printer) const {
760 printer->Print(variables_,
761 "$name$_= visitor.$visit_type_list$($name$_, other.$name$_);\n");
762 }
763
764 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateBuildingCode(io::Printer * printer) const765 GenerateBuildingCode(io::Printer* printer) const {
766 // noop for primitives
767 }
768
769 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const770 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
771 printer->Print(variables_,
772 "$name$_.makeImmutable();\n");
773 }
774
775 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const776 GenerateParsingCode(io::Printer* printer) const {
777 // TODO(dweis): Scan the input buffer to count, then initialize
778 // appropriately.
779 // TODO(dweis): Scan the input buffer to count and ensure capacity.
780 printer->Print(variables_,
781 "if (!$is_mutable$) {\n"
782 " $name$_ =\n"
783 " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
784 "}\n"
785 "$repeated_add$(input.read$capitalized_type$());\n");
786 }
787
788 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateParsingCodeFromPacked(io::Printer * printer) const789 GenerateParsingCodeFromPacked(io::Printer* printer) const {
790 printer->Print(variables_,
791 "int length = input.readRawVarint32();\n"
792 "int limit = input.pushLimit(length);\n"
793 "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n");
794
795 int fixed_size = FixedSize(GetType(descriptor_));
796 if (fixed_size == -1) {
797 // TODO(dweis): Scan the input buffer to count, then initialize
798 // appropriately.
799 printer->Print(variables_,
800 " $name$_ =\n"
801 " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n");
802 } else {
803 printer->Print(variables_,
804 " final int currentSize = $name$_.size();\n"
805 " $name$_ = $name$_.mutableCopyWithCapacity(\n"
806 " currentSize + (length/$fixed_size$));\n");
807 }
808
809 // TODO(dweis): Scan the input buffer to count and ensure capacity.
810 printer->Print(variables_,
811 "}\n"
812 "while (input.getBytesUntilLimit() > 0) {\n"
813 " $repeated_add$(input.read$capitalized_type$());\n"
814 "}\n"
815 "input.popLimit(limit);\n");
816 }
817
818 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const819 GenerateParsingDoneCode(io::Printer* printer) const {
820 printer->Print(variables_,
821 "if ($is_mutable$) {\n"
822 " $make_name_unmodifiable$;\n"
823 "}\n");
824 }
825
826 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const827 GenerateSerializationCode(io::Printer* printer) const {
828 if (descriptor_->options().packed()) {
829 // We invoke getSerializedSize in writeTo for messages that have packed
830 // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
831 // That makes it safe to rely on the memoized size here.
832 printer->Print(variables_,
833 "if (get$capitalized_name$List().size() > 0) {\n"
834 " output.writeUInt32NoTag($tag$);\n"
835 " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
836 "}\n"
837 "for (int i = 0; i < $name$_.size(); i++) {\n"
838 " output.write$capitalized_type$NoTag($repeated_get$(i));\n"
839 "}\n");
840 } else {
841 printer->Print(variables_,
842 "for (int i = 0; i < $name$_.size(); i++) {\n"
843 " output.write$capitalized_type$($number$, $repeated_get$(i));\n"
844 "}\n");
845 }
846 }
847
848 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const849 GenerateSerializedSizeCode(io::Printer* printer) const {
850 printer->Print(variables_,
851 "{\n"
852 " int dataSize = 0;\n");
853 printer->Indent();
854
855 if (FixedSize(GetType(descriptor_)) == -1) {
856 printer->Print(variables_,
857 "for (int i = 0; i < $name$_.size(); i++) {\n"
858 " dataSize += com.google.protobuf.CodedOutputStream\n"
859 " .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
860 "}\n");
861 } else {
862 printer->Print(variables_,
863 "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
864 }
865
866 printer->Print(
867 "size += dataSize;\n");
868
869 if (descriptor_->options().packed()) {
870 printer->Print(variables_,
871 "if (!get$capitalized_name$List().isEmpty()) {\n"
872 " size += $tag_size$;\n"
873 " size += com.google.protobuf.CodedOutputStream\n"
874 " .computeInt32SizeNoTag(dataSize);\n"
875 "}\n");
876 } else {
877 printer->Print(variables_,
878 "size += $tag_size$ * get$capitalized_name$List().size();\n");
879 }
880
881 // cache the data size for packed fields.
882 if (descriptor_->options().packed()) {
883 printer->Print(variables_,
884 "$name$MemoizedSerializedSize = dataSize;\n");
885 }
886
887 printer->Outdent();
888 printer->Print("}\n");
889 }
890
891 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const892 GenerateEqualsCode(io::Printer* printer) const {
893 printer->Print(variables_,
894 "result = result && get$capitalized_name$List()\n"
895 " .equals(other.get$capitalized_name$List());\n");
896 }
897
898 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const899 GenerateHashCode(io::Printer* printer) const {
900 printer->Print(variables_,
901 "if (get$capitalized_name$Count() > 0) {\n"
902 " hash = (37 * hash) + $constant_name$;\n"
903 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
904 "}\n");
905 }
906
GetBoxedType() const907 string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
908 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
909 }
910
911 } // namespace java
912 } // namespace compiler
913 } // namespace protobuf
914 } // namespace google
915