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_lite.h>
46 : #include <google/protobuf/io/printer.h>
47 : #include <google/protobuf/wire_format.h>
48 : #include <google/protobuf/stubs/strutil.h>
49 :
50 : namespace google {
51 : namespace protobuf {
52 : namespace compiler {
53 : namespace java {
54 :
55 : using internal::WireFormat;
56 : using internal::WireFormatLite;
57 :
58 : namespace {
59 :
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"] =
69 : "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
70 :
71 0 : (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
72 0 : (*variables)["default_init"] =
73 0 : "= " + ImmutableDefaultValue(descriptor, name_resolver);
74 0 : (*variables)["capitalized_type"] = "String";
75 0 : (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
76 0 : (*variables)["tag_size"] = SimpleItoa(
77 : WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
78 0 : (*variables)["null_check"] =
79 : " if (value == null) {\n"
80 : " throw new NullPointerException();\n"
81 : " }\n";
82 :
83 : // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
84 : // by the proto compiler
85 0 : (*variables)["deprecation"] = descriptor->options().deprecated()
86 : ? "@java.lang.Deprecated " : "";
87 0 : (*variables)["on_changed"] =
88 0 : HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
89 :
90 0 : if (SupportFieldPresence(descriptor->file())) {
91 : // For singular messages and builders, one bit is used for the hasField bit.
92 0 : (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
93 :
94 : // Note that these have a trailing ";".
95 0 : (*variables)["set_has_field_bit_message"] =
96 0 : GenerateSetBit(messageBitIndex) + ";";
97 0 : (*variables)["clear_has_field_bit_message"] =
98 0 : GenerateClearBit(messageBitIndex) + ";";
99 :
100 0 : (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
101 : } else {
102 0 : (*variables)["set_has_field_bit_message"] = "";
103 0 : (*variables)["clear_has_field_bit_message"] = "";
104 :
105 0 : (*variables)["is_field_present_message"] =
106 0 : "!get" + (*variables)["capitalized_name"] + ".isEmpty()";
107 : }
108 :
109 : // For repeated builders, the underlying list tracks mutability state.
110 0 : (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
111 :
112 0 : (*variables)["get_has_field_bit_from_local"] =
113 : GenerateGetBitFromLocal(builderBitIndex);
114 0 : (*variables)["set_has_field_bit_to_local"] =
115 : GenerateSetBitToLocal(messageBitIndex);
116 0 : }
117 :
118 : } // namespace
119 :
120 : // ===================================================================
121 :
122 0 : ImmutableStringFieldLiteGenerator::
123 : ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
124 : int messageBitIndex,
125 : int builderBitIndex,
126 : Context* context)
127 : : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
128 : builderBitIndex_(builderBitIndex), context_(context),
129 0 : name_resolver_(context->GetNameResolver()) {
130 : SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
131 : context->GetFieldGeneratorInfo(descriptor),
132 0 : name_resolver_, &variables_);
133 0 : }
134 :
135 0 : ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
136 :
137 0 : int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
138 0 : return 1;
139 : }
140 :
141 0 : int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
142 0 : return 0;
143 : }
144 :
145 : // A note about how strings are handled. In the SPEED and CODE_SIZE runtimes,
146 : // strings are not stored as java.lang.String in the Message because of two
147 : // issues:
148 : //
149 : // 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
150 : // strings, but rather fields that were raw bytes incorrectly marked
151 : // as strings in the proto file. This is common because in the proto1
152 : // syntax, string was the way to indicate bytes and C++ engineers can
153 : // easily make this mistake without affecting the C++ API. By converting to
154 : // strings immediately, some java code might corrupt these byte arrays as
155 : // it passes through a java server even if the field was never accessed by
156 : // application code.
157 : //
158 : // 2. There's a performance hit to converting between bytes and strings and
159 : // it many cases, the field is never even read by the application code. This
160 : // avoids unnecessary conversions in the common use cases.
161 : //
162 : // In the LITE_RUNTIME, we store strings as java.lang.String because we assume
163 : // that the users of this runtime are not subject to proto1 constraints and are
164 : // running code on devices that are user facing. That is, the developers are
165 : // properly incentivized to only fetch the data they need to read and wish to
166 : // reduce the number of allocations incurred when running on a user's device.
167 :
168 : // TODO(dweis): Consider dropping all of the *Bytes() methods. They really
169 : // shouldn't be necessary or used on devices.
170 0 : void ImmutableStringFieldLiteGenerator::
171 : GenerateInterfaceMembers(io::Printer* printer) const {
172 0 : if (SupportFieldPresence(descriptor_->file())) {
173 0 : WriteFieldDocComment(printer, descriptor_);
174 : printer->Print(variables_,
175 0 : "$deprecation$boolean has$capitalized_name$();\n");
176 : }
177 0 : WriteFieldDocComment(printer, descriptor_);
178 : printer->Print(variables_,
179 0 : "$deprecation$java.lang.String get$capitalized_name$();\n");
180 0 : WriteFieldDocComment(printer, descriptor_);
181 : printer->Print(variables_,
182 : "$deprecation$com.google.protobuf.ByteString\n"
183 0 : " get$capitalized_name$Bytes();\n");
184 0 : }
185 :
186 0 : void ImmutableStringFieldLiteGenerator::
187 : GenerateMembers(io::Printer* printer) const {
188 : printer->Print(variables_,
189 0 : "private java.lang.String $name$_;\n");
190 0 : PrintExtraFieldInfo(variables_, printer);
191 :
192 0 : if (SupportFieldPresence(descriptor_->file())) {
193 0 : WriteFieldDocComment(printer, descriptor_);
194 : printer->Print(variables_,
195 : "$deprecation$public boolean has$capitalized_name$() {\n"
196 : " return $get_has_field_bit_message$;\n"
197 0 : "}\n");
198 : }
199 :
200 0 : WriteFieldDocComment(printer, descriptor_);
201 : printer->Print(variables_,
202 : "$deprecation$public java.lang.String get$capitalized_name$() {\n"
203 : " return $name$_;\n"
204 0 : "}\n");
205 0 : WriteFieldDocComment(printer, descriptor_);
206 : printer->Print(variables_,
207 : "$deprecation$public com.google.protobuf.ByteString\n"
208 : " get$capitalized_name$Bytes() {\n"
209 : " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
210 0 : "}\n");
211 :
212 0 : WriteFieldDocComment(printer, descriptor_);
213 : printer->Print(variables_,
214 : "private void set$capitalized_name$(\n"
215 : " java.lang.String value) {\n"
216 : "$null_check$"
217 : " $set_has_field_bit_message$\n"
218 : " $name$_ = value;\n"
219 0 : "}\n");
220 0 : WriteFieldDocComment(printer, descriptor_);
221 : printer->Print(variables_,
222 : "private void clear$capitalized_name$() {\n"
223 : " $clear_has_field_bit_message$\n"
224 : // The default value is not a simple literal so we want to avoid executing
225 : // it multiple times. Instead, get the default out of the default instance.
226 : " $name$_ = getDefaultInstance().get$capitalized_name$();\n"
227 0 : "}\n");
228 :
229 0 : WriteFieldDocComment(printer, descriptor_);
230 : printer->Print(variables_,
231 : "private void set$capitalized_name$Bytes(\n"
232 : " com.google.protobuf.ByteString value) {\n"
233 0 : "$null_check$");
234 0 : if (CheckUtf8(descriptor_)) {
235 : printer->Print(variables_,
236 0 : " checkByteStringIsUtf8(value);\n");
237 : }
238 : printer->Print(variables_,
239 : " $set_has_field_bit_message$\n"
240 : " $name$_ = value.toStringUtf8();\n"
241 0 : "}\n");
242 0 : }
243 :
244 0 : void ImmutableStringFieldLiteGenerator::
245 : GenerateBuilderMembers(io::Printer* printer) const {
246 0 : if (SupportFieldPresence(descriptor_->file())) {
247 0 : WriteFieldDocComment(printer, descriptor_);
248 : printer->Print(variables_,
249 : "$deprecation$public boolean has$capitalized_name$() {\n"
250 : " return instance.has$capitalized_name$();\n"
251 0 : "}\n");
252 : }
253 :
254 0 : WriteFieldDocComment(printer, descriptor_);
255 : printer->Print(variables_,
256 : "$deprecation$public java.lang.String get$capitalized_name$() {\n"
257 : " return instance.get$capitalized_name$();\n"
258 0 : "}\n");
259 :
260 0 : WriteFieldDocComment(printer, descriptor_);
261 : printer->Print(variables_,
262 : "$deprecation$public com.google.protobuf.ByteString\n"
263 : " get$capitalized_name$Bytes() {\n"
264 : " return instance.get$capitalized_name$Bytes();\n"
265 0 : "}\n");
266 :
267 0 : WriteFieldDocComment(printer, descriptor_);
268 : printer->Print(variables_,
269 : "$deprecation$public Builder set$capitalized_name$(\n"
270 : " java.lang.String value) {\n"
271 : " copyOnWrite();\n"
272 : " instance.set$capitalized_name$(value);\n"
273 : " return this;\n"
274 0 : "}\n");
275 0 : WriteFieldDocComment(printer, descriptor_);
276 : printer->Print(variables_,
277 : "$deprecation$public Builder clear$capitalized_name$() {\n"
278 : " copyOnWrite();\n"
279 : " instance.clear$capitalized_name$();\n"
280 : " return this;\n"
281 0 : "}\n");
282 :
283 0 : WriteFieldDocComment(printer, descriptor_);
284 : printer->Print(variables_,
285 : "$deprecation$public Builder set$capitalized_name$Bytes(\n"
286 : " com.google.protobuf.ByteString value) {\n"
287 : " copyOnWrite();\n"
288 : " instance.set$capitalized_name$Bytes(value);\n"
289 : " return this;\n"
290 0 : "}\n");
291 0 : }
292 :
293 0 : void ImmutableStringFieldLiteGenerator::
294 : GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
295 : // noop for strings
296 0 : }
297 :
298 0 : void ImmutableStringFieldLiteGenerator::
299 : GenerateInitializationCode(io::Printer* printer) const {
300 0 : printer->Print(variables_, "$name$_ = $default$;\n");
301 0 : }
302 :
303 0 : void ImmutableStringFieldLiteGenerator::
304 : GenerateMergingCode(io::Printer* printer) const {
305 0 : if (SupportFieldPresence(descriptor_->file())) {
306 : // Allow a slight breach of abstraction here in order to avoid forcing
307 : // all string fields to Strings when copying fields from a Message.
308 : printer->Print(variables_,
309 : "if (other.has$capitalized_name$()) {\n"
310 : " $set_has_field_bit_message$\n"
311 : " $name$_ = other.$name$_;\n"
312 : " $on_changed$\n"
313 0 : "}\n");
314 : } else {
315 : printer->Print(variables_,
316 : "if (!other.get$capitalized_name$().isEmpty()) {\n"
317 : " $name$_ = other.$name$_;\n"
318 : " $on_changed$\n"
319 0 : "}\n");
320 : }
321 0 : }
322 :
323 0 : void ImmutableStringFieldLiteGenerator::
324 : GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
325 : // noop for scalars
326 0 : }
327 :
328 0 : void ImmutableStringFieldLiteGenerator::
329 : GenerateParsingCode(io::Printer* printer) const {
330 0 : if (CheckUtf8(descriptor_)) {
331 : printer->Print(variables_,
332 : "String s = input.readStringRequireUtf8();\n"
333 : "$set_has_field_bit_message$\n"
334 0 : "$name$_ = s;\n");
335 : } else {
336 : // Lite runtime should attempt to reduce allocations by attempting to
337 : // construct the string directly from the input stream buffer. This avoids
338 : // spurious intermediary ByteString allocations, cutting overall allocations
339 : // in half.
340 : printer->Print(variables_,
341 : "String s = input.readString();\n"
342 : "$set_has_field_bit_message$\n"
343 0 : "$name$_ = s;\n");
344 : }
345 0 : }
346 :
347 0 : void ImmutableStringFieldLiteGenerator::
348 : GenerateParsingDoneCode(io::Printer* printer) const {
349 : // noop for strings
350 0 : }
351 :
352 0 : void ImmutableStringFieldLiteGenerator::
353 : GenerateSerializationCode(io::Printer* printer) const {
354 : // Lite runtime should reduce allocations by serializing the string directly.
355 : // This avoids spurious intermediary ByteString allocations, cutting overall
356 : // allocations in half.
357 : printer->Print(variables_,
358 : "if ($is_field_present_message$) {\n"
359 : " output.writeString($number$, get$capitalized_name$());\n"
360 0 : "}\n");
361 0 : }
362 :
363 0 : void ImmutableStringFieldLiteGenerator::
364 : GenerateSerializedSizeCode(io::Printer* printer) const {
365 : // Lite runtime should reduce allocations by computing on the string directly.
366 : // This avoids spurious intermediary ByteString allocations, cutting overall
367 : // allocations in half.
368 : printer->Print(variables_,
369 : "if ($is_field_present_message$) {\n"
370 : " size += com.google.protobuf.CodedOutputStream\n"
371 : " .computeStringSize($number$, get$capitalized_name$());\n"
372 0 : "}\n");
373 0 : }
374 :
375 0 : void ImmutableStringFieldLiteGenerator::
376 : GenerateEqualsCode(io::Printer* printer) const {
377 : printer->Print(variables_,
378 : "result = result && get$capitalized_name$()\n"
379 0 : " .equals(other.get$capitalized_name$());\n");
380 0 : }
381 :
382 0 : void ImmutableStringFieldLiteGenerator::
383 : GenerateHashCode(io::Printer* printer) const {
384 : printer->Print(variables_,
385 0 : "hash = (37 * hash) + $constant_name$;\n");
386 : printer->Print(variables_,
387 0 : "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
388 0 : }
389 :
390 0 : string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
391 0 : return "java.lang.String";
392 : }
393 :
394 : // ===================================================================
395 :
396 0 : ImmutableStringOneofFieldLiteGenerator::
397 0 : ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
398 : int messageBitIndex,
399 : int builderBitIndex,
400 : Context* context)
401 : : ImmutableStringFieldLiteGenerator(
402 0 : descriptor, messageBitIndex, builderBitIndex, context) {
403 : const OneofGeneratorInfo* info =
404 0 : context->GetOneofGeneratorInfo(descriptor->containing_oneof());
405 0 : SetCommonOneofVariables(descriptor, info, &variables_);
406 0 : }
407 :
408 0 : ImmutableStringOneofFieldLiteGenerator::
409 0 : ~ImmutableStringOneofFieldLiteGenerator() {}
410 :
411 0 : void ImmutableStringOneofFieldLiteGenerator::
412 : GenerateMembers(io::Printer* printer) const {
413 0 : PrintExtraFieldInfo(variables_, printer);
414 :
415 0 : if (SupportFieldPresence(descriptor_->file())) {
416 0 : WriteFieldDocComment(printer, descriptor_);
417 : printer->Print(variables_,
418 : "$deprecation$public boolean has$capitalized_name$() {\n"
419 : " return $has_oneof_case_message$;\n"
420 0 : "}\n");
421 : }
422 :
423 0 : WriteFieldDocComment(printer, descriptor_);
424 : printer->Print(variables_,
425 : "$deprecation$public java.lang.String get$capitalized_name$() {\n"
426 : " java.lang.String ref $default_init$;\n"
427 : " if ($has_oneof_case_message$) {\n"
428 : " ref = (java.lang.String) $oneof_name$_;\n"
429 : " }\n"
430 : " return ref;\n"
431 0 : "}\n");
432 0 : WriteFieldDocComment(printer, descriptor_);
433 :
434 : printer->Print(variables_,
435 : "$deprecation$public com.google.protobuf.ByteString\n"
436 : " get$capitalized_name$Bytes() {\n"
437 : " java.lang.String ref $default_init$;\n"
438 : " if ($has_oneof_case_message$) {\n"
439 : " ref = (java.lang.String) $oneof_name$_;\n"
440 : " }\n"
441 : " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
442 0 : "}\n");
443 :
444 0 : WriteFieldDocComment(printer, descriptor_);
445 : printer->Print(variables_,
446 : "private void set$capitalized_name$(\n"
447 : " java.lang.String value) {\n"
448 : "$null_check$"
449 : " $set_oneof_case_message$;\n"
450 : " $oneof_name$_ = value;\n"
451 0 : "}\n");
452 0 : WriteFieldDocComment(printer, descriptor_);
453 : printer->Print(variables_,
454 : "private void clear$capitalized_name$() {\n"
455 : " if ($has_oneof_case_message$) {\n"
456 : " $clear_oneof_case_message$;\n"
457 : " $oneof_name$_ = null;\n"
458 : " }\n"
459 0 : "}\n");
460 :
461 0 : WriteFieldDocComment(printer, descriptor_);
462 : printer->Print(variables_,
463 : "private void set$capitalized_name$Bytes(\n"
464 : " com.google.protobuf.ByteString value) {\n"
465 0 : "$null_check$");
466 0 : if (CheckUtf8(descriptor_)) {
467 : printer->Print(variables_,
468 0 : " checkByteStringIsUtf8(value);\n");
469 : }
470 : printer->Print(variables_,
471 : " $set_oneof_case_message$;\n"
472 : " $oneof_name$_ = value.toStringUtf8();\n"
473 0 : "}\n");
474 0 : }
475 :
476 0 : void ImmutableStringOneofFieldLiteGenerator::
477 : GenerateBuilderMembers(io::Printer* printer) const {
478 0 : if (SupportFieldPresence(descriptor_->file())) {
479 0 : WriteFieldDocComment(printer, descriptor_);
480 : printer->Print(variables_,
481 : "$deprecation$public boolean has$capitalized_name$() {\n"
482 : " return instance.has$capitalized_name$();\n"
483 0 : "}\n");
484 : }
485 :
486 0 : WriteFieldDocComment(printer, descriptor_);
487 : printer->Print(variables_,
488 : "$deprecation$public java.lang.String get$capitalized_name$() {\n"
489 : " return instance.get$capitalized_name$();\n"
490 0 : "}\n");
491 :
492 0 : WriteFieldDocComment(printer, descriptor_);
493 : printer->Print(variables_,
494 : "$deprecation$public com.google.protobuf.ByteString\n"
495 : " get$capitalized_name$Bytes() {\n"
496 : " return instance.get$capitalized_name$Bytes();\n"
497 0 : "}\n");
498 :
499 0 : WriteFieldDocComment(printer, descriptor_);
500 : printer->Print(variables_,
501 : "$deprecation$public Builder set$capitalized_name$(\n"
502 : " java.lang.String value) {\n"
503 : " copyOnWrite();\n"
504 : " instance.set$capitalized_name$(value);\n"
505 : " return this;\n"
506 0 : "}\n");
507 0 : WriteFieldDocComment(printer, descriptor_);
508 : printer->Print(variables_,
509 : "$deprecation$public Builder clear$capitalized_name$() {\n"
510 : " copyOnWrite();\n"
511 : " instance.clear$capitalized_name$();\n"
512 : " return this;\n"
513 0 : "}\n");
514 :
515 0 : WriteFieldDocComment(printer, descriptor_);
516 : printer->Print(variables_,
517 : "$deprecation$public Builder set$capitalized_name$Bytes(\n"
518 : " com.google.protobuf.ByteString value) {\n"
519 : " copyOnWrite();\n"
520 : " instance.set$capitalized_name$Bytes(value);\n"
521 : " return this;\n"
522 0 : "}\n");
523 0 : }
524 :
525 0 : void ImmutableStringOneofFieldLiteGenerator::
526 : GenerateMergingCode(io::Printer* printer) const {
527 : // Allow a slight breach of abstraction here in order to avoid forcing
528 : // all string fields to Strings when copying fields from a Message.
529 : printer->Print(variables_,
530 : "$set_oneof_case_message$;\n"
531 : "$oneof_name$_ = other.$oneof_name$_;\n"
532 0 : "$on_changed$\n");
533 0 : }
534 :
535 0 : void ImmutableStringOneofFieldLiteGenerator::
536 : GenerateParsingCode(io::Printer* printer) const {
537 0 : if (CheckUtf8(descriptor_)) {
538 : printer->Print(variables_,
539 : "String s = input.readStringRequireUtf8();\n"
540 : "$set_oneof_case_message$;\n"
541 0 : "$oneof_name$_ = s;\n");
542 : } else {
543 : // Lite runtime should attempt to reduce allocations by attempting to
544 : // construct the string directly from the input stream buffer. This avoids
545 : // spurious intermediary ByteString allocations, cutting overall allocations
546 : // in half.
547 : printer->Print(variables_,
548 : "String s = input.readString();\n"
549 : "$set_oneof_case_message$;\n"
550 0 : "$oneof_name$_ = s;\n");
551 : }
552 0 : }
553 :
554 0 : void ImmutableStringOneofFieldLiteGenerator::
555 : GenerateSerializationCode(io::Printer* printer) const {
556 : // Lite runtime should reduce allocations by serializing the string directly.
557 : // This avoids spurious intermediary ByteString allocations, cutting overall
558 : // allocations in half.
559 : printer->Print(variables_,
560 : "if ($has_oneof_case_message$) {\n"
561 : " output.writeString($number$, get$capitalized_name$());\n"
562 0 : "}\n");
563 0 : }
564 :
565 0 : void ImmutableStringOneofFieldLiteGenerator::
566 : GenerateSerializedSizeCode(io::Printer* printer) const {
567 : // Lite runtime should reduce allocations by computing on the string directly.
568 : // This avoids spurious intermediary ByteString allocations, cutting overall
569 : // allocations in half.
570 : printer->Print(variables_,
571 : "if ($has_oneof_case_message$) {\n"
572 : " size += com.google.protobuf.CodedOutputStream\n"
573 : " .computeStringSize($number$, get$capitalized_name$());\n"
574 0 : "}\n");
575 0 : }
576 :
577 : // ===================================================================
578 :
579 0 : RepeatedImmutableStringFieldLiteGenerator::
580 : RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
581 : int messageBitIndex,
582 : int builderBitIndex,
583 : Context* context)
584 : : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
585 : builderBitIndex_(builderBitIndex), context_(context),
586 0 : name_resolver_(context->GetNameResolver()) {
587 : SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
588 : context->GetFieldGeneratorInfo(descriptor),
589 0 : name_resolver_, &variables_);
590 0 : }
591 :
592 0 : RepeatedImmutableStringFieldLiteGenerator::
593 0 : ~RepeatedImmutableStringFieldLiteGenerator() {}
594 :
595 0 : int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
596 0 : return 0;
597 : }
598 :
599 0 : int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
600 0 : return 0;
601 : }
602 :
603 0 : void RepeatedImmutableStringFieldLiteGenerator::
604 : GenerateInterfaceMembers(io::Printer* printer) const {
605 0 : WriteFieldDocComment(printer, descriptor_);
606 : printer->Print(variables_,
607 : "$deprecation$java.util.List<String>\n"
608 0 : " get$capitalized_name$List();\n");
609 0 : WriteFieldDocComment(printer, descriptor_);
610 : printer->Print(variables_,
611 0 : "$deprecation$int get$capitalized_name$Count();\n");
612 0 : WriteFieldDocComment(printer, descriptor_);
613 : printer->Print(variables_,
614 0 : "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
615 0 : WriteFieldDocComment(printer, descriptor_);
616 : printer->Print(variables_,
617 : "$deprecation$com.google.protobuf.ByteString\n"
618 0 : " get$capitalized_name$Bytes(int index);\n");
619 0 : }
620 :
621 :
622 0 : void RepeatedImmutableStringFieldLiteGenerator::
623 : GenerateMembers(io::Printer* printer) const {
624 : printer->Print(variables_,
625 0 : "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n");
626 0 : PrintExtraFieldInfo(variables_, printer);
627 0 : WriteFieldDocComment(printer, descriptor_);
628 : printer->Print(variables_,
629 : "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n"
630 : " return $name$_;\n" // note: unmodifiable list
631 0 : "}\n");
632 0 : WriteFieldDocComment(printer, descriptor_);
633 : printer->Print(variables_,
634 : "$deprecation$public int get$capitalized_name$Count() {\n"
635 : " return $name$_.size();\n"
636 0 : "}\n");
637 0 : WriteFieldDocComment(printer, descriptor_);
638 : printer->Print(variables_,
639 : "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
640 : " return $name$_.get(index);\n"
641 0 : "}\n");
642 0 : WriteFieldDocComment(printer, descriptor_);
643 : printer->Print(variables_,
644 : "$deprecation$public com.google.protobuf.ByteString\n"
645 : " get$capitalized_name$Bytes(int index) {\n"
646 : " return com.google.protobuf.ByteString.copyFromUtf8(\n"
647 : " $name$_.get(index));\n"
648 0 : "}\n");
649 :
650 0 : if (descriptor_->options().packed() &&
651 0 : HasGeneratedMethods(descriptor_->containing_type())) {
652 : printer->Print(variables_,
653 0 : "private int $name$MemoizedSerializedSize = -1;\n");
654 : }
655 :
656 : printer->Print(variables_,
657 : "private void ensure$capitalized_name$IsMutable() {\n"
658 : " if (!$is_mutable$) {\n"
659 : " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n"
660 : " $name$_);\n"
661 : " }\n"
662 0 : "}\n");
663 :
664 0 : WriteFieldDocComment(printer, descriptor_);
665 : printer->Print(variables_,
666 : "private void set$capitalized_name$(\n"
667 : " int index, java.lang.String value) {\n"
668 : "$null_check$"
669 : " ensure$capitalized_name$IsMutable();\n"
670 : " $name$_.set(index, value);\n"
671 0 : "}\n");
672 0 : WriteFieldDocComment(printer, descriptor_);
673 : printer->Print(variables_,
674 : "private void add$capitalized_name$(\n"
675 : " java.lang.String value) {\n"
676 : "$null_check$"
677 : " ensure$capitalized_name$IsMutable();\n"
678 : " $name$_.add(value);\n"
679 0 : "}\n");
680 0 : WriteFieldDocComment(printer, descriptor_);
681 : printer->Print(variables_,
682 : "private void addAll$capitalized_name$(\n"
683 : " java.lang.Iterable<java.lang.String> values) {\n"
684 : " ensure$capitalized_name$IsMutable();\n"
685 : " com.google.protobuf.AbstractMessageLite.addAll(\n"
686 : " values, $name$_);\n"
687 0 : "}\n");
688 0 : WriteFieldDocComment(printer, descriptor_);
689 : printer->Print(variables_,
690 : "private void clear$capitalized_name$() {\n"
691 : " $name$_ = $empty_list$;\n"
692 0 : "}\n");
693 :
694 0 : WriteFieldDocComment(printer, descriptor_);
695 : printer->Print(variables_,
696 : "private void add$capitalized_name$Bytes(\n"
697 : " com.google.protobuf.ByteString value) {\n"
698 0 : "$null_check$");
699 0 : if (CheckUtf8(descriptor_)) {
700 : printer->Print(variables_,
701 0 : " checkByteStringIsUtf8(value);\n");
702 : }
703 : printer->Print(variables_,
704 : " ensure$capitalized_name$IsMutable();\n"
705 : " $name$_.add(value.toStringUtf8());\n"
706 0 : "}\n");
707 0 : }
708 :
709 0 : void RepeatedImmutableStringFieldLiteGenerator::
710 : GenerateBuilderMembers(io::Printer* printer) const {
711 0 : WriteFieldDocComment(printer, descriptor_);
712 : printer->Print(variables_,
713 : "$deprecation$public java.util.List<String>\n"
714 : " get$capitalized_name$List() {\n"
715 : " return java.util.Collections.unmodifiableList(\n"
716 : " instance.get$capitalized_name$List());\n"
717 0 : "}\n");
718 0 : WriteFieldDocComment(printer, descriptor_);
719 : printer->Print(variables_,
720 : "$deprecation$public int get$capitalized_name$Count() {\n"
721 : " return instance.get$capitalized_name$Count();\n"
722 0 : "}\n");
723 0 : WriteFieldDocComment(printer, descriptor_);
724 : printer->Print(variables_,
725 : "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
726 : " return instance.get$capitalized_name$(index);\n"
727 0 : "}\n");
728 0 : WriteFieldDocComment(printer, descriptor_);
729 : printer->Print(variables_,
730 : "$deprecation$public com.google.protobuf.ByteString\n"
731 : " get$capitalized_name$Bytes(int index) {\n"
732 : " return instance.get$capitalized_name$Bytes(index);\n"
733 0 : "}\n");
734 0 : WriteFieldDocComment(printer, descriptor_);
735 : printer->Print(variables_,
736 : "$deprecation$public Builder set$capitalized_name$(\n"
737 : " int index, java.lang.String value) {\n"
738 : " copyOnWrite();\n"
739 : " instance.set$capitalized_name$(index, value);\n"
740 : " return this;\n"
741 0 : "}\n");
742 0 : WriteFieldDocComment(printer, descriptor_);
743 : printer->Print(variables_,
744 : "$deprecation$public Builder add$capitalized_name$(\n"
745 : " java.lang.String value) {\n"
746 : " copyOnWrite();\n"
747 : " instance.add$capitalized_name$(value);\n"
748 : " return this;\n"
749 0 : "}\n");
750 0 : WriteFieldDocComment(printer, descriptor_);
751 : printer->Print(variables_,
752 : "$deprecation$public Builder addAll$capitalized_name$(\n"
753 : " java.lang.Iterable<java.lang.String> values) {\n"
754 : " copyOnWrite();\n"
755 : " instance.addAll$capitalized_name$(values);\n"
756 : " return this;\n"
757 0 : "}\n");
758 0 : WriteFieldDocComment(printer, descriptor_);
759 : printer->Print(variables_,
760 : "$deprecation$public Builder clear$capitalized_name$() {\n"
761 : " copyOnWrite();\n"
762 : " instance.clear$capitalized_name$();\n"
763 : " return this;\n"
764 0 : "}\n");
765 :
766 0 : WriteFieldDocComment(printer, descriptor_);
767 : printer->Print(variables_,
768 : "$deprecation$public Builder add$capitalized_name$Bytes(\n"
769 : " com.google.protobuf.ByteString value) {\n"
770 : " copyOnWrite();\n"
771 : " instance.add$capitalized_name$Bytes(value);\n"
772 : " return this;\n"
773 0 : "}\n");
774 0 : }
775 :
776 0 : void RepeatedImmutableStringFieldLiteGenerator::
777 : GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
778 : // noop for strings
779 0 : }
780 :
781 0 : void RepeatedImmutableStringFieldLiteGenerator::
782 : GenerateInitializationCode(io::Printer* printer) const {
783 0 : printer->Print(variables_, "$name$_ = $empty_list$;\n");
784 0 : }
785 :
786 0 : void RepeatedImmutableStringFieldLiteGenerator::
787 : GenerateMergingCode(io::Printer* printer) const {
788 : // The code below does two optimizations:
789 : // 1. If the other list is empty, there's nothing to do. This ensures we
790 : // don't allocate a new array if we already have an immutable one.
791 : // 2. If the other list is non-empty and our current list is empty, we can
792 : // reuse the other list which is guaranteed to be immutable.
793 : printer->Print(variables_,
794 : "if (!other.$name$_.isEmpty()) {\n"
795 : " if ($name$_.isEmpty()) {\n"
796 : " $name$_ = other.$name$_;\n"
797 : " } else {\n"
798 : " ensure$capitalized_name$IsMutable();\n"
799 : " $name$_.addAll(other.$name$_);\n"
800 : " }\n"
801 : " $on_changed$\n"
802 0 : "}\n");
803 0 : }
804 :
805 0 : void RepeatedImmutableStringFieldLiteGenerator::
806 : GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
807 : printer->Print(variables_,
808 0 : "$name$_.makeImmutable();\n");
809 0 : }
810 :
811 0 : void RepeatedImmutableStringFieldLiteGenerator::
812 : GenerateParsingCode(io::Printer* printer) const {
813 0 : if (CheckUtf8(descriptor_)) {
814 : printer->Print(variables_,
815 0 : "String s = input.readStringRequireUtf8();\n");
816 : } else {
817 : // Lite runtime should attempt to reduce allocations by attempting to
818 : // construct the string directly from the input stream buffer. This avoids
819 : // spurious intermediary ByteString allocations, cutting overall allocations
820 : // in half.
821 : printer->Print(variables_,
822 0 : "String s = input.readString();\n");
823 : }
824 : printer->Print(variables_,
825 : "if (!$is_mutable$) {\n"
826 : " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
827 0 : "}\n");
828 0 : if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
829 : printer->Print(variables_,
830 0 : "$name$_.add(s);\n");
831 : } else {
832 : printer->Print(variables_,
833 0 : "$name$_.add(bs);\n");
834 : }
835 0 : }
836 :
837 0 : void RepeatedImmutableStringFieldLiteGenerator::
838 : GenerateParsingCodeFromPacked(io::Printer* printer) const {
839 : printer->Print(variables_,
840 : "int length = input.readRawVarint32();\n"
841 : "int limit = input.pushLimit(length);\n"
842 : "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n"
843 : " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
844 : "}\n"
845 0 : "while (input.getBytesUntilLimit() > 0) {\n");
846 0 : if (CheckUtf8(descriptor_)) {
847 : printer->Print(variables_,
848 0 : " String s = input.readStringRequireUtf8();\n");
849 : } else {
850 : printer->Print(variables_,
851 0 : " String s = input.readString();\n");
852 : }
853 : printer->Print(variables_,
854 0 : " $name$.add(s);\n");
855 : printer->Print(variables_,
856 : "}\n"
857 0 : "input.popLimit(limit);\n");
858 0 : }
859 :
860 0 : void RepeatedImmutableStringFieldLiteGenerator::
861 : GenerateParsingDoneCode(io::Printer* printer) const {
862 : printer->Print(variables_,
863 : "if ($is_mutable$) {\n"
864 : " $name$_.makeImmutable();\n"
865 0 : "}\n");
866 0 : }
867 :
868 0 : void RepeatedImmutableStringFieldLiteGenerator::
869 : GenerateSerializationCode(io::Printer* printer) const {
870 : // Lite runtime should reduce allocations by serializing the string directly.
871 : // This avoids spurious intermediary ByteString allocations, cutting overall
872 : // allocations in half.
873 0 : if (descriptor_->options().packed()) {
874 : printer->Print(variables_,
875 : "if (get$capitalized_name$List().size() > 0) {\n"
876 : " output.writeRawVarint32($tag$);\n"
877 : " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
878 : "}\n"
879 : "for (int i = 0; i < $name$_.size(); i++) {\n"
880 : " output.writeStringNoTag($name$_.get(i));\n"
881 0 : "}\n");
882 : } else {
883 : printer->Print(variables_,
884 : "for (int i = 0; i < $name$_.size(); i++) {\n"
885 : " output.writeString($number$, $name$_.get(i));\n"
886 0 : "}\n");
887 : }
888 0 : }
889 :
890 0 : void RepeatedImmutableStringFieldLiteGenerator::
891 : GenerateSerializedSizeCode(io::Printer* printer) const {
892 : // Lite runtime should reduce allocations by computing on the string directly.
893 : // This avoids spurious intermediary ByteString allocations, cutting overall
894 : // allocations in half.
895 : printer->Print(variables_,
896 : "{\n"
897 0 : " int dataSize = 0;\n");
898 0 : printer->Indent();
899 :
900 : printer->Print(variables_,
901 : "for (int i = 0; i < $name$_.size(); i++) {\n"
902 : " dataSize += com.google.protobuf.CodedOutputStream\n"
903 : " .computeStringSizeNoTag($name$_.get(i));\n"
904 0 : "}\n");
905 :
906 : printer->Print(
907 0 : "size += dataSize;\n");
908 :
909 0 : if (descriptor_->options().packed()) {
910 : printer->Print(variables_,
911 : "if (!get$capitalized_name$List().isEmpty()) {\n"
912 : " size += $tag_size$;\n"
913 : " size += com.google.protobuf.CodedOutputStream\n"
914 : " .computeInt32SizeNoTag(dataSize);\n"
915 0 : "}\n");
916 : } else {
917 : printer->Print(variables_,
918 0 : "size += $tag_size$ * get$capitalized_name$List().size();\n");
919 : }
920 :
921 : // cache the data size for packed fields.
922 0 : if (descriptor_->options().packed()) {
923 : printer->Print(variables_,
924 0 : "$name$MemoizedSerializedSize = dataSize;\n");
925 : }
926 :
927 0 : printer->Outdent();
928 0 : printer->Print("}\n");
929 0 : }
930 :
931 0 : void RepeatedImmutableStringFieldLiteGenerator::
932 : GenerateEqualsCode(io::Printer* printer) const {
933 : printer->Print(variables_,
934 : "result = result && get$capitalized_name$List()\n"
935 0 : " .equals(other.get$capitalized_name$List());\n");
936 0 : }
937 :
938 0 : void RepeatedImmutableStringFieldLiteGenerator::
939 : GenerateHashCode(io::Printer* printer) const {
940 : printer->Print(variables_,
941 : "if (get$capitalized_name$Count() > 0) {\n"
942 : " hash = (37 * hash) + $constant_name$;\n"
943 : " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
944 0 : "}\n");
945 0 : }
946 :
947 0 : string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
948 0 : return "String";
949 : }
950 :
951 : } // namespace java
952 : } // namespace compiler
953 : } // namespace protobuf
954 : } // namespace google
|