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 // Author: jonp@google.com (Jon Perlow)
33 // Based on original Protocol Buffers design by
34 // Sanjay Ghemawat, Jeff Dean, and others.
35
36 #include <map>
37 #include <string>
38
39 #include <google/protobuf/stubs/logging.h>
40 #include <google/protobuf/stubs/common.h>
41 #include <google/protobuf/compiler/java/java_context.h>
42 #include <google/protobuf/compiler/java/java_doc_comment.h>
43 #include <google/protobuf/compiler/java/java_helpers.h>
44 #include <google/protobuf/compiler/java/java_name_resolver.h>
45 #include <google/protobuf/compiler/java/java_string_field_lite.h>
46 #include <google/protobuf/io/printer.h>
47 #include <google/protobuf/wire_format.h>
48 #include <google/protobuf/stubs/strutil.h>
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,map<string,string> * variables)60 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
61 int messageBitIndex,
62 int builderBitIndex,
63 const FieldGeneratorInfo* info,
64 ClassNameResolver* name_resolver,
65 map<string, string>* variables) {
66 SetCommonFieldVariables(descriptor, info, variables);
67
68 (*variables)["empty_list"] =
69 "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
70
71 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
72 (*variables)["default_init"] =
73 "= " + ImmutableDefaultValue(descriptor, name_resolver);
74 (*variables)["capitalized_type"] = "String";
75 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
76 (*variables)["tag_size"] = SimpleItoa(
77 WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
78 (*variables)["null_check"] =
79 " if (value == null) {\n"
80 " throw new NullPointerException();\n"
81 " }\n";
82
83 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
84 // by the proto compiler
85 (*variables)["deprecation"] = descriptor->options().deprecated()
86 ? "@java.lang.Deprecated " : "";
87
88 if (SupportFieldPresence(descriptor->file())) {
89 // For singular messages and builders, one bit is used for the hasField bit.
90 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
91
92 // Note that these have a trailing ";".
93 (*variables)["set_has_field_bit_message"] =
94 GenerateSetBit(messageBitIndex) + ";";
95 (*variables)["clear_has_field_bit_message"] =
96 GenerateClearBit(messageBitIndex) + ";";
97
98 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
99 } else {
100 (*variables)["set_has_field_bit_message"] = "";
101 (*variables)["clear_has_field_bit_message"] = "";
102
103 (*variables)["is_field_present_message"] =
104 "!" + (*variables)["name"] + "_.isEmpty()";
105 }
106
107 // For repeated builders, the underlying list tracks mutability state.
108 (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
109
110 (*variables)["get_has_field_bit_from_local"] =
111 GenerateGetBitFromLocal(builderBitIndex);
112 (*variables)["set_has_field_bit_to_local"] =
113 GenerateSetBitToLocal(messageBitIndex);
114 }
115
116 } // namespace
117
118 // ===================================================================
119
120 ImmutableStringFieldLiteGenerator::
ImmutableStringFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)121 ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
122 int messageBitIndex,
123 int builderBitIndex,
124 Context* context)
125 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
126 builderBitIndex_(builderBitIndex), context_(context),
127 name_resolver_(context->GetNameResolver()) {
128 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
129 context->GetFieldGeneratorInfo(descriptor),
130 name_resolver_, &variables_);
131 }
132
~ImmutableStringFieldLiteGenerator()133 ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
134
GetNumBitsForMessage() const135 int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
136 return 1;
137 }
138
GetNumBitsForBuilder() const139 int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
140 return 0;
141 }
142
143 // A note about how strings are handled. In the SPEED and CODE_SIZE runtimes,
144 // strings are not stored as java.lang.String in the Message because of two
145 // issues:
146 //
147 // 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
148 // strings, but rather fields that were raw bytes incorrectly marked
149 // as strings in the proto file. This is common because in the proto1
150 // syntax, string was the way to indicate bytes and C++ engineers can
151 // easily make this mistake without affecting the C++ API. By converting to
152 // strings immediately, some java code might corrupt these byte arrays as
153 // it passes through a java server even if the field was never accessed by
154 // application code.
155 //
156 // 2. There's a performance hit to converting between bytes and strings and
157 // it many cases, the field is never even read by the application code. This
158 // avoids unnecessary conversions in the common use cases.
159 //
160 // In the LITE_RUNTIME, we store strings as java.lang.String because we assume
161 // that the users of this runtime are not subject to proto1 constraints and are
162 // running code on devices that are user facing. That is, the developers are
163 // properly incentivized to only fetch the data they need to read and wish to
164 // reduce the number of allocations incurred when running on a user's device.
165
166 // TODO(dweis): Consider dropping all of the *Bytes() methods. They really
167 // shouldn't be necessary or used on devices.
168 void ImmutableStringFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const169 GenerateInterfaceMembers(io::Printer* printer) const {
170 if (SupportFieldPresence(descriptor_->file())) {
171 WriteFieldDocComment(printer, descriptor_);
172 printer->Print(variables_,
173 "$deprecation$boolean has$capitalized_name$();\n");
174 }
175 WriteFieldDocComment(printer, descriptor_);
176 printer->Print(variables_,
177 "$deprecation$java.lang.String get$capitalized_name$();\n");
178 WriteFieldDocComment(printer, descriptor_);
179 printer->Print(variables_,
180 "$deprecation$com.google.protobuf.ByteString\n"
181 " get$capitalized_name$Bytes();\n");
182 }
183
184 void ImmutableStringFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const185 GenerateMembers(io::Printer* printer) const {
186 printer->Print(variables_,
187 "private java.lang.String $name$_;\n");
188 PrintExtraFieldInfo(variables_, printer);
189
190 if (SupportFieldPresence(descriptor_->file())) {
191 WriteFieldDocComment(printer, descriptor_);
192 printer->Print(variables_,
193 "$deprecation$public boolean has$capitalized_name$() {\n"
194 " return $get_has_field_bit_message$;\n"
195 "}\n");
196 }
197
198 WriteFieldDocComment(printer, descriptor_);
199 printer->Print(variables_,
200 "$deprecation$public java.lang.String get$capitalized_name$() {\n"
201 " return $name$_;\n"
202 "}\n");
203 WriteFieldDocComment(printer, descriptor_);
204 printer->Print(variables_,
205 "$deprecation$public com.google.protobuf.ByteString\n"
206 " get$capitalized_name$Bytes() {\n"
207 " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
208 "}\n");
209
210 WriteFieldDocComment(printer, descriptor_);
211 printer->Print(variables_,
212 "private void set$capitalized_name$(\n"
213 " java.lang.String value) {\n"
214 "$null_check$"
215 " $set_has_field_bit_message$\n"
216 " $name$_ = value;\n"
217 "}\n");
218 WriteFieldDocComment(printer, descriptor_);
219 printer->Print(variables_,
220 "private void clear$capitalized_name$() {\n"
221 " $clear_has_field_bit_message$\n"
222 // The default value is not a simple literal so we want to avoid executing
223 // it multiple times. Instead, get the default out of the default instance.
224 " $name$_ = getDefaultInstance().get$capitalized_name$();\n"
225 "}\n");
226
227 WriteFieldDocComment(printer, descriptor_);
228 printer->Print(variables_,
229 "private void set$capitalized_name$Bytes(\n"
230 " com.google.protobuf.ByteString value) {\n"
231 "$null_check$");
232 if (CheckUtf8(descriptor_)) {
233 printer->Print(variables_,
234 " checkByteStringIsUtf8(value);\n");
235 }
236 printer->Print(variables_,
237 " $set_has_field_bit_message$\n"
238 " $name$_ = value.toStringUtf8();\n"
239 "}\n");
240 }
241
242 void ImmutableStringFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const243 GenerateBuilderMembers(io::Printer* printer) const {
244 if (SupportFieldPresence(descriptor_->file())) {
245 WriteFieldDocComment(printer, descriptor_);
246 printer->Print(variables_,
247 "$deprecation$public boolean has$capitalized_name$() {\n"
248 " return instance.has$capitalized_name$();\n"
249 "}\n");
250 }
251
252 WriteFieldDocComment(printer, descriptor_);
253 printer->Print(variables_,
254 "$deprecation$public java.lang.String get$capitalized_name$() {\n"
255 " return instance.get$capitalized_name$();\n"
256 "}\n");
257
258 WriteFieldDocComment(printer, descriptor_);
259 printer->Print(variables_,
260 "$deprecation$public com.google.protobuf.ByteString\n"
261 " get$capitalized_name$Bytes() {\n"
262 " return instance.get$capitalized_name$Bytes();\n"
263 "}\n");
264
265 WriteFieldDocComment(printer, descriptor_);
266 printer->Print(variables_,
267 "$deprecation$public Builder set$capitalized_name$(\n"
268 " java.lang.String value) {\n"
269 " copyOnWrite();\n"
270 " instance.set$capitalized_name$(value);\n"
271 " return this;\n"
272 "}\n");
273 WriteFieldDocComment(printer, descriptor_);
274 printer->Print(variables_,
275 "$deprecation$public Builder clear$capitalized_name$() {\n"
276 " copyOnWrite();\n"
277 " instance.clear$capitalized_name$();\n"
278 " return this;\n"
279 "}\n");
280
281 WriteFieldDocComment(printer, descriptor_);
282 printer->Print(variables_,
283 "$deprecation$public Builder set$capitalized_name$Bytes(\n"
284 " com.google.protobuf.ByteString value) {\n"
285 " copyOnWrite();\n"
286 " instance.set$capitalized_name$Bytes(value);\n"
287 " return this;\n"
288 "}\n");
289 }
290
291 void ImmutableStringFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const292 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
293 // noop for strings
294 }
295
296 void ImmutableStringFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const297 GenerateInitializationCode(io::Printer* printer) const {
298 printer->Print(variables_, "$name$_ = $default$;\n");
299 }
300
301 void ImmutableStringFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const302 GenerateVisitCode(io::Printer* printer) const {
303 if (SupportFieldPresence(descriptor_->file())) {
304 printer->Print(variables_,
305 "$name$_ = visitor.visitString(\n"
306 " has$capitalized_name$(), $name$_,\n"
307 " other.has$capitalized_name$(), other.$name$_);\n");
308 } else {
309 printer->Print(variables_,
310 "$name$_ = visitor.visitString(!$name$_.isEmpty(), $name$_,\n"
311 " !other.$name$_.isEmpty(), other.$name$_);\n");
312 }
313 }
314
315 void ImmutableStringFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const316 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
317 // noop for scalars
318 }
319
320 void ImmutableStringFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const321 GenerateParsingCode(io::Printer* printer) const {
322 if (CheckUtf8(descriptor_)) {
323 printer->Print(variables_,
324 "String s = input.readStringRequireUtf8();\n"
325 "$set_has_field_bit_message$\n"
326 "$name$_ = s;\n");
327 } else {
328 // Lite runtime should attempt to reduce allocations by attempting to
329 // construct the string directly from the input stream buffer. This avoids
330 // spurious intermediary ByteString allocations, cutting overall allocations
331 // in half.
332 printer->Print(variables_,
333 "String s = input.readString();\n"
334 "$set_has_field_bit_message$\n"
335 "$name$_ = s;\n");
336 }
337 }
338
339 void ImmutableStringFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const340 GenerateParsingDoneCode(io::Printer* printer) const {
341 // noop for strings
342 }
343
344 void ImmutableStringFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const345 GenerateSerializationCode(io::Printer* printer) const {
346 // Lite runtime should reduce allocations by serializing the string directly.
347 // This avoids spurious intermediary ByteString allocations, cutting overall
348 // allocations in half.
349 printer->Print(variables_,
350 "if ($is_field_present_message$) {\n"
351 " output.writeString($number$, get$capitalized_name$());\n"
352 "}\n");
353 }
354
355 void ImmutableStringFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const356 GenerateSerializedSizeCode(io::Printer* printer) const {
357 // Lite runtime should reduce allocations by computing on the string directly.
358 // This avoids spurious intermediary ByteString allocations, cutting overall
359 // allocations in half.
360 printer->Print(variables_,
361 "if ($is_field_present_message$) {\n"
362 " size += com.google.protobuf.CodedOutputStream\n"
363 " .computeStringSize($number$, get$capitalized_name$());\n"
364 "}\n");
365 }
366
367 void ImmutableStringFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const368 GenerateEqualsCode(io::Printer* printer) const {
369 printer->Print(variables_,
370 "result = result && get$capitalized_name$()\n"
371 " .equals(other.get$capitalized_name$());\n");
372 }
373
374 void ImmutableStringFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const375 GenerateHashCode(io::Printer* printer) const {
376 printer->Print(variables_,
377 "hash = (37 * hash) + $constant_name$;\n");
378 printer->Print(variables_,
379 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
380 }
381
GetBoxedType() const382 string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
383 return "java.lang.String";
384 }
385
386 // ===================================================================
387
388 ImmutableStringOneofFieldLiteGenerator::
ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)389 ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
390 int messageBitIndex,
391 int builderBitIndex,
392 Context* context)
393 : ImmutableStringFieldLiteGenerator(
394 descriptor, messageBitIndex, builderBitIndex, context) {
395 const OneofGeneratorInfo* info =
396 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
397 SetCommonOneofVariables(descriptor, info, &variables_);
398 }
399
400 ImmutableStringOneofFieldLiteGenerator::
~ImmutableStringOneofFieldLiteGenerator()401 ~ImmutableStringOneofFieldLiteGenerator() {}
402
403 void ImmutableStringOneofFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const404 GenerateMembers(io::Printer* printer) const {
405 PrintExtraFieldInfo(variables_, printer);
406
407 if (SupportFieldPresence(descriptor_->file())) {
408 WriteFieldDocComment(printer, descriptor_);
409 printer->Print(variables_,
410 "$deprecation$public boolean has$capitalized_name$() {\n"
411 " return $has_oneof_case_message$;\n"
412 "}\n");
413 }
414
415 WriteFieldDocComment(printer, descriptor_);
416 printer->Print(variables_,
417 "$deprecation$public java.lang.String get$capitalized_name$() {\n"
418 " java.lang.String ref $default_init$;\n"
419 " if ($has_oneof_case_message$) {\n"
420 " ref = (java.lang.String) $oneof_name$_;\n"
421 " }\n"
422 " return ref;\n"
423 "}\n");
424 WriteFieldDocComment(printer, descriptor_);
425
426 printer->Print(variables_,
427 "$deprecation$public com.google.protobuf.ByteString\n"
428 " get$capitalized_name$Bytes() {\n"
429 " java.lang.String ref $default_init$;\n"
430 " if ($has_oneof_case_message$) {\n"
431 " ref = (java.lang.String) $oneof_name$_;\n"
432 " }\n"
433 " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
434 "}\n");
435
436 WriteFieldDocComment(printer, descriptor_);
437 printer->Print(variables_,
438 "private void set$capitalized_name$(\n"
439 " java.lang.String value) {\n"
440 "$null_check$"
441 " $set_oneof_case_message$;\n"
442 " $oneof_name$_ = value;\n"
443 "}\n");
444 WriteFieldDocComment(printer, descriptor_);
445 printer->Print(variables_,
446 "private void clear$capitalized_name$() {\n"
447 " if ($has_oneof_case_message$) {\n"
448 " $clear_oneof_case_message$;\n"
449 " $oneof_name$_ = null;\n"
450 " }\n"
451 "}\n");
452
453 WriteFieldDocComment(printer, descriptor_);
454 printer->Print(variables_,
455 "private void set$capitalized_name$Bytes(\n"
456 " com.google.protobuf.ByteString value) {\n"
457 "$null_check$");
458 if (CheckUtf8(descriptor_)) {
459 printer->Print(variables_,
460 " checkByteStringIsUtf8(value);\n");
461 }
462 printer->Print(variables_,
463 " $set_oneof_case_message$;\n"
464 " $oneof_name$_ = value.toStringUtf8();\n"
465 "}\n");
466 }
467
468 void ImmutableStringOneofFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const469 GenerateBuilderMembers(io::Printer* printer) const {
470 if (SupportFieldPresence(descriptor_->file())) {
471 WriteFieldDocComment(printer, descriptor_);
472 printer->Print(variables_,
473 "$deprecation$public boolean has$capitalized_name$() {\n"
474 " return instance.has$capitalized_name$();\n"
475 "}\n");
476 }
477
478 WriteFieldDocComment(printer, descriptor_);
479 printer->Print(variables_,
480 "$deprecation$public java.lang.String get$capitalized_name$() {\n"
481 " return instance.get$capitalized_name$();\n"
482 "}\n");
483
484 WriteFieldDocComment(printer, descriptor_);
485 printer->Print(variables_,
486 "$deprecation$public com.google.protobuf.ByteString\n"
487 " get$capitalized_name$Bytes() {\n"
488 " return instance.get$capitalized_name$Bytes();\n"
489 "}\n");
490
491 WriteFieldDocComment(printer, descriptor_);
492 printer->Print(variables_,
493 "$deprecation$public Builder set$capitalized_name$(\n"
494 " java.lang.String value) {\n"
495 " copyOnWrite();\n"
496 " instance.set$capitalized_name$(value);\n"
497 " return this;\n"
498 "}\n");
499 WriteFieldDocComment(printer, descriptor_);
500 printer->Print(variables_,
501 "$deprecation$public Builder clear$capitalized_name$() {\n"
502 " copyOnWrite();\n"
503 " instance.clear$capitalized_name$();\n"
504 " return this;\n"
505 "}\n");
506
507 WriteFieldDocComment(printer, descriptor_);
508 printer->Print(variables_,
509 "$deprecation$public Builder set$capitalized_name$Bytes(\n"
510 " com.google.protobuf.ByteString value) {\n"
511 " copyOnWrite();\n"
512 " instance.set$capitalized_name$Bytes(value);\n"
513 " return this;\n"
514 "}\n");
515 }
516
517 void ImmutableStringOneofFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const518 GenerateVisitCode(io::Printer* printer) const {
519 printer->Print(variables_,
520 "$oneof_name$_ = visitor.visitOneofString(\n"
521 " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
522 }
523
524 void ImmutableStringOneofFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const525 GenerateParsingCode(io::Printer* printer) const {
526 if (CheckUtf8(descriptor_)) {
527 printer->Print(variables_,
528 "String s = input.readStringRequireUtf8();\n"
529 "$set_oneof_case_message$;\n"
530 "$oneof_name$_ = s;\n");
531 } else {
532 // Lite runtime should attempt to reduce allocations by attempting to
533 // construct the string directly from the input stream buffer. This avoids
534 // spurious intermediary ByteString allocations, cutting overall allocations
535 // in half.
536 printer->Print(variables_,
537 "String s = input.readString();\n"
538 "$set_oneof_case_message$;\n"
539 "$oneof_name$_ = s;\n");
540 }
541 }
542
543 void ImmutableStringOneofFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const544 GenerateSerializationCode(io::Printer* printer) const {
545 // Lite runtime should reduce allocations by serializing the string directly.
546 // This avoids spurious intermediary ByteString allocations, cutting overall
547 // allocations in half.
548 printer->Print(variables_,
549 "if ($has_oneof_case_message$) {\n"
550 " output.writeString($number$, get$capitalized_name$());\n"
551 "}\n");
552 }
553
554 void ImmutableStringOneofFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const555 GenerateSerializedSizeCode(io::Printer* printer) const {
556 // Lite runtime should reduce allocations by computing on the string directly.
557 // This avoids spurious intermediary ByteString allocations, cutting overall
558 // allocations in half.
559 printer->Print(variables_,
560 "if ($has_oneof_case_message$) {\n"
561 " size += com.google.protobuf.CodedOutputStream\n"
562 " .computeStringSize($number$, get$capitalized_name$());\n"
563 "}\n");
564 }
565
566 // ===================================================================
567
568 RepeatedImmutableStringFieldLiteGenerator::
RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)569 RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
570 int messageBitIndex,
571 int builderBitIndex,
572 Context* context)
573 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
574 builderBitIndex_(builderBitIndex), context_(context),
575 name_resolver_(context->GetNameResolver()) {
576 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
577 context->GetFieldGeneratorInfo(descriptor),
578 name_resolver_, &variables_);
579 }
580
581 RepeatedImmutableStringFieldLiteGenerator::
~RepeatedImmutableStringFieldLiteGenerator()582 ~RepeatedImmutableStringFieldLiteGenerator() {}
583
GetNumBitsForMessage() const584 int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
585 return 0;
586 }
587
GetNumBitsForBuilder() const588 int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
589 return 0;
590 }
591
592 void RepeatedImmutableStringFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const593 GenerateInterfaceMembers(io::Printer* printer) const {
594 WriteFieldDocComment(printer, descriptor_);
595 printer->Print(variables_,
596 "$deprecation$java.util.List<String>\n"
597 " get$capitalized_name$List();\n");
598 WriteFieldDocComment(printer, descriptor_);
599 printer->Print(variables_,
600 "$deprecation$int get$capitalized_name$Count();\n");
601 WriteFieldDocComment(printer, descriptor_);
602 printer->Print(variables_,
603 "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
604 WriteFieldDocComment(printer, descriptor_);
605 printer->Print(variables_,
606 "$deprecation$com.google.protobuf.ByteString\n"
607 " get$capitalized_name$Bytes(int index);\n");
608 }
609
610
611 void RepeatedImmutableStringFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const612 GenerateMembers(io::Printer* printer) const {
613 printer->Print(variables_,
614 "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n");
615 PrintExtraFieldInfo(variables_, printer);
616 WriteFieldDocComment(printer, descriptor_);
617 printer->Print(variables_,
618 "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n"
619 " return $name$_;\n" // note: unmodifiable list
620 "}\n");
621 WriteFieldDocComment(printer, descriptor_);
622 printer->Print(variables_,
623 "$deprecation$public int get$capitalized_name$Count() {\n"
624 " return $name$_.size();\n"
625 "}\n");
626 WriteFieldDocComment(printer, descriptor_);
627 printer->Print(variables_,
628 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
629 " return $name$_.get(index);\n"
630 "}\n");
631 WriteFieldDocComment(printer, descriptor_);
632 printer->Print(variables_,
633 "$deprecation$public com.google.protobuf.ByteString\n"
634 " get$capitalized_name$Bytes(int index) {\n"
635 " return com.google.protobuf.ByteString.copyFromUtf8(\n"
636 " $name$_.get(index));\n"
637 "}\n");
638
639 printer->Print(variables_,
640 "private void ensure$capitalized_name$IsMutable() {\n"
641 " if (!$is_mutable$) {\n"
642 " $name$_ =\n"
643 " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
644 " }\n"
645 "}\n");
646
647 WriteFieldDocComment(printer, descriptor_);
648 printer->Print(variables_,
649 "private void set$capitalized_name$(\n"
650 " int index, java.lang.String value) {\n"
651 "$null_check$"
652 " ensure$capitalized_name$IsMutable();\n"
653 " $name$_.set(index, value);\n"
654 "}\n");
655 WriteFieldDocComment(printer, descriptor_);
656 printer->Print(variables_,
657 "private void add$capitalized_name$(\n"
658 " java.lang.String value) {\n"
659 "$null_check$"
660 " ensure$capitalized_name$IsMutable();\n"
661 " $name$_.add(value);\n"
662 "}\n");
663 WriteFieldDocComment(printer, descriptor_);
664 printer->Print(variables_,
665 "private void addAll$capitalized_name$(\n"
666 " java.lang.Iterable<java.lang.String> 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 WriteFieldDocComment(printer, descriptor_);
678 printer->Print(variables_,
679 "private void add$capitalized_name$Bytes(\n"
680 " com.google.protobuf.ByteString value) {\n"
681 "$null_check$");
682 if (CheckUtf8(descriptor_)) {
683 printer->Print(variables_,
684 " checkByteStringIsUtf8(value);\n");
685 }
686 printer->Print(variables_,
687 " ensure$capitalized_name$IsMutable();\n"
688 " $name$_.add(value.toStringUtf8());\n"
689 "}\n");
690 }
691
692 void RepeatedImmutableStringFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const693 GenerateBuilderMembers(io::Printer* printer) const {
694 WriteFieldDocComment(printer, descriptor_);
695 printer->Print(variables_,
696 "$deprecation$public java.util.List<String>\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 java.lang.String 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 com.google.protobuf.ByteString\n"
714 " get$capitalized_name$Bytes(int index) {\n"
715 " return instance.get$capitalized_name$Bytes(index);\n"
716 "}\n");
717 WriteFieldDocComment(printer, descriptor_);
718 printer->Print(variables_,
719 "$deprecation$public Builder set$capitalized_name$(\n"
720 " int index, java.lang.String value) {\n"
721 " copyOnWrite();\n"
722 " instance.set$capitalized_name$(index, value);\n"
723 " return this;\n"
724 "}\n");
725 WriteFieldDocComment(printer, descriptor_);
726 printer->Print(variables_,
727 "$deprecation$public Builder add$capitalized_name$(\n"
728 " java.lang.String value) {\n"
729 " copyOnWrite();\n"
730 " instance.add$capitalized_name$(value);\n"
731 " return this;\n"
732 "}\n");
733 WriteFieldDocComment(printer, descriptor_);
734 printer->Print(variables_,
735 "$deprecation$public Builder addAll$capitalized_name$(\n"
736 " java.lang.Iterable<java.lang.String> values) {\n"
737 " copyOnWrite();\n"
738 " instance.addAll$capitalized_name$(values);\n"
739 " return this;\n"
740 "}\n");
741 WriteFieldDocComment(printer, descriptor_);
742 printer->Print(variables_,
743 "$deprecation$public Builder clear$capitalized_name$() {\n"
744 " copyOnWrite();\n"
745 " instance.clear$capitalized_name$();\n"
746 " return this;\n"
747 "}\n");
748
749 WriteFieldDocComment(printer, descriptor_);
750 printer->Print(variables_,
751 "$deprecation$public Builder add$capitalized_name$Bytes(\n"
752 " com.google.protobuf.ByteString value) {\n"
753 " copyOnWrite();\n"
754 " instance.add$capitalized_name$Bytes(value);\n"
755 " return this;\n"
756 "}\n");
757 }
758
759 void RepeatedImmutableStringFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const760 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
761 // noop for strings
762 }
763
764 void RepeatedImmutableStringFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const765 GenerateInitializationCode(io::Printer* printer) const {
766 printer->Print(variables_, "$name$_ = $empty_list$;\n");
767 }
768
769 void RepeatedImmutableStringFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const770 GenerateVisitCode(io::Printer* printer) const {
771 printer->Print(variables_,
772 "$name$_= visitor.visitList($name$_, other.$name$_);\n");
773 }
774
775 void RepeatedImmutableStringFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const776 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
777 printer->Print(variables_,
778 "$name$_.makeImmutable();\n");
779 }
780
781 void RepeatedImmutableStringFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const782 GenerateParsingCode(io::Printer* printer) const {
783 if (CheckUtf8(descriptor_)) {
784 printer->Print(variables_,
785 "String s = input.readStringRequireUtf8();\n");
786 } else {
787 // Lite runtime should attempt to reduce allocations by attempting to
788 // construct the string directly from the input stream buffer. This avoids
789 // spurious intermediary ByteString allocations, cutting overall allocations
790 // in half.
791 printer->Print(variables_,
792 "String s = input.readString();\n");
793 }
794 printer->Print(variables_,
795 "if (!$is_mutable$) {\n"
796 " $name$_ =\n"
797 " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
798 "}\n");
799 printer->Print(variables_,
800 "$name$_.add(s);\n");
801 }
802
803 void RepeatedImmutableStringFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const804 GenerateParsingDoneCode(io::Printer* printer) const {
805 printer->Print(variables_,
806 "if ($is_mutable$) {\n"
807 " $name$_.makeImmutable();\n"
808 "}\n");
809 }
810
811 void RepeatedImmutableStringFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const812 GenerateSerializationCode(io::Printer* printer) const {
813 // Lite runtime should reduce allocations by serializing the string directly.
814 // This avoids spurious intermediary ByteString allocations, cutting overall
815 // allocations in half.
816 printer->Print(variables_,
817 "for (int i = 0; i < $name$_.size(); i++) {\n"
818 " output.writeString($number$, $name$_.get(i));\n"
819 "}\n");
820 }
821
822 void RepeatedImmutableStringFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const823 GenerateSerializedSizeCode(io::Printer* printer) const {
824 // Lite runtime should reduce allocations by computing on the string directly.
825 // This avoids spurious intermediary ByteString allocations, cutting overall
826 // allocations in half.
827 printer->Print(variables_,
828 "{\n"
829 " int dataSize = 0;\n");
830 printer->Indent();
831
832 printer->Print(variables_,
833 "for (int i = 0; i < $name$_.size(); i++) {\n"
834 " dataSize += com.google.protobuf.CodedOutputStream\n"
835 " .computeStringSizeNoTag($name$_.get(i));\n"
836 "}\n");
837
838 printer->Print(
839 "size += dataSize;\n");
840
841
842 printer->Print(variables_,
843 "size += $tag_size$ * get$capitalized_name$List().size();\n");
844
845 printer->Outdent();
846 printer->Print("}\n");
847 }
848
849 void RepeatedImmutableStringFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const850 GenerateEqualsCode(io::Printer* printer) const {
851 printer->Print(variables_,
852 "result = result && get$capitalized_name$List()\n"
853 " .equals(other.get$capitalized_name$List());\n");
854 }
855
856 void RepeatedImmutableStringFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const857 GenerateHashCode(io::Printer* printer) const {
858 printer->Print(variables_,
859 "if (get$capitalized_name$Count() > 0) {\n"
860 " hash = (37 * hash) + $constant_name$;\n"
861 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
862 "}\n");
863 }
864
GetBoxedType() const865 string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
866 return "String";
867 }
868
869 } // namespace java
870 } // namespace compiler
871 } // namespace protobuf
872 } // namespace google
873