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