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