blob: eb5964bd300e0ccef72611b2c0915c170a236f67 [file] [log] [blame]
Bo Yang5db21732015-05-21 14:28:59 -07001// 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
Feng Xiaoeee38b02015-08-22 18:25:48 -070039#include <google/protobuf/stubs/logging.h>
Bo Yang5db21732015-05-21 14:28:59 -070040#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
50namespace google {
51namespace protobuf {
52namespace compiler {
53namespace java {
54
55using internal::WireFormat;
56using internal::WireFormatLite;
57
58namespace {
59
60void SetPrimitiveVariables(const FieldDescriptor* descriptor,
61 int messageBitIndex,
62 int builderBitIndex,
63 const FieldGeneratorInfo* info,
64 ClassNameResolver* name_resolver,
65 map<string, string>* variables) {
66 SetCommonFieldVariables(descriptor, info, variables);
67
Feng Xiaoeee38b02015-08-22 18:25:48 -070068 (*variables)["empty_list"] =
69 "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
Bo Yang5db21732015-05-21 14:28:59 -070070
71 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
72 (*variables)["default_init"] =
73 "= " + ImmutableDefaultValue(descriptor, name_resolver);
74 (*variables)["capitalized_type"] = "String";
75 (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
76 (*variables)["tag_size"] = SimpleItoa(
77 WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
78 (*variables)["null_check"] =
79 " if (value == null) {\n"
80 " throw new NullPointerException();\n"
81 " }\n";
82
83 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
84 // by the proto compiler
85 (*variables)["deprecation"] = descriptor->options().deprecated()
86 ? "@java.lang.Deprecated " : "";
87 (*variables)["on_changed"] =
88 HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
89
90 if (SupportFieldPresence(descriptor->file())) {
91 // For singular messages and builders, one bit is used for the hasField bit.
92 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
93
94 // Note that these have a trailing ";".
95 (*variables)["set_has_field_bit_message"] =
96 GenerateSetBit(messageBitIndex) + ";";
97 (*variables)["clear_has_field_bit_message"] =
98 GenerateClearBit(messageBitIndex) + ";";
99
100 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
101 } else {
102 (*variables)["set_has_field_bit_message"] = "";
103 (*variables)["clear_has_field_bit_message"] = "";
104
105 (*variables)["is_field_present_message"] =
Feng Xiaoeee38b02015-08-22 18:25:48 -0700106 "!get" + (*variables)["capitalized_name"] + ".isEmpty()";
Bo Yang5db21732015-05-21 14:28:59 -0700107 }
108
109 // For repeated builders, the underlying list tracks mutability state.
110 (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
111
112 (*variables)["get_has_field_bit_from_local"] =
113 GenerateGetBitFromLocal(builderBitIndex);
114 (*variables)["set_has_field_bit_to_local"] =
115 GenerateSetBitToLocal(messageBitIndex);
116}
117
Bo Yang5db21732015-05-21 14:28:59 -0700118} // namespace
119
120// ===================================================================
121
122ImmutableStringFieldLiteGenerator::
123ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
124 int messageBitIndex,
125 int builderBitIndex,
126 Context* context)
127 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
128 builderBitIndex_(builderBitIndex), context_(context),
129 name_resolver_(context->GetNameResolver()) {
130 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
131 context->GetFieldGeneratorInfo(descriptor),
132 name_resolver_, &variables_);
133}
134
135ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
136
137int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
138 return 1;
139}
140
141int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
142 return 0;
143}
144
Feng Xiaoeee38b02015-08-22 18:25:48 -0700145// 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:
Bo Yang5db21732015-05-21 14:28:59 -0700148//
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//
Feng Xiaoeee38b02015-08-22 18:25:48 -0700162// 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.
Bo Yang5db21732015-05-21 14:28:59 -0700170void ImmutableStringFieldLiteGenerator::
171GenerateInterfaceMembers(io::Printer* printer) const {
172 if (SupportFieldPresence(descriptor_->file())) {
173 WriteFieldDocComment(printer, descriptor_);
174 printer->Print(variables_,
175 "$deprecation$boolean has$capitalized_name$();\n");
176 }
177 WriteFieldDocComment(printer, descriptor_);
178 printer->Print(variables_,
179 "$deprecation$java.lang.String get$capitalized_name$();\n");
180 WriteFieldDocComment(printer, descriptor_);
181 printer->Print(variables_,
182 "$deprecation$com.google.protobuf.ByteString\n"
183 " get$capitalized_name$Bytes();\n");
184}
185
186void ImmutableStringFieldLiteGenerator::
187GenerateMembers(io::Printer* printer) const {
188 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700189 "private java.lang.String $name$_;\n");
Bo Yang5db21732015-05-21 14:28:59 -0700190 PrintExtraFieldInfo(variables_, printer);
191
192 if (SupportFieldPresence(descriptor_->file())) {
193 WriteFieldDocComment(printer, descriptor_);
194 printer->Print(variables_,
195 "$deprecation$public boolean has$capitalized_name$() {\n"
196 " return $get_has_field_bit_message$;\n"
197 "}\n");
198 }
199
200 WriteFieldDocComment(printer, descriptor_);
201 printer->Print(variables_,
202 "$deprecation$public java.lang.String get$capitalized_name$() {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700203 " return $name$_;\n"
Bo Yang5db21732015-05-21 14:28:59 -0700204 "}\n");
205 WriteFieldDocComment(printer, descriptor_);
206 printer->Print(variables_,
207 "$deprecation$public com.google.protobuf.ByteString\n"
208 " get$capitalized_name$Bytes() {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700209 " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
Bo Yang5db21732015-05-21 14:28:59 -0700210 "}\n");
211
212 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 "}\n");
220 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 "}\n");
228
229 WriteFieldDocComment(printer, descriptor_);
230 printer->Print(variables_,
231 "private void set$capitalized_name$Bytes(\n"
232 " com.google.protobuf.ByteString value) {\n"
233 "$null_check$");
234 if (CheckUtf8(descriptor_)) {
235 printer->Print(variables_,
236 " checkByteStringIsUtf8(value);\n");
237 }
238 printer->Print(variables_,
239 " $set_has_field_bit_message$\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700240 " $name$_ = value.toStringUtf8();\n"
Bo Yang5db21732015-05-21 14:28:59 -0700241 "}\n");
242}
243
244void ImmutableStringFieldLiteGenerator::
245GenerateBuilderMembers(io::Printer* printer) const {
246 if (SupportFieldPresence(descriptor_->file())) {
247 WriteFieldDocComment(printer, descriptor_);
248 printer->Print(variables_,
249 "$deprecation$public boolean has$capitalized_name$() {\n"
250 " return instance.has$capitalized_name$();\n"
251 "}\n");
252 }
253
254 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 "}\n");
259
260 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 "}\n");
266
267 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 "}\n");
275 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 "}\n");
282
283 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 "}\n");
291}
292
293void ImmutableStringFieldLiteGenerator::
294GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
295 // noop for strings
296}
297
298void ImmutableStringFieldLiteGenerator::
299GenerateInitializationCode(io::Printer* printer) const {
300 printer->Print(variables_, "$name$_ = $default$;\n");
301}
302
303void ImmutableStringFieldLiteGenerator::
304GenerateMergingCode(io::Printer* printer) const {
305 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 "}\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 "}\n");
320 }
321}
322
323void ImmutableStringFieldLiteGenerator::
324GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
325 // noop for scalars
326}
327
328void ImmutableStringFieldLiteGenerator::
329GenerateParsingCode(io::Printer* printer) const {
330 if (CheckUtf8(descriptor_)) {
331 printer->Print(variables_,
332 "String s = input.readStringRequireUtf8();\n"
333 "$set_has_field_bit_message$\n"
334 "$name$_ = s;\n");
Feng Xiaoeee38b02015-08-22 18:25:48 -0700335 } else {
Bo Yang5db21732015-05-21 14:28:59 -0700336 // 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 "$name$_ = s;\n");
Bo Yang5db21732015-05-21 14:28:59 -0700344 }
345}
346
347void ImmutableStringFieldLiteGenerator::
348GenerateParsingDoneCode(io::Printer* printer) const {
349 // noop for strings
350}
351
352void ImmutableStringFieldLiteGenerator::
353GenerateSerializationCode(io::Printer* printer) const {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700354 // Lite runtime should reduce allocations by serializing the string directly.
355 // This avoids spurious intermediary ByteString allocations, cutting overall
356 // allocations in half.
Bo Yang5db21732015-05-21 14:28:59 -0700357 printer->Print(variables_,
358 "if ($is_field_present_message$) {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700359 " output.writeString($number$, get$capitalized_name$());\n"
Bo Yang5db21732015-05-21 14:28:59 -0700360 "}\n");
361}
362
363void ImmutableStringFieldLiteGenerator::
364GenerateSerializedSizeCode(io::Printer* printer) const {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700365 // Lite runtime should reduce allocations by computing on the string directly.
366 // This avoids spurious intermediary ByteString allocations, cutting overall
367 // allocations in half.
Bo Yang5db21732015-05-21 14:28:59 -0700368 printer->Print(variables_,
369 "if ($is_field_present_message$) {\n"
370 " size += com.google.protobuf.CodedOutputStream\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700371 " .computeStringSize($number$, get$capitalized_name$());\n"
Bo Yang5db21732015-05-21 14:28:59 -0700372 "}\n");
373}
374
375void ImmutableStringFieldLiteGenerator::
376GenerateEqualsCode(io::Printer* printer) const {
377 printer->Print(variables_,
378 "result = result && get$capitalized_name$()\n"
379 " .equals(other.get$capitalized_name$());\n");
380}
381
382void ImmutableStringFieldLiteGenerator::
383GenerateHashCode(io::Printer* printer) const {
384 printer->Print(variables_,
385 "hash = (37 * hash) + $constant_name$;\n");
386 printer->Print(variables_,
387 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
388}
389
390string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
391 return "java.lang.String";
392}
393
394// ===================================================================
395
396ImmutableStringOneofFieldLiteGenerator::
397ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
398 int messageBitIndex,
399 int builderBitIndex,
400 Context* context)
401 : ImmutableStringFieldLiteGenerator(
402 descriptor, messageBitIndex, builderBitIndex, context) {
403 const OneofGeneratorInfo* info =
404 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
405 SetCommonOneofVariables(descriptor, info, &variables_);
406}
407
408ImmutableStringOneofFieldLiteGenerator::
409~ImmutableStringOneofFieldLiteGenerator() {}
410
411void ImmutableStringOneofFieldLiteGenerator::
412GenerateMembers(io::Printer* printer) const {
413 PrintExtraFieldInfo(variables_, printer);
414
415 if (SupportFieldPresence(descriptor_->file())) {
416 WriteFieldDocComment(printer, descriptor_);
417 printer->Print(variables_,
418 "$deprecation$public boolean has$capitalized_name$() {\n"
419 " return $has_oneof_case_message$;\n"
420 "}\n");
421 }
422
423 WriteFieldDocComment(printer, descriptor_);
424 printer->Print(variables_,
425 "$deprecation$public java.lang.String get$capitalized_name$() {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700426 " java.lang.String ref $default_init$;\n"
Bo Yang5db21732015-05-21 14:28:59 -0700427 " if ($has_oneof_case_message$) {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700428 " ref = (java.lang.String) $oneof_name$_;\n"
Bo Yang5db21732015-05-21 14:28:59 -0700429 " }\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700430 " return ref;\n"
Bo Yang5db21732015-05-21 14:28:59 -0700431 "}\n");
432 WriteFieldDocComment(printer, descriptor_);
433
434 printer->Print(variables_,
435 "$deprecation$public com.google.protobuf.ByteString\n"
436 " get$capitalized_name$Bytes() {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700437 " java.lang.String ref $default_init$;\n"
Bo Yang5db21732015-05-21 14:28:59 -0700438 " if ($has_oneof_case_message$) {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700439 " ref = (java.lang.String) $oneof_name$_;\n"
Bo Yang5db21732015-05-21 14:28:59 -0700440 " }\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700441 " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
Bo Yang5db21732015-05-21 14:28:59 -0700442 "}\n");
443
444 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 "}\n");
452 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 "}\n");
460
461 WriteFieldDocComment(printer, descriptor_);
462 printer->Print(variables_,
463 "private void set$capitalized_name$Bytes(\n"
464 " com.google.protobuf.ByteString value) {\n"
465 "$null_check$");
466 if (CheckUtf8(descriptor_)) {
467 printer->Print(variables_,
468 " checkByteStringIsUtf8(value);\n");
469 }
470 printer->Print(variables_,
471 " $set_oneof_case_message$;\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700472 " $oneof_name$_ = value.toStringUtf8();\n"
Bo Yang5db21732015-05-21 14:28:59 -0700473 "}\n");
474}
475
476void ImmutableStringOneofFieldLiteGenerator::
477GenerateBuilderMembers(io::Printer* printer) const {
478 if (SupportFieldPresence(descriptor_->file())) {
479 WriteFieldDocComment(printer, descriptor_);
480 printer->Print(variables_,
481 "$deprecation$public boolean has$capitalized_name$() {\n"
482 " return instance.has$capitalized_name$();\n"
483 "}\n");
484 }
485
486 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 "}\n");
491
492 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 "}\n");
498
499 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 "}\n");
507 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 "}\n");
514
515 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 "}\n");
523}
524
525void ImmutableStringOneofFieldLiteGenerator::
526GenerateMergingCode(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 "$on_changed$\n");
533}
534
535void ImmutableStringOneofFieldLiteGenerator::
536GenerateParsingCode(io::Printer* printer) const {
537 if (CheckUtf8(descriptor_)) {
538 printer->Print(variables_,
539 "String s = input.readStringRequireUtf8();\n"
540 "$set_oneof_case_message$;\n"
541 "$oneof_name$_ = s;\n");
Feng Xiaoeee38b02015-08-22 18:25:48 -0700542 } else {
Bo Yang5db21732015-05-21 14:28:59 -0700543 // 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 "$oneof_name$_ = s;\n");
Bo Yang5db21732015-05-21 14:28:59 -0700551 }
552}
553
554void ImmutableStringOneofFieldLiteGenerator::
555GenerateSerializationCode(io::Printer* printer) const {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700556 // Lite runtime should reduce allocations by serializing the string directly.
557 // This avoids spurious intermediary ByteString allocations, cutting overall
558 // allocations in half.
Bo Yang5db21732015-05-21 14:28:59 -0700559 printer->Print(variables_,
560 "if ($has_oneof_case_message$) {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700561 " output.writeString($number$, get$capitalized_name$());\n"
Bo Yang5db21732015-05-21 14:28:59 -0700562 "}\n");
563}
564
565void ImmutableStringOneofFieldLiteGenerator::
566GenerateSerializedSizeCode(io::Printer* printer) const {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700567 // Lite runtime should reduce allocations by computing on the string directly.
568 // This avoids spurious intermediary ByteString allocations, cutting overall
569 // allocations in half.
Bo Yang5db21732015-05-21 14:28:59 -0700570 printer->Print(variables_,
571 "if ($has_oneof_case_message$) {\n"
572 " size += com.google.protobuf.CodedOutputStream\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700573 " .computeStringSize($number$, get$capitalized_name$());\n"
Bo Yang5db21732015-05-21 14:28:59 -0700574 "}\n");
575}
576
577// ===================================================================
578
579RepeatedImmutableStringFieldLiteGenerator::
580RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
581 int messageBitIndex,
582 int builderBitIndex,
583 Context* context)
584 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
585 builderBitIndex_(builderBitIndex), context_(context),
586 name_resolver_(context->GetNameResolver()) {
587 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
588 context->GetFieldGeneratorInfo(descriptor),
589 name_resolver_, &variables_);
590}
591
592RepeatedImmutableStringFieldLiteGenerator::
593~RepeatedImmutableStringFieldLiteGenerator() {}
594
595int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
596 return 0;
597}
598
599int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
600 return 0;
601}
602
603void RepeatedImmutableStringFieldLiteGenerator::
604GenerateInterfaceMembers(io::Printer* printer) const {
605 WriteFieldDocComment(printer, descriptor_);
606 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700607 "$deprecation$java.util.List<String>\n"
Bo Yang5db21732015-05-21 14:28:59 -0700608 " get$capitalized_name$List();\n");
609 WriteFieldDocComment(printer, descriptor_);
610 printer->Print(variables_,
611 "$deprecation$int get$capitalized_name$Count();\n");
612 WriteFieldDocComment(printer, descriptor_);
613 printer->Print(variables_,
614 "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
615 WriteFieldDocComment(printer, descriptor_);
616 printer->Print(variables_,
617 "$deprecation$com.google.protobuf.ByteString\n"
618 " get$capitalized_name$Bytes(int index);\n");
619}
620
621
622void RepeatedImmutableStringFieldLiteGenerator::
623GenerateMembers(io::Printer* printer) const {
624 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700625 "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n");
Bo Yang5db21732015-05-21 14:28:59 -0700626 PrintExtraFieldInfo(variables_, printer);
627 WriteFieldDocComment(printer, descriptor_);
628 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700629 "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n"
Bo Yang5db21732015-05-21 14:28:59 -0700630 " return $name$_;\n" // note: unmodifiable list
631 "}\n");
632 WriteFieldDocComment(printer, descriptor_);
633 printer->Print(variables_,
634 "$deprecation$public int get$capitalized_name$Count() {\n"
635 " return $name$_.size();\n"
636 "}\n");
637 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 "}\n");
642 WriteFieldDocComment(printer, descriptor_);
643 printer->Print(variables_,
644 "$deprecation$public com.google.protobuf.ByteString\n"
645 " get$capitalized_name$Bytes(int index) {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700646 " return com.google.protobuf.ByteString.copyFromUtf8(\n"
647 " $name$_.get(index));\n"
Bo Yang5db21732015-05-21 14:28:59 -0700648 "}\n");
649
Bo Yang5db21732015-05-21 14:28:59 -0700650 printer->Print(variables_,
651 "private void ensure$capitalized_name$IsMutable() {\n"
652 " if (!$is_mutable$) {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700653 " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n"
654 " $name$_);\n"
Bo Yang5db21732015-05-21 14:28:59 -0700655 " }\n"
656 "}\n");
657
658 WriteFieldDocComment(printer, descriptor_);
659 printer->Print(variables_,
660 "private void set$capitalized_name$(\n"
661 " int index, java.lang.String value) {\n"
662 "$null_check$"
663 " ensure$capitalized_name$IsMutable();\n"
664 " $name$_.set(index, value);\n"
665 "}\n");
666 WriteFieldDocComment(printer, descriptor_);
667 printer->Print(variables_,
668 "private void add$capitalized_name$(\n"
669 " java.lang.String value) {\n"
670 "$null_check$"
671 " ensure$capitalized_name$IsMutable();\n"
672 " $name$_.add(value);\n"
673 "}\n");
674 WriteFieldDocComment(printer, descriptor_);
675 printer->Print(variables_,
676 "private void addAll$capitalized_name$(\n"
677 " java.lang.Iterable<java.lang.String> values) {\n"
678 " ensure$capitalized_name$IsMutable();\n"
679 " com.google.protobuf.AbstractMessageLite.addAll(\n"
680 " values, $name$_);\n"
681 "}\n");
682 WriteFieldDocComment(printer, descriptor_);
683 printer->Print(variables_,
684 "private void clear$capitalized_name$() {\n"
685 " $name$_ = $empty_list$;\n"
686 "}\n");
687
688 WriteFieldDocComment(printer, descriptor_);
689 printer->Print(variables_,
690 "private void add$capitalized_name$Bytes(\n"
691 " com.google.protobuf.ByteString value) {\n"
692 "$null_check$");
693 if (CheckUtf8(descriptor_)) {
694 printer->Print(variables_,
695 " checkByteStringIsUtf8(value);\n");
696 }
697 printer->Print(variables_,
698 " ensure$capitalized_name$IsMutable();\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700699 " $name$_.add(value.toStringUtf8());\n"
Bo Yang5db21732015-05-21 14:28:59 -0700700 "}\n");
701}
702
703void RepeatedImmutableStringFieldLiteGenerator::
704GenerateBuilderMembers(io::Printer* printer) const {
705 WriteFieldDocComment(printer, descriptor_);
706 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700707 "$deprecation$public java.util.List<String>\n"
Bo Yang5db21732015-05-21 14:28:59 -0700708 " get$capitalized_name$List() {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700709 " return java.util.Collections.unmodifiableList(\n"
710 " instance.get$capitalized_name$List());\n"
Bo Yang5db21732015-05-21 14:28:59 -0700711 "}\n");
712 WriteFieldDocComment(printer, descriptor_);
713 printer->Print(variables_,
714 "$deprecation$public int get$capitalized_name$Count() {\n"
715 " return instance.get$capitalized_name$Count();\n"
716 "}\n");
717 WriteFieldDocComment(printer, descriptor_);
718 printer->Print(variables_,
719 "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
720 " return instance.get$capitalized_name$(index);\n"
721 "}\n");
722 WriteFieldDocComment(printer, descriptor_);
723 printer->Print(variables_,
724 "$deprecation$public com.google.protobuf.ByteString\n"
725 " get$capitalized_name$Bytes(int index) {\n"
726 " return instance.get$capitalized_name$Bytes(index);\n"
727 "}\n");
728 WriteFieldDocComment(printer, descriptor_);
729 printer->Print(variables_,
730 "$deprecation$public Builder set$capitalized_name$(\n"
731 " int index, java.lang.String value) {\n"
732 " copyOnWrite();\n"
733 " instance.set$capitalized_name$(index, value);\n"
734 " return this;\n"
735 "}\n");
736 WriteFieldDocComment(printer, descriptor_);
737 printer->Print(variables_,
738 "$deprecation$public Builder add$capitalized_name$(\n"
739 " java.lang.String value) {\n"
740 " copyOnWrite();\n"
741 " instance.add$capitalized_name$(value);\n"
742 " return this;\n"
743 "}\n");
744 WriteFieldDocComment(printer, descriptor_);
745 printer->Print(variables_,
746 "$deprecation$public Builder addAll$capitalized_name$(\n"
747 " java.lang.Iterable<java.lang.String> values) {\n"
748 " copyOnWrite();\n"
749 " instance.addAll$capitalized_name$(values);\n"
750 " return this;\n"
751 "}\n");
752 WriteFieldDocComment(printer, descriptor_);
753 printer->Print(variables_,
754 "$deprecation$public Builder clear$capitalized_name$() {\n"
755 " copyOnWrite();\n"
756 " instance.clear$capitalized_name$();\n"
757 " return this;\n"
758 "}\n");
759
760 WriteFieldDocComment(printer, descriptor_);
761 printer->Print(variables_,
762 "$deprecation$public Builder add$capitalized_name$Bytes(\n"
763 " com.google.protobuf.ByteString value) {\n"
764 " copyOnWrite();\n"
765 " instance.add$capitalized_name$Bytes(value);\n"
766 " return this;\n"
767 "}\n");
768}
769
770void RepeatedImmutableStringFieldLiteGenerator::
771GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
772 // noop for strings
773}
774
775void RepeatedImmutableStringFieldLiteGenerator::
776GenerateInitializationCode(io::Printer* printer) const {
777 printer->Print(variables_, "$name$_ = $empty_list$;\n");
778}
779
780void RepeatedImmutableStringFieldLiteGenerator::
781GenerateMergingCode(io::Printer* printer) const {
782 // The code below does two optimizations:
783 // 1. If the other list is empty, there's nothing to do. This ensures we
784 // don't allocate a new array if we already have an immutable one.
785 // 2. If the other list is non-empty and our current list is empty, we can
786 // reuse the other list which is guaranteed to be immutable.
787 printer->Print(variables_,
788 "if (!other.$name$_.isEmpty()) {\n"
789 " if ($name$_.isEmpty()) {\n"
790 " $name$_ = other.$name$_;\n"
791 " } else {\n"
792 " ensure$capitalized_name$IsMutable();\n"
793 " $name$_.addAll(other.$name$_);\n"
794 " }\n"
795 " $on_changed$\n"
796 "}\n");
797}
798
799void RepeatedImmutableStringFieldLiteGenerator::
800GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
801 printer->Print(variables_,
802 "$name$_.makeImmutable();\n");
803}
804
805void RepeatedImmutableStringFieldLiteGenerator::
806GenerateParsingCode(io::Printer* printer) const {
807 if (CheckUtf8(descriptor_)) {
808 printer->Print(variables_,
809 "String s = input.readStringRequireUtf8();\n");
Feng Xiaoeee38b02015-08-22 18:25:48 -0700810 } else {
Bo Yang5db21732015-05-21 14:28:59 -0700811 // Lite runtime should attempt to reduce allocations by attempting to
812 // construct the string directly from the input stream buffer. This avoids
813 // spurious intermediary ByteString allocations, cutting overall allocations
814 // in half.
815 printer->Print(variables_,
816 "String s = input.readString();\n");
Bo Yang5db21732015-05-21 14:28:59 -0700817 }
818 printer->Print(variables_,
819 "if (!$is_mutable$) {\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700820 " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
Bo Yang5db21732015-05-21 14:28:59 -0700821 "}\n");
822 if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
823 printer->Print(variables_,
824 "$name$_.add(s);\n");
825 } else {
826 printer->Print(variables_,
827 "$name$_.add(bs);\n");
828 }
829}
830
831void RepeatedImmutableStringFieldLiteGenerator::
Bo Yang5db21732015-05-21 14:28:59 -0700832GenerateParsingDoneCode(io::Printer* printer) const {
833 printer->Print(variables_,
834 "if ($is_mutable$) {\n"
835 " $name$_.makeImmutable();\n"
836 "}\n");
837}
838
839void RepeatedImmutableStringFieldLiteGenerator::
840GenerateSerializationCode(io::Printer* printer) const {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700841 // Lite runtime should reduce allocations by serializing the string directly.
842 // This avoids spurious intermediary ByteString allocations, cutting overall
843 // allocations in half.
Feng Xiaoe841bac2015-12-11 17:09:20 -0800844 printer->Print(variables_,
845 "for (int i = 0; i < $name$_.size(); i++) {\n"
846 " output.writeString($number$, $name$_.get(i));\n"
847 "}\n");
Bo Yang5db21732015-05-21 14:28:59 -0700848}
849
850void RepeatedImmutableStringFieldLiteGenerator::
851GenerateSerializedSizeCode(io::Printer* printer) const {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700852 // Lite runtime should reduce allocations by computing on the string directly.
853 // This avoids spurious intermediary ByteString allocations, cutting overall
854 // allocations in half.
Bo Yang5db21732015-05-21 14:28:59 -0700855 printer->Print(variables_,
856 "{\n"
857 " int dataSize = 0;\n");
858 printer->Indent();
859
860 printer->Print(variables_,
861 "for (int i = 0; i < $name$_.size(); i++) {\n"
862 " dataSize += com.google.protobuf.CodedOutputStream\n"
Feng Xiaoeee38b02015-08-22 18:25:48 -0700863 " .computeStringSizeNoTag($name$_.get(i));\n"
Bo Yang5db21732015-05-21 14:28:59 -0700864 "}\n");
865
866 printer->Print(
867 "size += dataSize;\n");
868
Bo Yang5db21732015-05-21 14:28:59 -0700869
Feng Xiaoe841bac2015-12-11 17:09:20 -0800870 printer->Print(variables_,
871 "size += $tag_size$ * get$capitalized_name$List().size();\n");
Bo Yang5db21732015-05-21 14:28:59 -0700872
873 printer->Outdent();
874 printer->Print("}\n");
875}
876
877void RepeatedImmutableStringFieldLiteGenerator::
878GenerateEqualsCode(io::Printer* printer) const {
879 printer->Print(variables_,
880 "result = result && get$capitalized_name$List()\n"
881 " .equals(other.get$capitalized_name$List());\n");
882}
883
884void RepeatedImmutableStringFieldLiteGenerator::
885GenerateHashCode(io::Printer* printer) const {
886 printer->Print(variables_,
887 "if (get$capitalized_name$Count() > 0) {\n"
888 " hash = (37 * hash) + $constant_name$;\n"
889 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
890 "}\n");
891}
892
893string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
894 return "String";
895}
896
897} // namespace java
898} // namespace compiler
899} // namespace protobuf
900} // namespace google