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.h>
46 #include <google/protobuf/io/printer.h>
47 #include <google/protobuf/wire_format.h>
48 #include <google/protobuf/stubs/strutil.h>
49
50
51 namespace google {
52 namespace protobuf {
53 namespace compiler {
54 namespace java {
55
56 using internal::WireFormat;
57 using internal::WireFormatLite;
58
59 namespace {
60
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables)61 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
62 int messageBitIndex, int builderBitIndex,
63 const FieldGeneratorInfo* info,
64 ClassNameResolver* name_resolver,
65 std::map<std::string, std::string>* variables) {
66 SetCommonFieldVariables(descriptor, info, variables);
67
68 (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
69
70 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
71 (*variables)["default_init"] =
72 "= " + ImmutableDefaultValue(descriptor, name_resolver);
73 (*variables)["capitalized_type"] = "String";
74 (*variables)["tag"] =
75 StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
76 (*variables)["tag_size"] = StrCat(
77 WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
78 (*variables)["null_check"] =
79 " if (value == null) {\n"
80 " throw new NullPointerException();\n"
81 " }\n";
82 (*variables)["writeString"] = "com.google.protobuf.GeneratedMessage" +
83 GeneratedCodeVersionSuffix() + ".writeString";
84 (*variables)["computeStringSize"] = "com.google.protobuf.GeneratedMessage" +
85 GeneratedCodeVersionSuffix() +
86 ".computeStringSize";
87
88 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
89 // by the proto compiler
90 (*variables)["deprecation"] =
91 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
92 (*variables)["on_changed"] = "onChanged();";
93
94 if (SupportFieldPresence(descriptor->file())) {
95 // For singular messages and builders, one bit is used for the hasField bit.
96 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
97 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
98
99 // Note that these have a trailing ";".
100 (*variables)["set_has_field_bit_message"] =
101 GenerateSetBit(messageBitIndex) + ";";
102 (*variables)["set_has_field_bit_builder"] =
103 GenerateSetBit(builderBitIndex) + ";";
104 (*variables)["clear_has_field_bit_builder"] =
105 GenerateClearBit(builderBitIndex) + ";";
106
107 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
108 } else {
109 (*variables)["set_has_field_bit_message"] = "";
110 (*variables)["set_has_field_bit_builder"] = "";
111 (*variables)["clear_has_field_bit_builder"] = "";
112
113 (*variables)["is_field_present_message"] =
114 "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()";
115 }
116
117 // For repeated builders, one bit is used for whether the array is immutable.
118 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
119 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
120 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
121
122 // For repeated fields, one bit is used for whether the array is immutable
123 // in the parsing constructor.
124 (*variables)["get_mutable_bit_parser"] =
125 GenerateGetBitMutableLocal(builderBitIndex);
126 (*variables)["set_mutable_bit_parser"] =
127 GenerateSetBitMutableLocal(builderBitIndex);
128
129 (*variables)["get_has_field_bit_from_local"] =
130 GenerateGetBitFromLocal(builderBitIndex);
131 (*variables)["set_has_field_bit_to_local"] =
132 GenerateSetBitToLocal(messageBitIndex);
133 }
134
135 } // namespace
136
137 // ===================================================================
138
ImmutableStringFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)139 ImmutableStringFieldGenerator::ImmutableStringFieldGenerator(
140 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
141 Context* context)
142 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
143 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
144 context->GetFieldGeneratorInfo(descriptor),
145 name_resolver_, &variables_);
146 }
147
~ImmutableStringFieldGenerator()148 ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
149
GetNumBitsForMessage() const150 int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
151 return SupportFieldPresence(descriptor_->file()) ? 1 : 0;
152 }
153
GetNumBitsForBuilder() const154 int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
155 return GetNumBitsForMessage();
156 }
157
158 // A note about how strings are handled. This code used to just store a String
159 // in the Message. This had two issues:
160 //
161 // 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
162 // strings, but rather fields that were raw bytes incorrectly marked
163 // as strings in the proto file. This is common because in the proto1
164 // syntax, string was the way to indicate bytes and C++ engineers can
165 // easily make this mistake without affecting the C++ API. By converting to
166 // strings immediately, some java code might corrupt these byte arrays as
167 // it passes through a java server even if the field was never accessed by
168 // application code.
169 //
170 // 2. There's a performance hit to converting between bytes and strings and
171 // it many cases, the field is never even read by the application code. This
172 // avoids unnecessary conversions in the common use cases.
173 //
174 // So now, the field for String is maintained as an Object reference which can
175 // either store a String or a ByteString. The code uses an instanceof check
176 // to see which one it has and converts to the other one if needed. It remembers
177 // the last value requested (in a thread safe manner) as this is most likely
178 // the one needed next. The thread safety is such that if two threads both
179 // convert the field because the changes made by each thread were not visible to
180 // the other, they may cause a conversion to happen more times than would
181 // otherwise be necessary. This was deemed better than adding synchronization
182 // overhead. It will not cause any corruption issues or affect the behavior of
183 // the API. The instanceof check is also highly optimized in the JVM and we
184 // decided it was better to reduce the memory overhead by not having two
185 // separate fields but rather use dynamic type checking.
186 //
187 // For single fields, the logic for this is done inside the generated code. For
188 // repeated fields, the logic is done in LazyStringArrayList and
189 // UnmodifiableLazyStringList.
GenerateInterfaceMembers(io::Printer * printer) const190 void ImmutableStringFieldGenerator::GenerateInterfaceMembers(
191 io::Printer* printer) const {
192 if (SupportFieldPresence(descriptor_->file())) {
193 WriteFieldDocComment(printer, descriptor_);
194 printer->Print(variables_,
195 "$deprecation$boolean has$capitalized_name$();\n");
196 }
197 WriteFieldDocComment(printer, descriptor_);
198 printer->Print(variables_,
199 "$deprecation$java.lang.String get$capitalized_name$();\n");
200 WriteFieldDocComment(printer, descriptor_);
201 printer->Print(variables_,
202 "$deprecation$com.google.protobuf.ByteString\n"
203 " get$capitalized_name$Bytes();\n");
204 }
205
GenerateMembers(io::Printer * printer) const206 void ImmutableStringFieldGenerator::GenerateMembers(
207 io::Printer* printer) const {
208 printer->Print(variables_, "private volatile java.lang.Object $name$_;\n");
209 PrintExtraFieldInfo(variables_, printer);
210
211 if (SupportFieldPresence(descriptor_->file())) {
212 WriteFieldDocComment(printer, descriptor_);
213 printer->Print(
214 variables_,
215 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
216 " return $get_has_field_bit_message$;\n"
217 "}\n");
218 printer->Annotate("{", "}", descriptor_);
219 }
220
221 WriteFieldDocComment(printer, descriptor_);
222 printer->Print(
223 variables_,
224 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
225 " java.lang.Object ref = $name$_;\n"
226 " if (ref instanceof java.lang.String) {\n"
227 " return (java.lang.String) ref;\n"
228 " } else {\n"
229 " com.google.protobuf.ByteString bs = \n"
230 " (com.google.protobuf.ByteString) ref;\n"
231 " java.lang.String s = bs.toStringUtf8();\n");
232 printer->Annotate("{", "}", descriptor_);
233 if (CheckUtf8(descriptor_)) {
234 printer->Print(variables_, " $name$_ = s;\n");
235 } else {
236 printer->Print(variables_,
237 " if (bs.isValidUtf8()) {\n"
238 " $name$_ = s;\n"
239 " }\n");
240 }
241 printer->Print(variables_,
242 " return s;\n"
243 " }\n"
244 "}\n");
245 WriteFieldDocComment(printer, descriptor_);
246 printer->Print(variables_,
247 "$deprecation$public com.google.protobuf.ByteString\n"
248 " ${$get$capitalized_name$Bytes$}$() {\n"
249 " java.lang.Object ref = $name$_;\n"
250 " if (ref instanceof java.lang.String) {\n"
251 " com.google.protobuf.ByteString b = \n"
252 " com.google.protobuf.ByteString.copyFromUtf8(\n"
253 " (java.lang.String) ref);\n"
254 " $name$_ = b;\n"
255 " return b;\n"
256 " } else {\n"
257 " return (com.google.protobuf.ByteString) ref;\n"
258 " }\n"
259 "}\n");
260 printer->Annotate("{", "}", descriptor_);
261 }
262
GenerateBuilderMembers(io::Printer * printer) const263 void ImmutableStringFieldGenerator::GenerateBuilderMembers(
264 io::Printer* printer) const {
265 printer->Print(variables_,
266 "private java.lang.Object $name$_ $default_init$;\n");
267 if (SupportFieldPresence(descriptor_->file())) {
268 WriteFieldDocComment(printer, descriptor_);
269 printer->Print(
270 variables_,
271 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
272 " return $get_has_field_bit_builder$;\n"
273 "}\n");
274 printer->Annotate("{", "}", descriptor_);
275 }
276
277 WriteFieldDocComment(printer, descriptor_);
278 printer->Print(
279 variables_,
280 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
281 " java.lang.Object ref = $name$_;\n"
282 " if (!(ref instanceof java.lang.String)) {\n"
283 " com.google.protobuf.ByteString bs =\n"
284 " (com.google.protobuf.ByteString) ref;\n"
285 " java.lang.String s = bs.toStringUtf8();\n");
286 printer->Annotate("{", "}", descriptor_);
287 if (CheckUtf8(descriptor_)) {
288 printer->Print(variables_, " $name$_ = s;\n");
289 } else {
290 printer->Print(variables_,
291 " if (bs.isValidUtf8()) {\n"
292 " $name$_ = s;\n"
293 " }\n");
294 }
295 printer->Print(variables_,
296 " return s;\n"
297 " } else {\n"
298 " return (java.lang.String) ref;\n"
299 " }\n"
300 "}\n");
301
302 WriteFieldDocComment(printer, descriptor_);
303 printer->Print(variables_,
304 "$deprecation$public com.google.protobuf.ByteString\n"
305 " ${$get$capitalized_name$Bytes$}$() {\n"
306 " java.lang.Object ref = $name$_;\n"
307 " if (ref instanceof String) {\n"
308 " com.google.protobuf.ByteString b = \n"
309 " com.google.protobuf.ByteString.copyFromUtf8(\n"
310 " (java.lang.String) ref);\n"
311 " $name$_ = b;\n"
312 " return b;\n"
313 " } else {\n"
314 " return (com.google.protobuf.ByteString) ref;\n"
315 " }\n"
316 "}\n");
317 printer->Annotate("{", "}", descriptor_);
318
319 WriteFieldDocComment(printer, descriptor_);
320 printer->Print(variables_,
321 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
322 " java.lang.String value) {\n"
323 "$null_check$"
324 " $set_has_field_bit_builder$\n"
325 " $name$_ = value;\n"
326 " $on_changed$\n"
327 " return this;\n"
328 "}\n");
329 printer->Annotate("{", "}", descriptor_);
330 WriteFieldDocComment(printer, descriptor_);
331 printer->Print(
332 variables_,
333 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
334 " $clear_has_field_bit_builder$\n");
335 printer->Annotate("{", "}", descriptor_);
336 // The default value is not a simple literal so we want to avoid executing
337 // it multiple times. Instead, get the default out of the default instance.
338 printer->Print(variables_,
339 " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
340 printer->Print(variables_,
341 " $on_changed$\n"
342 " return this;\n"
343 "}\n");
344
345 WriteFieldDocComment(printer, descriptor_);
346 printer->Print(
347 variables_,
348 "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
349 " com.google.protobuf.ByteString value) {\n"
350 "$null_check$");
351 printer->Annotate("{", "}", descriptor_);
352 if (CheckUtf8(descriptor_)) {
353 printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
354 }
355 printer->Print(variables_,
356 " $set_has_field_bit_builder$\n"
357 " $name$_ = value;\n"
358 " $on_changed$\n"
359 " return this;\n"
360 "}\n");
361 }
362
GenerateFieldBuilderInitializationCode(io::Printer * printer) const363 void ImmutableStringFieldGenerator::GenerateFieldBuilderInitializationCode(
364 io::Printer* printer) const {
365 // noop for primitives
366 }
367
GenerateInitializationCode(io::Printer * printer) const368 void ImmutableStringFieldGenerator::GenerateInitializationCode(
369 io::Printer* printer) const {
370 printer->Print(variables_, "$name$_ = $default$;\n");
371 }
372
GenerateBuilderClearCode(io::Printer * printer) const373 void ImmutableStringFieldGenerator::GenerateBuilderClearCode(
374 io::Printer* printer) const {
375 printer->Print(variables_,
376 "$name$_ = $default$;\n"
377 "$clear_has_field_bit_builder$\n");
378 }
379
GenerateMergingCode(io::Printer * printer) const380 void ImmutableStringFieldGenerator::GenerateMergingCode(
381 io::Printer* printer) const {
382 if (SupportFieldPresence(descriptor_->file())) {
383 // Allow a slight breach of abstraction here in order to avoid forcing
384 // all string fields to Strings when copying fields from a Message.
385 printer->Print(variables_,
386 "if (other.has$capitalized_name$()) {\n"
387 " $set_has_field_bit_builder$\n"
388 " $name$_ = other.$name$_;\n"
389 " $on_changed$\n"
390 "}\n");
391 } else {
392 printer->Print(variables_,
393 "if (!other.get$capitalized_name$().isEmpty()) {\n"
394 " $name$_ = other.$name$_;\n"
395 " $on_changed$\n"
396 "}\n");
397 }
398 }
399
GenerateBuildingCode(io::Printer * printer) const400 void ImmutableStringFieldGenerator::GenerateBuildingCode(
401 io::Printer* printer) const {
402 if (SupportFieldPresence(descriptor_->file())) {
403 printer->Print(variables_,
404 "if ($get_has_field_bit_from_local$) {\n"
405 " $set_has_field_bit_to_local$;\n"
406 "}\n");
407 }
408 printer->Print(variables_, "result.$name$_ = $name$_;\n");
409 }
410
GenerateParsingCode(io::Printer * printer) const411 void ImmutableStringFieldGenerator::GenerateParsingCode(
412 io::Printer* printer) const {
413 if (CheckUtf8(descriptor_)) {
414 printer->Print(variables_,
415 "java.lang.String s = input.readStringRequireUtf8();\n"
416 "$set_has_field_bit_message$\n"
417 "$name$_ = s;\n");
418 } else {
419 printer->Print(variables_,
420 "com.google.protobuf.ByteString bs = input.readBytes();\n"
421 "$set_has_field_bit_message$\n"
422 "$name$_ = bs;\n");
423 }
424 }
425
GenerateParsingDoneCode(io::Printer * printer) const426 void ImmutableStringFieldGenerator::GenerateParsingDoneCode(
427 io::Printer* printer) const {
428 // noop for strings.
429 }
430
GenerateSerializationCode(io::Printer * printer) const431 void ImmutableStringFieldGenerator::GenerateSerializationCode(
432 io::Printer* printer) const {
433 printer->Print(variables_,
434 "if ($is_field_present_message$) {\n"
435 " $writeString$(output, $number$, $name$_);\n"
436 "}\n");
437 }
438
GenerateSerializedSizeCode(io::Printer * printer) const439 void ImmutableStringFieldGenerator::GenerateSerializedSizeCode(
440 io::Printer* printer) const {
441 printer->Print(variables_,
442 "if ($is_field_present_message$) {\n"
443 " size += $computeStringSize$($number$, $name$_);\n"
444 "}\n");
445 }
446
GenerateEqualsCode(io::Printer * printer) const447 void ImmutableStringFieldGenerator::GenerateEqualsCode(
448 io::Printer* printer) const {
449 printer->Print(variables_,
450 "if (!get$capitalized_name$()\n"
451 " .equals(other.get$capitalized_name$())) return false;\n");
452 }
453
GenerateHashCode(io::Printer * printer) const454 void ImmutableStringFieldGenerator::GenerateHashCode(
455 io::Printer* printer) const {
456 printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
457 printer->Print(variables_,
458 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
459 }
460
GetBoxedType() const461 std::string ImmutableStringFieldGenerator::GetBoxedType() const {
462 return "java.lang.String";
463 }
464
465 // ===================================================================
466
ImmutableStringOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)467 ImmutableStringOneofFieldGenerator::ImmutableStringOneofFieldGenerator(
468 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
469 Context* context)
470 : ImmutableStringFieldGenerator(descriptor, messageBitIndex,
471 builderBitIndex, context) {
472 const OneofGeneratorInfo* info =
473 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
474 SetCommonOneofVariables(descriptor, info, &variables_);
475 }
476
~ImmutableStringOneofFieldGenerator()477 ImmutableStringOneofFieldGenerator::~ImmutableStringOneofFieldGenerator() {}
478
GenerateMembers(io::Printer * printer) const479 void ImmutableStringOneofFieldGenerator::GenerateMembers(
480 io::Printer* printer) const {
481 PrintExtraFieldInfo(variables_, printer);
482
483 if (SupportFieldPresence(descriptor_->file())) {
484 WriteFieldDocComment(printer, descriptor_);
485 printer->Print(
486 variables_,
487 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
488 " return $has_oneof_case_message$;\n"
489 "}\n");
490 printer->Annotate("{", "}", descriptor_);
491 }
492
493 WriteFieldDocComment(printer, descriptor_);
494 printer->Print(
495 variables_,
496 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
497 " java.lang.Object ref $default_init$;\n"
498 " if ($has_oneof_case_message$) {\n"
499 " ref = $oneof_name$_;\n"
500 " }\n"
501 " if (ref instanceof java.lang.String) {\n"
502 " return (java.lang.String) ref;\n"
503 " } else {\n"
504 " com.google.protobuf.ByteString bs = \n"
505 " (com.google.protobuf.ByteString) ref;\n"
506 " java.lang.String s = bs.toStringUtf8();\n");
507 printer->Annotate("{", "}", descriptor_);
508 if (CheckUtf8(descriptor_)) {
509 printer->Print(variables_,
510 " if ($has_oneof_case_message$) {\n"
511 " $oneof_name$_ = s;\n"
512 " }\n");
513 } else {
514 printer->Print(variables_,
515 " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
516 " $oneof_name$_ = s;\n"
517 " }\n");
518 }
519 printer->Print(variables_,
520 " return s;\n"
521 " }\n"
522 "}\n");
523 WriteFieldDocComment(printer, descriptor_);
524
525 printer->Print(variables_,
526 "$deprecation$public com.google.protobuf.ByteString\n"
527 " ${$get$capitalized_name$Bytes$}$() {\n"
528 " java.lang.Object ref $default_init$;\n"
529 " if ($has_oneof_case_message$) {\n"
530 " ref = $oneof_name$_;\n"
531 " }\n"
532 " if (ref instanceof java.lang.String) {\n"
533 " com.google.protobuf.ByteString b = \n"
534 " com.google.protobuf.ByteString.copyFromUtf8(\n"
535 " (java.lang.String) ref);\n"
536 " if ($has_oneof_case_message$) {\n"
537 " $oneof_name$_ = b;\n"
538 " }\n"
539 " return b;\n"
540 " } else {\n"
541 " return (com.google.protobuf.ByteString) ref;\n"
542 " }\n"
543 "}\n");
544 printer->Annotate("{", "}", descriptor_);
545 }
546
GenerateBuilderMembers(io::Printer * printer) const547 void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
548 io::Printer* printer) const {
549 if (SupportFieldPresence(descriptor_->file())) {
550 WriteFieldDocComment(printer, descriptor_);
551 printer->Print(
552 variables_,
553 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
554 " return $has_oneof_case_message$;\n"
555 "}\n");
556 printer->Annotate("{", "}", descriptor_);
557 }
558
559 WriteFieldDocComment(printer, descriptor_);
560 printer->Print(
561 variables_,
562 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
563 " java.lang.Object ref $default_init$;\n"
564 " if ($has_oneof_case_message$) {\n"
565 " ref = $oneof_name$_;\n"
566 " }\n"
567 " if (!(ref instanceof java.lang.String)) {\n"
568 " com.google.protobuf.ByteString bs =\n"
569 " (com.google.protobuf.ByteString) ref;\n"
570 " java.lang.String s = bs.toStringUtf8();\n"
571 " if ($has_oneof_case_message$) {\n");
572 printer->Annotate("{", "}", descriptor_);
573 if (CheckUtf8(descriptor_)) {
574 printer->Print(variables_, " $oneof_name$_ = s;\n");
575 } else {
576 printer->Print(variables_,
577 " if (bs.isValidUtf8()) {\n"
578 " $oneof_name$_ = s;\n"
579 " }\n");
580 }
581 printer->Print(variables_,
582 " }\n"
583 " return s;\n"
584 " } else {\n"
585 " return (java.lang.String) ref;\n"
586 " }\n"
587 "}\n");
588
589 WriteFieldDocComment(printer, descriptor_);
590 printer->Print(variables_,
591 "$deprecation$public com.google.protobuf.ByteString\n"
592 " ${$get$capitalized_name$Bytes$}$() {\n"
593 " java.lang.Object ref $default_init$;\n"
594 " if ($has_oneof_case_message$) {\n"
595 " ref = $oneof_name$_;\n"
596 " }\n"
597 " if (ref instanceof String) {\n"
598 " com.google.protobuf.ByteString b = \n"
599 " com.google.protobuf.ByteString.copyFromUtf8(\n"
600 " (java.lang.String) ref);\n"
601 " if ($has_oneof_case_message$) {\n"
602 " $oneof_name$_ = b;\n"
603 " }\n"
604 " return b;\n"
605 " } else {\n"
606 " return (com.google.protobuf.ByteString) ref;\n"
607 " }\n"
608 "}\n");
609 printer->Annotate("{", "}", descriptor_);
610
611 WriteFieldDocComment(printer, descriptor_);
612 printer->Print(variables_,
613 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
614 " java.lang.String value) {\n"
615 "$null_check$"
616 " $set_oneof_case_message$;\n"
617 " $oneof_name$_ = value;\n"
618 " $on_changed$\n"
619 " return this;\n"
620 "}\n");
621 printer->Annotate("{", "}", descriptor_);
622 WriteFieldDocComment(printer, descriptor_);
623 printer->Print(
624 variables_,
625 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
626 " if ($has_oneof_case_message$) {\n"
627 " $clear_oneof_case_message$;\n"
628 " $oneof_name$_ = null;\n"
629 " $on_changed$\n"
630 " }\n"
631 " return this;\n"
632 "}\n");
633 printer->Annotate("{", "}", descriptor_);
634
635 WriteFieldDocComment(printer, descriptor_);
636 printer->Print(
637 variables_,
638 "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
639 " com.google.protobuf.ByteString value) {\n"
640 "$null_check$");
641 printer->Annotate("{", "}", descriptor_);
642 if (CheckUtf8(descriptor_)) {
643 printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
644 }
645 printer->Print(variables_,
646 " $set_oneof_case_message$;\n"
647 " $oneof_name$_ = value;\n"
648 " $on_changed$\n"
649 " return this;\n"
650 "}\n");
651 }
652
GenerateMergingCode(io::Printer * printer) const653 void ImmutableStringOneofFieldGenerator::GenerateMergingCode(
654 io::Printer* printer) const {
655 // Allow a slight breach of abstraction here in order to avoid forcing
656 // all string fields to Strings when copying fields from a Message.
657 printer->Print(variables_,
658 "$set_oneof_case_message$;\n"
659 "$oneof_name$_ = other.$oneof_name$_;\n"
660 "$on_changed$\n");
661 }
662
GenerateBuildingCode(io::Printer * printer) const663 void ImmutableStringOneofFieldGenerator::GenerateBuildingCode(
664 io::Printer* printer) const {
665 printer->Print(variables_,
666 "if ($has_oneof_case_message$) {\n"
667 " result.$oneof_name$_ = $oneof_name$_;\n"
668 "}\n");
669 }
670
GenerateParsingCode(io::Printer * printer) const671 void ImmutableStringOneofFieldGenerator::GenerateParsingCode(
672 io::Printer* printer) const {
673 if (CheckUtf8(descriptor_)) {
674 printer->Print(variables_,
675 "java.lang.String s = input.readStringRequireUtf8();\n"
676 "$set_oneof_case_message$;\n"
677 "$oneof_name$_ = s;\n");
678 } else {
679 printer->Print(variables_,
680 "com.google.protobuf.ByteString bs = input.readBytes();\n"
681 "$set_oneof_case_message$;\n"
682 "$oneof_name$_ = bs;\n");
683 }
684 }
685
GenerateSerializationCode(io::Printer * printer) const686 void ImmutableStringOneofFieldGenerator::GenerateSerializationCode(
687 io::Printer* printer) const {
688 printer->Print(variables_,
689 "if ($has_oneof_case_message$) {\n"
690 " $writeString$(output, $number$, $oneof_name$_);\n"
691 "}\n");
692 }
693
GenerateSerializedSizeCode(io::Printer * printer) const694 void ImmutableStringOneofFieldGenerator::GenerateSerializedSizeCode(
695 io::Printer* printer) const {
696 printer->Print(variables_,
697 "if ($has_oneof_case_message$) {\n"
698 " size += $computeStringSize$($number$, $oneof_name$_);\n"
699 "}\n");
700 }
701
702 // ===================================================================
703
RepeatedImmutableStringFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)704 RepeatedImmutableStringFieldGenerator::RepeatedImmutableStringFieldGenerator(
705 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
706 Context* context)
707 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
708 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
709 context->GetFieldGeneratorInfo(descriptor),
710 name_resolver_, &variables_);
711 }
712
713 RepeatedImmutableStringFieldGenerator::
~RepeatedImmutableStringFieldGenerator()714 ~RepeatedImmutableStringFieldGenerator() {}
715
GetNumBitsForMessage() const716 int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const {
717 return 0;
718 }
719
GetNumBitsForBuilder() const720 int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
721 return 1;
722 }
723
GenerateInterfaceMembers(io::Printer * printer) const724 void RepeatedImmutableStringFieldGenerator::GenerateInterfaceMembers(
725 io::Printer* printer) const {
726 WriteFieldDocComment(printer, descriptor_);
727 printer->Print(
728 variables_,
729 // NOTE: the same method in the implementation class actually returns
730 // com.google.protobuf.ProtocolStringList (a subclass of List). It's
731 // changed between protobuf 2.5.0 release and protobuf 2.6.1 release.
732 // To retain binary compatibility with both 2.5.0 and 2.6.1 generated
733 // code, we make this interface method return List so both methods
734 // with different return types exist in the compiled byte code.
735 "$deprecation$java.util.List<java.lang.String>\n"
736 " get$capitalized_name$List();\n");
737 WriteFieldDocComment(printer, descriptor_);
738 printer->Print(variables_,
739 "$deprecation$int get$capitalized_name$Count();\n");
740 WriteFieldDocComment(printer, descriptor_);
741 printer->Print(
742 variables_,
743 "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
744 WriteFieldDocComment(printer, descriptor_);
745 printer->Print(variables_,
746 "$deprecation$com.google.protobuf.ByteString\n"
747 " get$capitalized_name$Bytes(int index);\n");
748 }
749
GenerateMembers(io::Printer * printer) const750 void RepeatedImmutableStringFieldGenerator::GenerateMembers(
751 io::Printer* printer) const {
752 printer->Print(variables_,
753 "private com.google.protobuf.LazyStringList $name$_;\n");
754 PrintExtraFieldInfo(variables_, printer);
755 WriteFieldDocComment(printer, descriptor_);
756 printer->Print(variables_,
757 "$deprecation$public com.google.protobuf.ProtocolStringList\n"
758 " ${$get$capitalized_name$List$}$() {\n"
759 " return $name$_;\n" // note: unmodifiable list
760 "}\n");
761 printer->Annotate("{", "}", descriptor_);
762 WriteFieldDocComment(printer, descriptor_);
763 printer->Print(
764 variables_,
765 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
766 " return $name$_.size();\n"
767 "}\n");
768 printer->Annotate("{", "}", descriptor_);
769 WriteFieldDocComment(printer, descriptor_);
770 printer->Print(variables_,
771 "$deprecation$public java.lang.String "
772 "${$get$capitalized_name$$}$(int index) {\n"
773 " return $name$_.get(index);\n"
774 "}\n");
775 printer->Annotate("{", "}", descriptor_);
776 WriteFieldDocComment(printer, descriptor_);
777 printer->Print(variables_,
778 "$deprecation$public com.google.protobuf.ByteString\n"
779 " ${$get$capitalized_name$Bytes$}$(int index) {\n"
780 " return $name$_.getByteString(index);\n"
781 "}\n");
782 printer->Annotate("{", "}", descriptor_);
783 }
784
GenerateBuilderMembers(io::Printer * printer) const785 void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
786 io::Printer* printer) const {
787 // One field is the list and the bit field keeps track of whether the
788 // list is immutable. If it's immutable, the invariant is that it must
789 // either an instance of Collections.emptyList() or it's an ArrayList
790 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
791 // a refererence to the underlying ArrayList. This invariant allows us to
792 // share instances of lists between protocol buffers avoiding expensive
793 // memory allocations. Note, immutable is a strong guarantee here -- not
794 // just that the list cannot be modified via the reference but that the
795 // list can never be modified.
796 printer->Print(
797 variables_,
798 "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
799
800 printer->Print(
801 variables_,
802 "private void ensure$capitalized_name$IsMutable() {\n"
803 " if (!$get_mutable_bit_builder$) {\n"
804 " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
805 " $set_mutable_bit_builder$;\n"
806 " }\n"
807 "}\n");
808
809 // Note: We return an unmodifiable list because otherwise the caller
810 // could hold on to the returned list and modify it after the message
811 // has been built, thus mutating the message which is supposed to be
812 // immutable.
813 WriteFieldDocComment(printer, descriptor_);
814 printer->Print(variables_,
815 "$deprecation$public com.google.protobuf.ProtocolStringList\n"
816 " ${$get$capitalized_name$List$}$() {\n"
817 " return $name$_.getUnmodifiableView();\n"
818 "}\n");
819 printer->Annotate("{", "}", descriptor_);
820 WriteFieldDocComment(printer, descriptor_);
821 printer->Print(
822 variables_,
823 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
824 " return $name$_.size();\n"
825 "}\n");
826 printer->Annotate("{", "}", descriptor_);
827 WriteFieldDocComment(printer, descriptor_);
828 printer->Print(variables_,
829 "$deprecation$public java.lang.String "
830 "${$get$capitalized_name$$}$(int index) {\n"
831 " return $name$_.get(index);\n"
832 "}\n");
833 printer->Annotate("{", "}", descriptor_);
834 WriteFieldDocComment(printer, descriptor_);
835 printer->Print(variables_,
836 "$deprecation$public com.google.protobuf.ByteString\n"
837 " ${$get$capitalized_name$Bytes$}$(int index) {\n"
838 " return $name$_.getByteString(index);\n"
839 "}\n");
840 printer->Annotate("{", "}", descriptor_);
841 WriteFieldDocComment(printer, descriptor_);
842 printer->Print(variables_,
843 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
844 " int index, java.lang.String value) {\n"
845 "$null_check$"
846 " ensure$capitalized_name$IsMutable();\n"
847 " $name$_.set(index, value);\n"
848 " $on_changed$\n"
849 " return this;\n"
850 "}\n");
851 printer->Annotate("{", "}", descriptor_);
852 WriteFieldDocComment(printer, descriptor_);
853 printer->Print(variables_,
854 "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
855 " java.lang.String value) {\n"
856 "$null_check$"
857 " ensure$capitalized_name$IsMutable();\n"
858 " $name$_.add(value);\n"
859 " $on_changed$\n"
860 " return this;\n"
861 "}\n");
862 printer->Annotate("{", "}", descriptor_);
863 WriteFieldDocComment(printer, descriptor_);
864 printer->Print(variables_,
865 "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
866 " java.lang.Iterable<java.lang.String> values) {\n"
867 " ensure$capitalized_name$IsMutable();\n"
868 " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
869 " values, $name$_);\n"
870 " $on_changed$\n"
871 " return this;\n"
872 "}\n");
873 printer->Annotate("{", "}", descriptor_);
874 WriteFieldDocComment(printer, descriptor_);
875 printer->Print(
876 variables_,
877 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
878 " $name$_ = $empty_list$;\n"
879 " $clear_mutable_bit_builder$;\n"
880 " $on_changed$\n"
881 " return this;\n"
882 "}\n");
883 printer->Annotate("{", "}", descriptor_);
884
885 WriteFieldDocComment(printer, descriptor_);
886 printer->Print(
887 variables_,
888 "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
889 " com.google.protobuf.ByteString value) {\n"
890 "$null_check$");
891 printer->Annotate("{", "}", descriptor_);
892 if (CheckUtf8(descriptor_)) {
893 printer->Print(variables_, " checkByteStringIsUtf8(value);\n");
894 }
895 printer->Print(variables_,
896 " ensure$capitalized_name$IsMutable();\n"
897 " $name$_.add(value);\n"
898 " $on_changed$\n"
899 " return this;\n"
900 "}\n");
901 }
902
903 void RepeatedImmutableStringFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const904 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
905 // noop for primitives
906 }
907
GenerateInitializationCode(io::Printer * printer) const908 void RepeatedImmutableStringFieldGenerator::GenerateInitializationCode(
909 io::Printer* printer) const {
910 printer->Print(variables_, "$name$_ = $empty_list$;\n");
911 }
912
GenerateBuilderClearCode(io::Printer * printer) const913 void RepeatedImmutableStringFieldGenerator::GenerateBuilderClearCode(
914 io::Printer* printer) const {
915 printer->Print(variables_,
916 "$name$_ = $empty_list$;\n"
917 "$clear_mutable_bit_builder$;\n");
918 }
919
GenerateMergingCode(io::Printer * printer) const920 void RepeatedImmutableStringFieldGenerator::GenerateMergingCode(
921 io::Printer* printer) const {
922 // The code below does two optimizations:
923 // 1. If the other list is empty, there's nothing to do. This ensures we
924 // don't allocate a new array if we already have an immutable one.
925 // 2. If the other list is non-empty and our current list is empty, we can
926 // reuse the other list which is guaranteed to be immutable.
927 printer->Print(variables_,
928 "if (!other.$name$_.isEmpty()) {\n"
929 " if ($name$_.isEmpty()) {\n"
930 " $name$_ = other.$name$_;\n"
931 " $clear_mutable_bit_builder$;\n"
932 " } else {\n"
933 " ensure$capitalized_name$IsMutable();\n"
934 " $name$_.addAll(other.$name$_);\n"
935 " }\n"
936 " $on_changed$\n"
937 "}\n");
938 }
939
GenerateBuildingCode(io::Printer * printer) const940 void RepeatedImmutableStringFieldGenerator::GenerateBuildingCode(
941 io::Printer* printer) const {
942 // The code below ensures that the result has an immutable list. If our
943 // list is immutable, we can just reuse it. If not, we make it immutable.
944
945 printer->Print(variables_,
946 "if ($get_mutable_bit_builder$) {\n"
947 " $name$_ = $name$_.getUnmodifiableView();\n"
948 " $clear_mutable_bit_builder$;\n"
949 "}\n"
950 "result.$name$_ = $name$_;\n");
951 }
952
GenerateParsingCode(io::Printer * printer) const953 void RepeatedImmutableStringFieldGenerator::GenerateParsingCode(
954 io::Printer* printer) const {
955 if (CheckUtf8(descriptor_)) {
956 printer->Print(variables_,
957 "java.lang.String s = input.readStringRequireUtf8();\n");
958 } else {
959 printer->Print(variables_,
960 "com.google.protobuf.ByteString bs = input.readBytes();\n");
961 }
962 printer->Print(variables_,
963 "if (!$get_mutable_bit_parser$) {\n"
964 " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
965 " $set_mutable_bit_parser$;\n"
966 "}\n");
967 if (CheckUtf8(descriptor_)) {
968 printer->Print(variables_, "$name$_.add(s);\n");
969 } else {
970 printer->Print(variables_, "$name$_.add(bs);\n");
971 }
972 }
973
GenerateParsingDoneCode(io::Printer * printer) const974 void RepeatedImmutableStringFieldGenerator::GenerateParsingDoneCode(
975 io::Printer* printer) const {
976 printer->Print(variables_,
977 "if ($get_mutable_bit_parser$) {\n"
978 " $name$_ = $name$_.getUnmodifiableView();\n"
979 "}\n");
980 }
981
GenerateSerializationCode(io::Printer * printer) const982 void RepeatedImmutableStringFieldGenerator::GenerateSerializationCode(
983 io::Printer* printer) const {
984 printer->Print(variables_,
985 "for (int i = 0; i < $name$_.size(); i++) {\n"
986 " $writeString$(output, $number$, $name$_.getRaw(i));\n"
987 "}\n");
988 }
989
GenerateSerializedSizeCode(io::Printer * printer) const990 void RepeatedImmutableStringFieldGenerator::GenerateSerializedSizeCode(
991 io::Printer* printer) const {
992 printer->Print(variables_,
993 "{\n"
994 " int dataSize = 0;\n");
995 printer->Indent();
996
997 printer->Print(variables_,
998 "for (int i = 0; i < $name$_.size(); i++) {\n"
999 " dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n"
1000 "}\n");
1001
1002 printer->Print("size += dataSize;\n");
1003
1004 printer->Print(variables_,
1005 "size += $tag_size$ * get$capitalized_name$List().size();\n");
1006
1007 printer->Outdent();
1008 printer->Print("}\n");
1009 }
1010
GenerateEqualsCode(io::Printer * printer) const1011 void RepeatedImmutableStringFieldGenerator::GenerateEqualsCode(
1012 io::Printer* printer) const {
1013 printer->Print(
1014 variables_,
1015 "if (!get$capitalized_name$List()\n"
1016 " .equals(other.get$capitalized_name$List())) return false;\n");
1017 }
1018
GenerateHashCode(io::Printer * printer) const1019 void RepeatedImmutableStringFieldGenerator::GenerateHashCode(
1020 io::Printer* printer) const {
1021 printer->Print(
1022 variables_,
1023 "if (get$capitalized_name$Count() > 0) {\n"
1024 " hash = (37 * hash) + $constant_name$;\n"
1025 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
1026 "}\n");
1027 }
1028
GetBoxedType() const1029 std::string RepeatedImmutableStringFieldGenerator::GetBoxedType() const {
1030 return "String";
1031 }
1032
1033 } // namespace java
1034 } // namespace compiler
1035 } // namespace protobuf
1036 } // namespace google
1037