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 "google/protobuf/compiler/java/string_field.h"
37
38 #include <cstdint>
39 #include <map>
40 #include <string>
41
42 #include "google/protobuf/stubs/logging.h"
43 #include "google/protobuf/stubs/common.h"
44 #include "google/protobuf/io/printer.h"
45 #include "google/protobuf/wire_format.h"
46 #include "google/protobuf/stubs/strutil.h"
47 #include "google/protobuf/compiler/java/context.h"
48 #include "google/protobuf/compiler/java/doc_comment.h"
49 #include "google/protobuf/compiler/java/helpers.h"
50 #include "google/protobuf/compiler/java/name_resolver.h"
51
52 namespace google {
53 namespace protobuf {
54 namespace compiler {
55 namespace java {
56
57 using internal::WireFormat;
58 using internal::WireFormatLite;
59
60 namespace {
61
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables,Context * context)62 void SetPrimitiveVariables(
63 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
64 const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
65 std::map<std::string, std::string>* variables,
66 Context* context) {
67 SetCommonFieldVariables(descriptor, info, variables);
68
69 (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
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"] =
76 StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
77 (*variables)["tag_size"] = StrCat(
78 WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
79 (*variables)["null_check"] =
80 "if (value == null) { throw new NullPointerException(); }";
81 (*variables)["isStringEmpty"] = "com.google.protobuf.GeneratedMessage" +
82 GeneratedCodeVersionSuffix() +
83 ".isStringEmpty";
84 (*variables)["writeString"] = "com.google.protobuf.GeneratedMessage" +
85 GeneratedCodeVersionSuffix() + ".writeString";
86 (*variables)["computeStringSize"] = "com.google.protobuf.GeneratedMessage" +
87 GeneratedCodeVersionSuffix() +
88 ".computeStringSize";
89
90 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
91 // by the proto compiler
92 (*variables)["deprecation"] =
93 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
94 variables->insert(
95 {"kt_deprecation",
96 descriptor->options().deprecated()
97 ? StrCat("@kotlin.Deprecated(message = \"Field ",
98 (*variables)["name"], " is deprecated\") ")
99 : ""});
100 (*variables)["on_changed"] = "onChanged();";
101
102 if (HasHasbit(descriptor)) {
103 // For singular messages and builders, one bit is used for the hasField bit.
104 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
105 (*variables)["set_has_field_bit_to_local"] =
106 GenerateSetBitToLocal(messageBitIndex);
107
108 // Note that these have a trailing ";".
109 (*variables)["set_has_field_bit_message"] =
110 GenerateSetBit(messageBitIndex) + ";";
111
112 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
113 } else {
114 (*variables)["get_has_field_bit_message"] = "";
115 (*variables)["set_has_field_bit_to_local"] = "";
116 (*variables)["set_has_field_bit_message"] = "";
117
118 variables->insert({"is_field_present_message",
119 StrCat("!", (*variables)["isStringEmpty"], "(",
120 (*variables)["name"], "_)")});
121 }
122
123 // For repeated builders, one bit is used for whether the array is immutable.
124 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
125 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
126 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
127
128 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
129 (*variables)["get_has_field_bit_from_local"] =
130 GenerateGetBitFromLocal(builderBitIndex);
131 (*variables)["set_has_field_bit_builder"] =
132 GenerateSetBit(builderBitIndex) + ";";
133 (*variables)["clear_has_field_bit_builder"] =
134 GenerateClearBit(builderBitIndex) + ";";
135 }
136
137 } // namespace
138
139 // ===================================================================
140
ImmutableStringFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)141 ImmutableStringFieldGenerator::ImmutableStringFieldGenerator(
142 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
143 Context* context)
144 : descriptor_(descriptor),
145 message_bit_index_(messageBitIndex),
146 builder_bit_index_(builderBitIndex),
147 name_resolver_(context->GetNameResolver()) {
148 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
149 context->GetFieldGeneratorInfo(descriptor),
150 name_resolver_, &variables_, context);
151 }
152
~ImmutableStringFieldGenerator()153 ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
154
GetMessageBitIndex() const155 int ImmutableStringFieldGenerator::GetMessageBitIndex() const {
156 return message_bit_index_;
157 }
158
GetBuilderBitIndex() const159 int ImmutableStringFieldGenerator::GetBuilderBitIndex() const {
160 return builder_bit_index_;
161 }
162
GetNumBitsForMessage() const163 int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
164 return HasHasbit(descriptor_) ? 1 : 0;
165 }
166
GetNumBitsForBuilder() const167 int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { return 1; }
168
169 // A note about how strings are handled. This code used to just store a String
170 // in the Message. This had two issues:
171 //
172 // 1. It wouldn't roundtrip byte arrays that were not valid UTF-8 encoded
173 // strings, but rather fields that were raw bytes incorrectly marked
174 // as strings in the proto file. This is common because in the proto1
175 // syntax, string was the way to indicate bytes and C++ engineers can
176 // easily make this mistake without affecting the C++ API. By converting to
177 // strings immediately, some java code might corrupt these byte arrays as
178 // it passes through a java server even if the field was never accessed by
179 // application code.
180 //
181 // 2. There's a performance hit to converting between bytes and strings and
182 // it many cases, the field is never even read by the application code. This
183 // avoids unnecessary conversions in the common use cases.
184 //
185 // So now, the field for String is maintained as an Object reference which can
186 // either store a String or a ByteString. The code uses an instanceof check
187 // to see which one it has and converts to the other one if needed. It remembers
188 // the last value requested (in a thread safe manner) as this is most likely
189 // the one needed next. The thread safety is such that if two threads both
190 // convert the field because the changes made by each thread were not visible to
191 // the other, they may cause a conversion to happen more times than would
192 // otherwise be necessary. This was deemed better than adding synchronization
193 // overhead. It will not cause any corruption issues or affect the behavior of
194 // the API. The instanceof check is also highly optimized in the JVM and we
195 // decided it was better to reduce the memory overhead by not having two
196 // separate fields but rather use dynamic type checking.
197 //
198 // For single fields, the logic for this is done inside the generated code. For
199 // repeated fields, the logic is done in LazyStringArrayList and
200 // UnmodifiableLazyStringList.
GenerateInterfaceMembers(io::Printer * printer) const201 void ImmutableStringFieldGenerator::GenerateInterfaceMembers(
202 io::Printer* printer) const {
203 if (HasHazzer(descriptor_)) {
204 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
205 printer->Print(variables_,
206 "$deprecation$boolean has$capitalized_name$();\n");
207 }
208 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
209 printer->Print(variables_,
210 "$deprecation$java.lang.String get$capitalized_name$();\n");
211 WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
212 printer->Print(variables_,
213 "$deprecation$com.google.protobuf.ByteString\n"
214 " get$capitalized_name$Bytes();\n");
215 }
216
GenerateMembers(io::Printer * printer) const217 void ImmutableStringFieldGenerator::GenerateMembers(
218 io::Printer* printer) const {
219 printer->Print(variables_,
220 "@SuppressWarnings(\"serial\")\n"
221 "private volatile java.lang.Object $name$_ = $default$;\n");
222 PrintExtraFieldInfo(variables_, printer);
223
224 if (HasHazzer(descriptor_)) {
225 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
226 printer->Print(
227 variables_,
228 "@java.lang.Override\n"
229 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
230 " return $get_has_field_bit_message$;\n"
231 "}\n");
232 printer->Annotate("{", "}", descriptor_);
233 }
234
235 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
236 printer->Print(
237 variables_,
238 "@java.lang.Override\n"
239 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
240 " java.lang.Object ref = $name$_;\n"
241 " if (ref instanceof java.lang.String) {\n"
242 " return (java.lang.String) ref;\n"
243 " } else {\n"
244 " com.google.protobuf.ByteString bs = \n"
245 " (com.google.protobuf.ByteString) ref;\n"
246 " java.lang.String s = bs.toStringUtf8();\n");
247 printer->Annotate("{", "}", descriptor_);
248 if (CheckUtf8(descriptor_)) {
249 printer->Print(variables_, " $name$_ = s;\n");
250 } else {
251 printer->Print(variables_,
252 " if (bs.isValidUtf8()) {\n"
253 " $name$_ = s;\n"
254 " }\n");
255 }
256 printer->Print(variables_,
257 " return s;\n"
258 " }\n"
259 "}\n");
260 WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
261 printer->Print(variables_,
262 "@java.lang.Override\n"
263 "$deprecation$public com.google.protobuf.ByteString\n"
264 " ${$get$capitalized_name$Bytes$}$() {\n"
265 " java.lang.Object ref = $name$_;\n"
266 " if (ref instanceof java.lang.String) {\n"
267 " com.google.protobuf.ByteString b = \n"
268 " com.google.protobuf.ByteString.copyFromUtf8(\n"
269 " (java.lang.String) ref);\n"
270 " $name$_ = b;\n"
271 " return b;\n"
272 " } else {\n"
273 " return (com.google.protobuf.ByteString) ref;\n"
274 " }\n"
275 "}\n");
276 printer->Annotate("{", "}", descriptor_);
277 }
278
GenerateBuilderMembers(io::Printer * printer) const279 void ImmutableStringFieldGenerator::GenerateBuilderMembers(
280 io::Printer* printer) const {
281 printer->Print(variables_,
282 "private java.lang.Object $name$_ $default_init$;\n");
283 if (HasHazzer(descriptor_)) {
284 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
285 printer->Print(
286 variables_,
287 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
288 " return $get_has_field_bit_builder$;\n"
289 "}\n");
290 printer->Annotate("{", "}", descriptor_);
291 }
292
293 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
294 printer->Print(
295 variables_,
296 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
297 " java.lang.Object ref = $name$_;\n"
298 " if (!(ref instanceof java.lang.String)) {\n"
299 " com.google.protobuf.ByteString bs =\n"
300 " (com.google.protobuf.ByteString) ref;\n"
301 " java.lang.String s = bs.toStringUtf8();\n");
302 printer->Annotate("{", "}", descriptor_);
303 if (CheckUtf8(descriptor_)) {
304 printer->Print(variables_, " $name$_ = s;\n");
305 } else {
306 printer->Print(variables_,
307 " if (bs.isValidUtf8()) {\n"
308 " $name$_ = s;\n"
309 " }\n");
310 }
311 printer->Print(variables_,
312 " return s;\n"
313 " } else {\n"
314 " return (java.lang.String) ref;\n"
315 " }\n"
316 "}\n");
317
318 WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
319 printer->Print(variables_,
320 "$deprecation$public com.google.protobuf.ByteString\n"
321 " ${$get$capitalized_name$Bytes$}$() {\n"
322 " java.lang.Object ref = $name$_;\n"
323 " if (ref instanceof String) {\n"
324 " com.google.protobuf.ByteString b = \n"
325 " com.google.protobuf.ByteString.copyFromUtf8(\n"
326 " (java.lang.String) ref);\n"
327 " $name$_ = b;\n"
328 " return b;\n"
329 " } else {\n"
330 " return (com.google.protobuf.ByteString) ref;\n"
331 " }\n"
332 "}\n");
333 printer->Annotate("{", "}", descriptor_);
334
335 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
336 /* builder */ true);
337 printer->Print(variables_,
338 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
339 " java.lang.String value) {\n"
340 " $null_check$\n"
341 " $name$_ = value;\n"
342 " $set_has_field_bit_builder$\n"
343 " $on_changed$\n"
344 " return this;\n"
345 "}\n");
346 printer->Annotate("{", "}", descriptor_);
347 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
348 /* builder */ true);
349 printer->Print(
350 variables_,
351 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n");
352 printer->Annotate("{", "}", descriptor_);
353 // The default value is not a simple literal so we want to avoid executing
354 // it multiple times. Instead, get the default out of the default instance.
355 printer->Print(variables_,
356 " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
357 printer->Print(variables_,
358 " $clear_has_field_bit_builder$\n"
359 " $on_changed$\n"
360 " return this;\n"
361 "}\n");
362
363 WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
364 /* builder */ true);
365 printer->Print(
366 variables_,
367 "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
368 " com.google.protobuf.ByteString value) {\n"
369 " $null_check$\n");
370 printer->Annotate("{", "}", descriptor_);
371 if (CheckUtf8(descriptor_)) {
372 printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
373 }
374 printer->Print(variables_,
375 " $name$_ = value;\n"
376 " $set_has_field_bit_builder$\n"
377 " $on_changed$\n"
378 " return this;\n"
379 "}\n");
380 }
381
GenerateKotlinDslMembers(io::Printer * printer) const382 void ImmutableStringFieldGenerator::GenerateKotlinDslMembers(
383 io::Printer* printer) const {
384 WriteFieldDocComment(printer, descriptor_);
385 printer->Print(variables_,
386 "$kt_deprecation$public var $kt_name$: kotlin.String\n"
387 " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
388 " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
389 " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
390 " set(value) {\n"
391 " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
392 " }\n");
393
394 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
395 /* builder */ false);
396 printer->Print(variables_,
397 "public fun ${$clear$kt_capitalized_name$$}$() {\n"
398 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
399 "}\n");
400
401 if (HasHazzer(descriptor_)) {
402 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
403 printer->Print(
404 variables_,
405 "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
406 " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
407 "}\n");
408 }
409 }
410
GenerateFieldBuilderInitializationCode(io::Printer * printer) const411 void ImmutableStringFieldGenerator::GenerateFieldBuilderInitializationCode(
412 io::Printer* printer) const {
413 // noop for primitives
414 }
415
GenerateInitializationCode(io::Printer * printer) const416 void ImmutableStringFieldGenerator::GenerateInitializationCode(
417 io::Printer* printer) const {
418 printer->Print(variables_, "$name$_ = $default$;\n");
419 }
420
GenerateBuilderClearCode(io::Printer * printer) const421 void ImmutableStringFieldGenerator::GenerateBuilderClearCode(
422 io::Printer* printer) const {
423 printer->Print(variables_, "$name$_ = $default$;\n");
424 }
425
GenerateMergingCode(io::Printer * printer) const426 void ImmutableStringFieldGenerator::GenerateMergingCode(
427 io::Printer* printer) const {
428 if (HasHazzer(descriptor_)) {
429 // Allow a slight breach of abstraction here in order to avoid forcing
430 // all string fields to Strings when copying fields from a Message.
431 printer->Print(variables_,
432 "if (other.has$capitalized_name$()) {\n"
433 " $name$_ = other.$name$_;\n"
434 " $set_has_field_bit_builder$\n"
435 " $on_changed$\n"
436 "}\n");
437 } else {
438 printer->Print(variables_,
439 "if (!other.get$capitalized_name$().isEmpty()) {\n"
440 " $name$_ = other.$name$_;\n"
441 " $set_has_field_bit_builder$\n"
442 " $on_changed$\n"
443 "}\n");
444 }
445 }
446
GenerateBuildingCode(io::Printer * printer) const447 void ImmutableStringFieldGenerator::GenerateBuildingCode(
448 io::Printer* printer) const {
449 printer->Print(variables_,
450 "if ($get_has_field_bit_from_local$) {\n"
451 " result.$name$_ = $name$_;\n");
452 if (GetNumBitsForMessage() > 0) {
453 printer->Print(variables_, " $set_has_field_bit_to_local$;\n");
454 }
455 printer->Print("}\n");
456 }
457
GenerateBuilderParsingCode(io::Printer * printer) const458 void ImmutableStringFieldGenerator::GenerateBuilderParsingCode(
459 io::Printer* printer) const {
460 if (CheckUtf8(descriptor_)) {
461 printer->Print(variables_,
462 "$name$_ = input.readStringRequireUtf8();\n"
463 "$set_has_field_bit_builder$\n");
464 } else {
465 printer->Print(variables_,
466 "$name$_ = input.readBytes();\n"
467 "$set_has_field_bit_builder$\n");
468 }
469 }
470
GenerateSerializationCode(io::Printer * printer) const471 void ImmutableStringFieldGenerator::GenerateSerializationCode(
472 io::Printer* printer) const {
473 printer->Print(variables_,
474 "if ($is_field_present_message$) {\n"
475 " $writeString$(output, $number$, $name$_);\n"
476 "}\n");
477 }
478
GenerateSerializedSizeCode(io::Printer * printer) const479 void ImmutableStringFieldGenerator::GenerateSerializedSizeCode(
480 io::Printer* printer) const {
481 printer->Print(variables_,
482 "if ($is_field_present_message$) {\n"
483 " size += $computeStringSize$($number$, $name$_);\n"
484 "}\n");
485 }
486
GenerateEqualsCode(io::Printer * printer) const487 void ImmutableStringFieldGenerator::GenerateEqualsCode(
488 io::Printer* printer) const {
489 printer->Print(variables_,
490 "if (!get$capitalized_name$()\n"
491 " .equals(other.get$capitalized_name$())) return false;\n");
492 }
493
GenerateHashCode(io::Printer * printer) const494 void ImmutableStringFieldGenerator::GenerateHashCode(
495 io::Printer* printer) const {
496 printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
497 printer->Print(variables_,
498 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
499 }
500
GetBoxedType() const501 std::string ImmutableStringFieldGenerator::GetBoxedType() const {
502 return "java.lang.String";
503 }
504
505 // ===================================================================
506
ImmutableStringOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)507 ImmutableStringOneofFieldGenerator::ImmutableStringOneofFieldGenerator(
508 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
509 Context* context)
510 : ImmutableStringFieldGenerator(descriptor, messageBitIndex,
511 builderBitIndex, context) {
512 const OneofGeneratorInfo* info =
513 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
514 SetCommonOneofVariables(descriptor, info, &variables_);
515 }
516
~ImmutableStringOneofFieldGenerator()517 ImmutableStringOneofFieldGenerator::~ImmutableStringOneofFieldGenerator() {}
518
GenerateMembers(io::Printer * printer) const519 void ImmutableStringOneofFieldGenerator::GenerateMembers(
520 io::Printer* printer) const {
521 PrintExtraFieldInfo(variables_, printer);
522 GOOGLE_DCHECK(HasHazzer(descriptor_));
523 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
524 printer->Print(variables_,
525 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
526 " return $has_oneof_case_message$;\n"
527 "}\n");
528 printer->Annotate("{", "}", descriptor_);
529
530 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
531 printer->Print(
532 variables_,
533 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
534 " java.lang.Object ref $default_init$;\n"
535 " if ($has_oneof_case_message$) {\n"
536 " ref = $oneof_name$_;\n"
537 " }\n"
538 " if (ref instanceof java.lang.String) {\n"
539 " return (java.lang.String) ref;\n"
540 " } else {\n"
541 " com.google.protobuf.ByteString bs = \n"
542 " (com.google.protobuf.ByteString) ref;\n"
543 " java.lang.String s = bs.toStringUtf8();\n");
544 printer->Annotate("{", "}", descriptor_);
545 if (CheckUtf8(descriptor_)) {
546 printer->Print(variables_,
547 " if ($has_oneof_case_message$) {\n"
548 " $oneof_name$_ = s;\n"
549 " }\n");
550 } else {
551 printer->Print(variables_,
552 " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
553 " $oneof_name$_ = s;\n"
554 " }\n");
555 }
556 printer->Print(variables_,
557 " return s;\n"
558 " }\n"
559 "}\n");
560 WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
561
562 printer->Print(variables_,
563 "$deprecation$public com.google.protobuf.ByteString\n"
564 " ${$get$capitalized_name$Bytes$}$() {\n"
565 " java.lang.Object ref $default_init$;\n"
566 " if ($has_oneof_case_message$) {\n"
567 " ref = $oneof_name$_;\n"
568 " }\n"
569 " if (ref instanceof java.lang.String) {\n"
570 " com.google.protobuf.ByteString b = \n"
571 " com.google.protobuf.ByteString.copyFromUtf8(\n"
572 " (java.lang.String) ref);\n"
573 " if ($has_oneof_case_message$) {\n"
574 " $oneof_name$_ = b;\n"
575 " }\n"
576 " return b;\n"
577 " } else {\n"
578 " return (com.google.protobuf.ByteString) ref;\n"
579 " }\n"
580 "}\n");
581 printer->Annotate("{", "}", descriptor_);
582 }
583
GenerateBuilderMembers(io::Printer * printer) const584 void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
585 io::Printer* printer) const {
586 GOOGLE_DCHECK(HasHazzer(descriptor_));
587 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
588 printer->Print(variables_,
589 "@java.lang.Override\n"
590 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
591 " return $has_oneof_case_message$;\n"
592 "}\n");
593 printer->Annotate("{", "}", descriptor_);
594
595 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
596 printer->Print(
597 variables_,
598 "@java.lang.Override\n"
599 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
600 " java.lang.Object ref $default_init$;\n"
601 " if ($has_oneof_case_message$) {\n"
602 " ref = $oneof_name$_;\n"
603 " }\n"
604 " if (!(ref instanceof java.lang.String)) {\n"
605 " com.google.protobuf.ByteString bs =\n"
606 " (com.google.protobuf.ByteString) ref;\n"
607 " java.lang.String s = bs.toStringUtf8();\n"
608 " if ($has_oneof_case_message$) {\n");
609 printer->Annotate("{", "}", descriptor_);
610 if (CheckUtf8(descriptor_)) {
611 printer->Print(variables_, " $oneof_name$_ = s;\n");
612 } else {
613 printer->Print(variables_,
614 " if (bs.isValidUtf8()) {\n"
615 " $oneof_name$_ = s;\n"
616 " }\n");
617 }
618 printer->Print(variables_,
619 " }\n"
620 " return s;\n"
621 " } else {\n"
622 " return (java.lang.String) ref;\n"
623 " }\n"
624 "}\n");
625
626 WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
627 printer->Print(variables_,
628 "@java.lang.Override\n"
629 "$deprecation$public com.google.protobuf.ByteString\n"
630 " ${$get$capitalized_name$Bytes$}$() {\n"
631 " java.lang.Object ref $default_init$;\n"
632 " if ($has_oneof_case_message$) {\n"
633 " ref = $oneof_name$_;\n"
634 " }\n"
635 " if (ref instanceof String) {\n"
636 " com.google.protobuf.ByteString b = \n"
637 " com.google.protobuf.ByteString.copyFromUtf8(\n"
638 " (java.lang.String) ref);\n"
639 " if ($has_oneof_case_message$) {\n"
640 " $oneof_name$_ = b;\n"
641 " }\n"
642 " return b;\n"
643 " } else {\n"
644 " return (com.google.protobuf.ByteString) ref;\n"
645 " }\n"
646 "}\n");
647 printer->Annotate("{", "}", descriptor_);
648
649 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
650 /* builder */ true);
651 printer->Print(variables_,
652 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
653 " java.lang.String value) {\n"
654 " $null_check$\n"
655 " $set_oneof_case_message$;\n"
656 " $oneof_name$_ = value;\n"
657 " $on_changed$\n"
658 " return this;\n"
659 "}\n");
660 printer->Annotate("{", "}", descriptor_);
661 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
662 /* builder */ true);
663 printer->Print(
664 variables_,
665 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
666 " if ($has_oneof_case_message$) {\n"
667 " $clear_oneof_case_message$;\n"
668 " $oneof_name$_ = null;\n"
669 " $on_changed$\n"
670 " }\n"
671 " return this;\n"
672 "}\n");
673 printer->Annotate("{", "}", descriptor_);
674
675 WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
676 /* builder */ true);
677 printer->Print(
678 variables_,
679 "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
680 " com.google.protobuf.ByteString value) {\n"
681 " $null_check$\n");
682 printer->Annotate("{", "}", descriptor_);
683 if (CheckUtf8(descriptor_)) {
684 printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
685 }
686 printer->Print(variables_,
687 " $set_oneof_case_message$;\n"
688 " $oneof_name$_ = value;\n"
689 " $on_changed$\n"
690 " return this;\n"
691 "}\n");
692 }
693
GenerateBuilderClearCode(io::Printer * printer) const694 void ImmutableStringOneofFieldGenerator::GenerateBuilderClearCode(
695 io::Printer* printer) const {
696 // No-Op: String fields in oneofs are correctly cleared by clearing the oneof
697 }
698
GenerateMergingCode(io::Printer * printer) const699 void ImmutableStringOneofFieldGenerator::GenerateMergingCode(
700 io::Printer* printer) const {
701 // Allow a slight breach of abstraction here in order to avoid forcing
702 // all string fields to Strings when copying fields from a Message.
703 printer->Print(variables_,
704 "$set_oneof_case_message$;\n"
705 "$oneof_name$_ = other.$oneof_name$_;\n"
706 "$on_changed$\n");
707 }
708
GenerateBuildingCode(io::Printer * printer) const709 void ImmutableStringOneofFieldGenerator::GenerateBuildingCode(
710 io::Printer* printer) const {
711 // No-Op: oneof fields are built by a single statement
712 }
713
GenerateBuilderParsingCode(io::Printer * printer) const714 void ImmutableStringOneofFieldGenerator::GenerateBuilderParsingCode(
715 io::Printer* printer) const {
716 if (CheckUtf8(descriptor_)) {
717 printer->Print(variables_,
718 "java.lang.String s = input.readStringRequireUtf8();\n"
719 "$set_oneof_case_message$;\n"
720 "$oneof_name$_ = s;\n");
721 } else {
722 printer->Print(variables_,
723 "com.google.protobuf.ByteString bs = input.readBytes();\n"
724 "$set_oneof_case_message$;\n"
725 "$oneof_name$_ = bs;\n");
726 }
727 }
728
GenerateSerializationCode(io::Printer * printer) const729 void ImmutableStringOneofFieldGenerator::GenerateSerializationCode(
730 io::Printer* printer) const {
731 printer->Print(variables_,
732 "if ($has_oneof_case_message$) {\n"
733 " $writeString$(output, $number$, $oneof_name$_);\n"
734 "}\n");
735 }
736
GenerateSerializedSizeCode(io::Printer * printer) const737 void ImmutableStringOneofFieldGenerator::GenerateSerializedSizeCode(
738 io::Printer* printer) const {
739 printer->Print(variables_,
740 "if ($has_oneof_case_message$) {\n"
741 " size += $computeStringSize$($number$, $oneof_name$_);\n"
742 "}\n");
743 }
744
745 // ===================================================================
746
RepeatedImmutableStringFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)747 RepeatedImmutableStringFieldGenerator::RepeatedImmutableStringFieldGenerator(
748 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
749 Context* context)
750 : ImmutableStringFieldGenerator(descriptor, messageBitIndex,
751 builderBitIndex, context) {}
752
753 RepeatedImmutableStringFieldGenerator::
~RepeatedImmutableStringFieldGenerator()754 ~RepeatedImmutableStringFieldGenerator() {}
755
GetNumBitsForMessage() const756 int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const {
757 return 0;
758 }
759
GetNumBitsForBuilder() const760 int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
761 return 1;
762 }
763
GenerateInterfaceMembers(io::Printer * printer) const764 void RepeatedImmutableStringFieldGenerator::GenerateInterfaceMembers(
765 io::Printer* printer) const {
766 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
767 printer->Print(
768 variables_,
769 // NOTE: the same method in the implementation class actually returns
770 // com.google.protobuf.ProtocolStringList (a subclass of List). It's
771 // changed between protobuf 2.5.0 release and protobuf 2.6.1 release.
772 // To retain binary compatibility with both 2.5.0 and 2.6.1 generated
773 // code, we make this interface method return List so both methods
774 // with different return types exist in the compiled byte code.
775 "$deprecation$java.util.List<java.lang.String>\n"
776 " get$capitalized_name$List();\n");
777 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
778 printer->Print(variables_,
779 "$deprecation$int get$capitalized_name$Count();\n");
780 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
781 printer->Print(
782 variables_,
783 "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
784 WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
785 LIST_INDEXED_GETTER);
786 printer->Print(variables_,
787 "$deprecation$com.google.protobuf.ByteString\n"
788 " get$capitalized_name$Bytes(int index);\n");
789 }
790
GenerateMembers(io::Printer * printer) const791 void RepeatedImmutableStringFieldGenerator::GenerateMembers(
792 io::Printer* printer) const {
793 printer->Print(variables_,
794 "@SuppressWarnings(\"serial\")\n"
795 "private com.google.protobuf.LazyStringList $name$_;\n");
796 PrintExtraFieldInfo(variables_, printer);
797 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
798 printer->Print(variables_,
799 "$deprecation$public com.google.protobuf.ProtocolStringList\n"
800 " ${$get$capitalized_name$List$}$() {\n"
801 " return $name$_;\n" // note: unmodifiable list
802 "}\n");
803 printer->Annotate("{", "}", descriptor_);
804 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
805 printer->Print(
806 variables_,
807 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
808 " return $name$_.size();\n"
809 "}\n");
810 printer->Annotate("{", "}", descriptor_);
811 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
812 printer->Print(variables_,
813 "$deprecation$public java.lang.String "
814 "${$get$capitalized_name$$}$(int index) {\n"
815 " return $name$_.get(index);\n"
816 "}\n");
817 printer->Annotate("{", "}", descriptor_);
818 WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
819 LIST_INDEXED_GETTER);
820 printer->Print(variables_,
821 "$deprecation$public com.google.protobuf.ByteString\n"
822 " ${$get$capitalized_name$Bytes$}$(int index) {\n"
823 " return $name$_.getByteString(index);\n"
824 "}\n");
825 printer->Annotate("{", "}", descriptor_);
826 }
827
GenerateBuilderMembers(io::Printer * printer) const828 void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
829 io::Printer* printer) const {
830 // One field is the list and the bit field keeps track of whether the
831 // list is immutable. If it's immutable, the invariant is that it must
832 // either an instance of Collections.emptyList() or it's an ArrayList
833 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
834 // a reference to the underlying ArrayList. This invariant allows us to
835 // share instances of lists between protocol buffers avoiding expensive
836 // memory allocations. Note, immutable is a strong guarantee here -- not
837 // just that the list cannot be modified via the reference but that the
838 // list can never be modified.
839 printer->Print(
840 variables_,
841 "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
842
843 printer->Print(
844 variables_,
845 "private void ensure$capitalized_name$IsMutable() {\n"
846 " if (!$get_mutable_bit_builder$) {\n"
847 " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
848 " $set_mutable_bit_builder$;\n"
849 " }\n"
850 "}\n");
851
852 // Note: We return an unmodifiable list because otherwise the caller
853 // could hold on to the returned list and modify it after the message
854 // has been built, thus mutating the message which is supposed to be
855 // immutable.
856 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
857 printer->Print(variables_,
858 "$deprecation$public com.google.protobuf.ProtocolStringList\n"
859 " ${$get$capitalized_name$List$}$() {\n"
860 " return $name$_.getUnmodifiableView();\n"
861 "}\n");
862 printer->Annotate("{", "}", descriptor_);
863 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
864 printer->Print(
865 variables_,
866 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
867 " return $name$_.size();\n"
868 "}\n");
869 printer->Annotate("{", "}", descriptor_);
870 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
871 printer->Print(variables_,
872 "$deprecation$public java.lang.String "
873 "${$get$capitalized_name$$}$(int index) {\n"
874 " return $name$_.get(index);\n"
875 "}\n");
876 printer->Annotate("{", "}", descriptor_);
877 WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
878 LIST_INDEXED_GETTER);
879 printer->Print(variables_,
880 "$deprecation$public com.google.protobuf.ByteString\n"
881 " ${$get$capitalized_name$Bytes$}$(int index) {\n"
882 " return $name$_.getByteString(index);\n"
883 "}\n");
884 printer->Annotate("{", "}", descriptor_);
885 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
886 /* builder */ true);
887 printer->Print(variables_,
888 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
889 " int index, java.lang.String value) {\n"
890 " $null_check$\n"
891 " ensure$capitalized_name$IsMutable();\n"
892 " $name$_.set(index, value);\n"
893 " $on_changed$\n"
894 " return this;\n"
895 "}\n");
896 printer->Annotate("{", "}", descriptor_);
897 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
898 /* builder */ true);
899 printer->Print(variables_,
900 "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
901 " java.lang.String value) {\n"
902 " $null_check$\n"
903 " ensure$capitalized_name$IsMutable();\n"
904 " $name$_.add(value);\n"
905 " $on_changed$\n"
906 " return this;\n"
907 "}\n");
908 printer->Annotate("{", "}", descriptor_);
909 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
910 /* builder */ true);
911 printer->Print(variables_,
912 "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
913 " java.lang.Iterable<java.lang.String> values) {\n"
914 " ensure$capitalized_name$IsMutable();\n"
915 " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
916 " values, $name$_);\n"
917 " $on_changed$\n"
918 " return this;\n"
919 "}\n");
920 printer->Annotate("{", "}", descriptor_);
921 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
922 /* builder */ true);
923 printer->Print(
924 variables_,
925 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
926 " $name$_ = $empty_list$;\n"
927 " $clear_mutable_bit_builder$;\n"
928 " $on_changed$\n"
929 " return this;\n"
930 "}\n");
931 printer->Annotate("{", "}", descriptor_);
932
933 WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER,
934 /* builder */ true);
935 printer->Print(
936 variables_,
937 "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
938 " com.google.protobuf.ByteString value) {\n"
939 " $null_check$\n");
940 printer->Annotate("{", "}", descriptor_);
941 if (CheckUtf8(descriptor_)) {
942 printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
943 }
944 printer->Print(variables_,
945 " ensure$capitalized_name$IsMutable();\n"
946 " $name$_.add(value);\n"
947 " $on_changed$\n"
948 " return this;\n"
949 "}\n");
950 }
951
GenerateKotlinDslMembers(io::Printer * printer) const952 void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers(
953 io::Printer* printer) const {
954 printer->Print(
955 variables_,
956 "/**\n"
957 " * An uninstantiable, behaviorless type to represent the field in\n"
958 " * generics.\n"
959 " */\n"
960 "@kotlin.OptIn"
961 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
962 "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
963 " : com.google.protobuf.kotlin.DslProxy()\n");
964
965 // property for List<String>
966 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
967 printer->Print(variables_,
968 "$kt_deprecation$public val $kt_name$: "
969 "com.google.protobuf.kotlin.DslList"
970 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n"
971 " @kotlin.jvm.JvmSynthetic\n"
972 " get() = com.google.protobuf.kotlin.DslList(\n"
973 " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
974 " )\n");
975
976 // List<String>.add(String)
977 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
978 /* builder */ false);
979 printer->Print(variables_,
980 "@kotlin.jvm.JvmSynthetic\n"
981 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
982 "public fun com.google.protobuf.kotlin.DslList"
983 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
984 "add(value: kotlin.String) {\n"
985 " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
986 "}\n");
987
988 // List<String> += String
989 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
990 /* builder */ false);
991 printer->Print(variables_,
992 "@kotlin.jvm.JvmSynthetic\n"
993 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
994 "@Suppress(\"NOTHING_TO_INLINE\")\n"
995 "public inline operator fun com.google.protobuf.kotlin.DslList"
996 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
997 "plusAssign(value: kotlin.String) {\n"
998 " add(value)\n"
999 "}\n");
1000
1001 // List<String>.addAll(Iterable<String>)
1002 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
1003 /* builder */ false);
1004 printer->Print(
1005 variables_,
1006 "@kotlin.jvm.JvmSynthetic\n"
1007 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
1008 "public fun com.google.protobuf.kotlin.DslList"
1009 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
1010 "addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n"
1011 " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
1012 "}\n");
1013
1014 // List<String> += Iterable<String>
1015 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
1016 /* builder */ false);
1017 printer->Print(
1018 variables_,
1019 "@kotlin.jvm.JvmSynthetic\n"
1020 "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
1021 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1022 "public inline operator fun com.google.protobuf.kotlin.DslList"
1023 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
1024 "plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n"
1025 " addAll(values)\n"
1026 "}\n");
1027
1028 // List<String>[Int] = String
1029 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
1030 /* builder */ false);
1031 printer->Print(
1032 variables_,
1033 "@kotlin.jvm.JvmSynthetic\n"
1034 "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
1035 "public operator fun com.google.protobuf.kotlin.DslList"
1036 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
1037 "set(index: kotlin.Int, value: kotlin.String) {\n"
1038 " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
1039 "}");
1040
1041 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
1042 /* builder */ false);
1043 printer->Print(variables_,
1044 "@kotlin.jvm.JvmSynthetic\n"
1045 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
1046 "public fun com.google.protobuf.kotlin.DslList"
1047 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
1048 "clear() {\n"
1049 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
1050 "}");
1051 }
1052
1053 void RepeatedImmutableStringFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const1054 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
1055 // noop for primitives
1056 }
1057
GenerateInitializationCode(io::Printer * printer) const1058 void RepeatedImmutableStringFieldGenerator::GenerateInitializationCode(
1059 io::Printer* printer) const {
1060 printer->Print(variables_, "$name$_ = $empty_list$;\n");
1061 }
1062
GenerateBuilderClearCode(io::Printer * printer) const1063 void RepeatedImmutableStringFieldGenerator::GenerateBuilderClearCode(
1064 io::Printer* printer) const {
1065 printer->Print(variables_,
1066 "$name$_ = $empty_list$;\n"
1067 "$clear_mutable_bit_builder$;\n");
1068 }
1069
GenerateMergingCode(io::Printer * printer) const1070 void RepeatedImmutableStringFieldGenerator::GenerateMergingCode(
1071 io::Printer* printer) const {
1072 // The code below does two optimizations:
1073 // 1. If the other list is empty, there's nothing to do. This ensures we
1074 // don't allocate a new array if we already have an immutable one.
1075 // 2. If the other list is non-empty and our current list is empty, we can
1076 // reuse the other list which is guaranteed to be immutable.
1077 printer->Print(variables_,
1078 "if (!other.$name$_.isEmpty()) {\n"
1079 " if ($name$_.isEmpty()) {\n"
1080 " $name$_ = other.$name$_;\n"
1081 " $clear_mutable_bit_builder$;\n"
1082 " } else {\n"
1083 " ensure$capitalized_name$IsMutable();\n"
1084 " $name$_.addAll(other.$name$_);\n"
1085 " }\n"
1086 " $on_changed$\n"
1087 "}\n");
1088 }
1089
GenerateBuildingCode(io::Printer * printer) const1090 void RepeatedImmutableStringFieldGenerator::GenerateBuildingCode(
1091 io::Printer* printer) const {
1092 // The code below ensures that the result has an immutable list. If our
1093 // list is immutable, we can just reuse it. If not, we make it immutable.
1094
1095 printer->Print(variables_,
1096 "if ($get_mutable_bit_builder$) {\n"
1097 " $name$_ = $name$_.getUnmodifiableView();\n"
1098 " $clear_mutable_bit_builder$;\n"
1099 "}\n"
1100 "result.$name$_ = $name$_;\n");
1101 }
1102
GenerateBuilderParsingCode(io::Printer * printer) const1103 void RepeatedImmutableStringFieldGenerator::GenerateBuilderParsingCode(
1104 io::Printer* printer) const {
1105 if (CheckUtf8(descriptor_)) {
1106 printer->Print(variables_,
1107 "java.lang.String s = input.readStringRequireUtf8();\n"
1108 "ensure$capitalized_name$IsMutable();\n"
1109 "$name$_.add(s);\n");
1110 } else {
1111 printer->Print(variables_,
1112 "com.google.protobuf.ByteString bs = input.readBytes();\n"
1113 "ensure$capitalized_name$IsMutable();\n"
1114 "$name$_.add(bs);\n");
1115 }
1116 }
1117
GenerateSerializationCode(io::Printer * printer) const1118 void RepeatedImmutableStringFieldGenerator::GenerateSerializationCode(
1119 io::Printer* printer) const {
1120 printer->Print(variables_,
1121 "for (int i = 0; i < $name$_.size(); i++) {\n"
1122 " $writeString$(output, $number$, $name$_.getRaw(i));\n"
1123 "}\n");
1124 }
1125
GenerateSerializedSizeCode(io::Printer * printer) const1126 void RepeatedImmutableStringFieldGenerator::GenerateSerializedSizeCode(
1127 io::Printer* printer) const {
1128 printer->Print(variables_,
1129 "{\n"
1130 " int dataSize = 0;\n");
1131 printer->Indent();
1132
1133 printer->Print(variables_,
1134 "for (int i = 0; i < $name$_.size(); i++) {\n"
1135 " dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n"
1136 "}\n");
1137
1138 printer->Print("size += dataSize;\n");
1139
1140 printer->Print(variables_,
1141 "size += $tag_size$ * get$capitalized_name$List().size();\n");
1142
1143 printer->Outdent();
1144 printer->Print("}\n");
1145 }
1146
GenerateEqualsCode(io::Printer * printer) const1147 void RepeatedImmutableStringFieldGenerator::GenerateEqualsCode(
1148 io::Printer* printer) const {
1149 printer->Print(
1150 variables_,
1151 "if (!get$capitalized_name$List()\n"
1152 " .equals(other.get$capitalized_name$List())) return false;\n");
1153 }
1154
GenerateHashCode(io::Printer * printer) const1155 void RepeatedImmutableStringFieldGenerator::GenerateHashCode(
1156 io::Printer* printer) const {
1157 printer->Print(
1158 variables_,
1159 "if (get$capitalized_name$Count() > 0) {\n"
1160 " hash = (37 * hash) + $constant_name$;\n"
1161 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
1162 "}\n");
1163 }
1164
GetBoxedType() const1165 std::string RepeatedImmutableStringFieldGenerator::GetBoxedType() const {
1166 return "String";
1167 }
1168
1169 } // namespace java
1170 } // namespace compiler
1171 } // namespace protobuf
1172 } // namespace google
1173