• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,map<string,string> * variables)60 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   SetCommonFieldVariables(descriptor, info, variables);
67 
68   (*variables)["empty_list"] =
69       "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
70 
71   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
72   (*variables)["default_init"] =
73       "= " + ImmutableDefaultValue(descriptor, name_resolver);
74   (*variables)["capitalized_type"] = "String";
75   (*variables)["tag"] = 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 
88   if (SupportFieldPresence(descriptor->file())) {
89     // For singular messages and builders, one bit is used for the hasField bit.
90     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
91 
92     // Note that these have a trailing ";".
93     (*variables)["set_has_field_bit_message"] =
94         GenerateSetBit(messageBitIndex) + ";";
95     (*variables)["clear_has_field_bit_message"] =
96         GenerateClearBit(messageBitIndex) + ";";
97 
98     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
99   } else {
100     (*variables)["set_has_field_bit_message"] = "";
101     (*variables)["clear_has_field_bit_message"] = "";
102 
103     (*variables)["is_field_present_message"] =
104         "!" + (*variables)["name"] + "_.isEmpty()";
105   }
106 
107   // For repeated builders, the underlying list tracks mutability state.
108   (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
109 
110   (*variables)["get_has_field_bit_from_local"] =
111       GenerateGetBitFromLocal(builderBitIndex);
112   (*variables)["set_has_field_bit_to_local"] =
113       GenerateSetBitToLocal(messageBitIndex);
114 }
115 
116 }  // namespace
117 
118 // ===================================================================
119 
120 ImmutableStringFieldLiteGenerator::
ImmutableStringFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)121 ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
122                               int messageBitIndex,
123                               int builderBitIndex,
124                               Context* context)
125   : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
126     builderBitIndex_(builderBitIndex), context_(context),
127     name_resolver_(context->GetNameResolver()) {
128   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
129                         context->GetFieldGeneratorInfo(descriptor),
130                         name_resolver_, &variables_);
131 }
132 
~ImmutableStringFieldLiteGenerator()133 ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
134 
GetNumBitsForMessage() const135 int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
136   return 1;
137 }
138 
GetNumBitsForBuilder() const139 int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
140   return 0;
141 }
142 
143 // A note about how strings are handled. In the SPEED and CODE_SIZE runtimes,
144 // strings are not stored as java.lang.String in the Message because of two
145 // issues:
146 //
147 //  1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
148 //     strings, but rather fields that were raw bytes incorrectly marked
149 //     as strings in the proto file. This is common because in the proto1
150 //     syntax, string was the way to indicate bytes and C++ engineers can
151 //     easily make this mistake without affecting the C++ API. By converting to
152 //     strings immediately, some java code might corrupt these byte arrays as
153 //     it passes through a java server even if the field was never accessed by
154 //     application code.
155 //
156 //  2. There's a performance hit to converting between bytes and strings and
157 //     it many cases, the field is never even read by the application code. This
158 //     avoids unnecessary conversions in the common use cases.
159 //
160 // In the LITE_RUNTIME, we store strings as java.lang.String because we assume
161 // that the users of this runtime are not subject to proto1 constraints and are
162 // running code on devices that are user facing. That is, the developers are
163 // properly incentivized to only fetch the data they need to read and wish to
164 // reduce the number of allocations incurred when running on a user's device.
165 
166 // TODO(dweis): Consider dropping all of the *Bytes() methods. They really
167 //     shouldn't be necessary or used on devices.
168 void ImmutableStringFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const169 GenerateInterfaceMembers(io::Printer* printer) const {
170   if (SupportFieldPresence(descriptor_->file())) {
171     WriteFieldDocComment(printer, descriptor_);
172     printer->Print(variables_,
173       "$deprecation$boolean has$capitalized_name$();\n");
174   }
175   WriteFieldDocComment(printer, descriptor_);
176   printer->Print(variables_,
177     "$deprecation$java.lang.String get$capitalized_name$();\n");
178   WriteFieldDocComment(printer, descriptor_);
179   printer->Print(variables_,
180     "$deprecation$com.google.protobuf.ByteString\n"
181     "    get$capitalized_name$Bytes();\n");
182 }
183 
184 void ImmutableStringFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const185 GenerateMembers(io::Printer* printer) const {
186   printer->Print(variables_,
187     "private java.lang.String $name$_;\n");
188   PrintExtraFieldInfo(variables_, printer);
189 
190   if (SupportFieldPresence(descriptor_->file())) {
191     WriteFieldDocComment(printer, descriptor_);
192     printer->Print(variables_,
193       "$deprecation$public boolean has$capitalized_name$() {\n"
194       "  return $get_has_field_bit_message$;\n"
195       "}\n");
196   }
197 
198   WriteFieldDocComment(printer, descriptor_);
199   printer->Print(variables_,
200     "$deprecation$public java.lang.String get$capitalized_name$() {\n"
201     "  return $name$_;\n"
202     "}\n");
203   WriteFieldDocComment(printer, descriptor_);
204   printer->Print(variables_,
205     "$deprecation$public com.google.protobuf.ByteString\n"
206     "    get$capitalized_name$Bytes() {\n"
207     "  return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
208     "}\n");
209 
210   WriteFieldDocComment(printer, descriptor_);
211   printer->Print(variables_,
212     "private void set$capitalized_name$(\n"
213     "    java.lang.String value) {\n"
214     "$null_check$"
215     "  $set_has_field_bit_message$\n"
216     "  $name$_ = value;\n"
217     "}\n");
218   WriteFieldDocComment(printer, descriptor_);
219   printer->Print(variables_,
220     "private void clear$capitalized_name$() {\n"
221     "  $clear_has_field_bit_message$\n"
222     // The default value is not a simple literal so we want to avoid executing
223     // it multiple times.  Instead, get the default out of the default instance.
224     "  $name$_ = getDefaultInstance().get$capitalized_name$();\n"
225     "}\n");
226 
227   WriteFieldDocComment(printer, descriptor_);
228   printer->Print(variables_,
229     "private void set$capitalized_name$Bytes(\n"
230     "    com.google.protobuf.ByteString value) {\n"
231     "$null_check$");
232   if (CheckUtf8(descriptor_)) {
233     printer->Print(variables_,
234       "  checkByteStringIsUtf8(value);\n");
235   }
236   printer->Print(variables_,
237     "  $set_has_field_bit_message$\n"
238     "  $name$_ = value.toStringUtf8();\n"
239     "}\n");
240 }
241 
242 void ImmutableStringFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const243 GenerateBuilderMembers(io::Printer* printer) const {
244   if (SupportFieldPresence(descriptor_->file())) {
245     WriteFieldDocComment(printer, descriptor_);
246     printer->Print(variables_,
247       "$deprecation$public boolean has$capitalized_name$() {\n"
248       "  return instance.has$capitalized_name$();\n"
249       "}\n");
250   }
251 
252   WriteFieldDocComment(printer, descriptor_);
253   printer->Print(variables_,
254     "$deprecation$public java.lang.String get$capitalized_name$() {\n"
255     "  return instance.get$capitalized_name$();\n"
256     "}\n");
257 
258   WriteFieldDocComment(printer, descriptor_);
259   printer->Print(variables_,
260     "$deprecation$public com.google.protobuf.ByteString\n"
261     "    get$capitalized_name$Bytes() {\n"
262     "  return instance.get$capitalized_name$Bytes();\n"
263     "}\n");
264 
265   WriteFieldDocComment(printer, descriptor_);
266   printer->Print(variables_,
267     "$deprecation$public Builder set$capitalized_name$(\n"
268     "    java.lang.String value) {\n"
269     "  copyOnWrite();\n"
270     "  instance.set$capitalized_name$(value);\n"
271     "  return this;\n"
272     "}\n");
273   WriteFieldDocComment(printer, descriptor_);
274   printer->Print(variables_,
275     "$deprecation$public Builder clear$capitalized_name$() {\n"
276     "  copyOnWrite();\n"
277     "  instance.clear$capitalized_name$();\n"
278     "  return this;\n"
279     "}\n");
280 
281   WriteFieldDocComment(printer, descriptor_);
282   printer->Print(variables_,
283     "$deprecation$public Builder set$capitalized_name$Bytes(\n"
284     "    com.google.protobuf.ByteString value) {\n"
285     "  copyOnWrite();\n"
286     "  instance.set$capitalized_name$Bytes(value);\n"
287     "  return this;\n"
288     "}\n");
289 }
290 
291 void ImmutableStringFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const292 GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
293   // noop for strings
294 }
295 
296 void ImmutableStringFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const297 GenerateInitializationCode(io::Printer* printer) const {
298   printer->Print(variables_, "$name$_ = $default$;\n");
299 }
300 
301 void ImmutableStringFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const302 GenerateVisitCode(io::Printer* printer) const {
303   if (SupportFieldPresence(descriptor_->file())) {
304     printer->Print(variables_,
305       "$name$_ = visitor.visitString(\n"
306       "    has$capitalized_name$(), $name$_,\n"
307       "    other.has$capitalized_name$(), other.$name$_);\n");
308   } else {
309     printer->Print(variables_,
310       "$name$_ = visitor.visitString(!$name$_.isEmpty(), $name$_,\n"
311       "    !other.$name$_.isEmpty(), other.$name$_);\n");
312   }
313 }
314 
315 void ImmutableStringFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const316 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
317   // noop for scalars
318 }
319 
320 void ImmutableStringFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const321 GenerateParsingCode(io::Printer* printer) const {
322   if (CheckUtf8(descriptor_)) {
323     printer->Print(variables_,
324       "String s = input.readStringRequireUtf8();\n"
325       "$set_has_field_bit_message$\n"
326       "$name$_ = s;\n");
327   } else {
328     // Lite runtime should attempt to reduce allocations by attempting to
329     // construct the string directly from the input stream buffer. This avoids
330     // spurious intermediary ByteString allocations, cutting overall allocations
331     // in half.
332     printer->Print(variables_,
333       "String s = input.readString();\n"
334       "$set_has_field_bit_message$\n"
335       "$name$_ = s;\n");
336   }
337 }
338 
339 void ImmutableStringFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const340 GenerateParsingDoneCode(io::Printer* printer) const {
341   // noop for strings
342 }
343 
344 void ImmutableStringFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const345 GenerateSerializationCode(io::Printer* printer) const {
346   // Lite runtime should reduce allocations by serializing the string directly.
347   // This avoids spurious intermediary ByteString allocations, cutting overall
348   // allocations in half.
349   printer->Print(variables_,
350     "if ($is_field_present_message$) {\n"
351     "  output.writeString($number$, get$capitalized_name$());\n"
352     "}\n");
353 }
354 
355 void ImmutableStringFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const356 GenerateSerializedSizeCode(io::Printer* printer) const {
357   // Lite runtime should reduce allocations by computing on the string directly.
358   // This avoids spurious intermediary ByteString allocations, cutting overall
359   // allocations in half.
360   printer->Print(variables_,
361     "if ($is_field_present_message$) {\n"
362     "  size += com.google.protobuf.CodedOutputStream\n"
363     "    .computeStringSize($number$, get$capitalized_name$());\n"
364     "}\n");
365 }
366 
367 void ImmutableStringFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const368 GenerateEqualsCode(io::Printer* printer) const {
369   printer->Print(variables_,
370     "result = result && get$capitalized_name$()\n"
371     "    .equals(other.get$capitalized_name$());\n");
372 }
373 
374 void ImmutableStringFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const375 GenerateHashCode(io::Printer* printer) const {
376   printer->Print(variables_,
377     "hash = (37 * hash) + $constant_name$;\n");
378   printer->Print(variables_,
379     "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
380 }
381 
GetBoxedType() const382 string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
383   return "java.lang.String";
384 }
385 
386 // ===================================================================
387 
388 ImmutableStringOneofFieldLiteGenerator::
ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)389 ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
390                                    int messageBitIndex,
391                                    int builderBitIndex,
392                                    Context* context)
393     : ImmutableStringFieldLiteGenerator(
394           descriptor, messageBitIndex, builderBitIndex, context) {
395   const OneofGeneratorInfo* info =
396       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
397   SetCommonOneofVariables(descriptor, info, &variables_);
398 }
399 
400 ImmutableStringOneofFieldLiteGenerator::
~ImmutableStringOneofFieldLiteGenerator()401 ~ImmutableStringOneofFieldLiteGenerator() {}
402 
403 void ImmutableStringOneofFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const404 GenerateMembers(io::Printer* printer) const {
405   PrintExtraFieldInfo(variables_, printer);
406 
407   if (SupportFieldPresence(descriptor_->file())) {
408   WriteFieldDocComment(printer, descriptor_);
409   printer->Print(variables_,
410     "$deprecation$public boolean has$capitalized_name$() {\n"
411     "  return $has_oneof_case_message$;\n"
412     "}\n");
413   }
414 
415   WriteFieldDocComment(printer, descriptor_);
416   printer->Print(variables_,
417     "$deprecation$public java.lang.String get$capitalized_name$() {\n"
418     "  java.lang.String ref $default_init$;\n"
419     "  if ($has_oneof_case_message$) {\n"
420     "    ref = (java.lang.String) $oneof_name$_;\n"
421     "  }\n"
422     "  return ref;\n"
423     "}\n");
424   WriteFieldDocComment(printer, descriptor_);
425 
426   printer->Print(variables_,
427     "$deprecation$public com.google.protobuf.ByteString\n"
428     "    get$capitalized_name$Bytes() {\n"
429     "  java.lang.String ref $default_init$;\n"
430     "  if ($has_oneof_case_message$) {\n"
431     "    ref = (java.lang.String) $oneof_name$_;\n"
432     "  }\n"
433     "  return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
434     "}\n");
435 
436   WriteFieldDocComment(printer, descriptor_);
437   printer->Print(variables_,
438     "private void set$capitalized_name$(\n"
439     "    java.lang.String value) {\n"
440     "$null_check$"
441     "  $set_oneof_case_message$;\n"
442     "  $oneof_name$_ = value;\n"
443     "}\n");
444   WriteFieldDocComment(printer, descriptor_);
445   printer->Print(variables_,
446     "private void clear$capitalized_name$() {\n"
447     "  if ($has_oneof_case_message$) {\n"
448     "    $clear_oneof_case_message$;\n"
449     "    $oneof_name$_ = null;\n"
450     "  }\n"
451     "}\n");
452 
453   WriteFieldDocComment(printer, descriptor_);
454   printer->Print(variables_,
455     "private void set$capitalized_name$Bytes(\n"
456     "    com.google.protobuf.ByteString value) {\n"
457     "$null_check$");
458   if (CheckUtf8(descriptor_)) {
459     printer->Print(variables_,
460       "  checkByteStringIsUtf8(value);\n");
461   }
462   printer->Print(variables_,
463     "  $set_oneof_case_message$;\n"
464     "  $oneof_name$_ = value.toStringUtf8();\n"
465     "}\n");
466 }
467 
468 void ImmutableStringOneofFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const469 GenerateBuilderMembers(io::Printer* printer) const {
470   if (SupportFieldPresence(descriptor_->file())) {
471     WriteFieldDocComment(printer, descriptor_);
472     printer->Print(variables_,
473       "$deprecation$public boolean has$capitalized_name$() {\n"
474       "  return instance.has$capitalized_name$();\n"
475       "}\n");
476   }
477 
478   WriteFieldDocComment(printer, descriptor_);
479   printer->Print(variables_,
480     "$deprecation$public java.lang.String get$capitalized_name$() {\n"
481     "  return instance.get$capitalized_name$();\n"
482     "}\n");
483 
484   WriteFieldDocComment(printer, descriptor_);
485   printer->Print(variables_,
486     "$deprecation$public com.google.protobuf.ByteString\n"
487     "    get$capitalized_name$Bytes() {\n"
488     "  return instance.get$capitalized_name$Bytes();\n"
489     "}\n");
490 
491   WriteFieldDocComment(printer, descriptor_);
492   printer->Print(variables_,
493     "$deprecation$public Builder set$capitalized_name$(\n"
494     "    java.lang.String value) {\n"
495     "  copyOnWrite();\n"
496     "  instance.set$capitalized_name$(value);\n"
497     "  return this;\n"
498     "}\n");
499   WriteFieldDocComment(printer, descriptor_);
500   printer->Print(variables_,
501     "$deprecation$public Builder clear$capitalized_name$() {\n"
502     "  copyOnWrite();\n"
503     "  instance.clear$capitalized_name$();\n"
504     "  return this;\n"
505     "}\n");
506 
507   WriteFieldDocComment(printer, descriptor_);
508   printer->Print(variables_,
509     "$deprecation$public Builder set$capitalized_name$Bytes(\n"
510     "    com.google.protobuf.ByteString value) {\n"
511     "  copyOnWrite();\n"
512     "  instance.set$capitalized_name$Bytes(value);\n"
513     "  return this;\n"
514     "}\n");
515 }
516 
517 void ImmutableStringOneofFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const518 GenerateVisitCode(io::Printer* printer) const {
519   printer->Print(variables_,
520     "$oneof_name$_ = visitor.visitOneofString(\n"
521     "   $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
522 }
523 
524 void ImmutableStringOneofFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const525 GenerateParsingCode(io::Printer* printer) const {
526   if (CheckUtf8(descriptor_)) {
527     printer->Print(variables_,
528       "String s = input.readStringRequireUtf8();\n"
529       "$set_oneof_case_message$;\n"
530       "$oneof_name$_ = s;\n");
531   } else {
532     // Lite runtime should attempt to reduce allocations by attempting to
533     // construct the string directly from the input stream buffer. This avoids
534     // spurious intermediary ByteString allocations, cutting overall allocations
535     // in half.
536     printer->Print(variables_,
537       "String s = input.readString();\n"
538       "$set_oneof_case_message$;\n"
539       "$oneof_name$_ = s;\n");
540   }
541 }
542 
543 void ImmutableStringOneofFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const544 GenerateSerializationCode(io::Printer* printer) const {
545   // Lite runtime should reduce allocations by serializing the string directly.
546   // This avoids spurious intermediary ByteString allocations, cutting overall
547   // allocations in half.
548   printer->Print(variables_,
549     "if ($has_oneof_case_message$) {\n"
550     "  output.writeString($number$, get$capitalized_name$());\n"
551     "}\n");
552 }
553 
554 void ImmutableStringOneofFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const555 GenerateSerializedSizeCode(io::Printer* printer) const {
556   // Lite runtime should reduce allocations by computing on 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     "  size += com.google.protobuf.CodedOutputStream\n"
562     "    .computeStringSize($number$, get$capitalized_name$());\n"
563     "}\n");
564 }
565 
566 // ===================================================================
567 
568 RepeatedImmutableStringFieldLiteGenerator::
RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)569 RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
570                                       int messageBitIndex,
571                                       int builderBitIndex,
572                                       Context* context)
573   : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
574     builderBitIndex_(builderBitIndex), context_(context),
575     name_resolver_(context->GetNameResolver()) {
576   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
577                         context->GetFieldGeneratorInfo(descriptor),
578                         name_resolver_, &variables_);
579 }
580 
581 RepeatedImmutableStringFieldLiteGenerator::
~RepeatedImmutableStringFieldLiteGenerator()582 ~RepeatedImmutableStringFieldLiteGenerator() {}
583 
GetNumBitsForMessage() const584 int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
585   return 0;
586 }
587 
GetNumBitsForBuilder() const588 int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
589   return 0;
590 }
591 
592 void RepeatedImmutableStringFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const593 GenerateInterfaceMembers(io::Printer* printer) const {
594   WriteFieldDocComment(printer, descriptor_);
595   printer->Print(variables_,
596     "$deprecation$java.util.List<String>\n"
597     "    get$capitalized_name$List();\n");
598   WriteFieldDocComment(printer, descriptor_);
599   printer->Print(variables_,
600     "$deprecation$int get$capitalized_name$Count();\n");
601   WriteFieldDocComment(printer, descriptor_);
602   printer->Print(variables_,
603     "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
604   WriteFieldDocComment(printer, descriptor_);
605   printer->Print(variables_,
606     "$deprecation$com.google.protobuf.ByteString\n"
607     "    get$capitalized_name$Bytes(int index);\n");
608 }
609 
610 
611 void RepeatedImmutableStringFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const612 GenerateMembers(io::Printer* printer) const {
613   printer->Print(variables_,
614     "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n");
615   PrintExtraFieldInfo(variables_, printer);
616   WriteFieldDocComment(printer, descriptor_);
617   printer->Print(variables_,
618     "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n"
619     "  return $name$_;\n"   // note:  unmodifiable list
620     "}\n");
621   WriteFieldDocComment(printer, descriptor_);
622   printer->Print(variables_,
623     "$deprecation$public int get$capitalized_name$Count() {\n"
624     "  return $name$_.size();\n"
625     "}\n");
626   WriteFieldDocComment(printer, descriptor_);
627   printer->Print(variables_,
628     "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
629     "  return $name$_.get(index);\n"
630     "}\n");
631   WriteFieldDocComment(printer, descriptor_);
632   printer->Print(variables_,
633     "$deprecation$public com.google.protobuf.ByteString\n"
634     "    get$capitalized_name$Bytes(int index) {\n"
635     "  return com.google.protobuf.ByteString.copyFromUtf8(\n"
636     "      $name$_.get(index));\n"
637     "}\n");
638 
639   printer->Print(variables_,
640     "private void ensure$capitalized_name$IsMutable() {\n"
641     "  if (!$is_mutable$) {\n"
642     "    $name$_ =\n"
643     "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
644     "   }\n"
645     "}\n");
646 
647   WriteFieldDocComment(printer, descriptor_);
648   printer->Print(variables_,
649     "private void set$capitalized_name$(\n"
650     "    int index, java.lang.String value) {\n"
651     "$null_check$"
652     "  ensure$capitalized_name$IsMutable();\n"
653     "  $name$_.set(index, value);\n"
654     "}\n");
655   WriteFieldDocComment(printer, descriptor_);
656   printer->Print(variables_,
657     "private void add$capitalized_name$(\n"
658     "    java.lang.String value) {\n"
659     "$null_check$"
660     "  ensure$capitalized_name$IsMutable();\n"
661     "  $name$_.add(value);\n"
662     "}\n");
663   WriteFieldDocComment(printer, descriptor_);
664   printer->Print(variables_,
665     "private void addAll$capitalized_name$(\n"
666     "    java.lang.Iterable<java.lang.String> values) {\n"
667     "  ensure$capitalized_name$IsMutable();\n"
668     "  com.google.protobuf.AbstractMessageLite.addAll(\n"
669     "      values, $name$_);\n"
670     "}\n");
671   WriteFieldDocComment(printer, descriptor_);
672   printer->Print(variables_,
673     "private void clear$capitalized_name$() {\n"
674     "  $name$_ = $empty_list$;\n"
675     "}\n");
676 
677   WriteFieldDocComment(printer, descriptor_);
678   printer->Print(variables_,
679     "private void add$capitalized_name$Bytes(\n"
680     "    com.google.protobuf.ByteString value) {\n"
681     "$null_check$");
682   if (CheckUtf8(descriptor_)) {
683     printer->Print(variables_,
684       "  checkByteStringIsUtf8(value);\n");
685   }
686   printer->Print(variables_,
687     "  ensure$capitalized_name$IsMutable();\n"
688     "  $name$_.add(value.toStringUtf8());\n"
689     "}\n");
690 }
691 
692 void RepeatedImmutableStringFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const693 GenerateBuilderMembers(io::Printer* printer) const {
694   WriteFieldDocComment(printer, descriptor_);
695   printer->Print(variables_,
696     "$deprecation$public java.util.List<String>\n"
697     "    get$capitalized_name$List() {\n"
698     "  return java.util.Collections.unmodifiableList(\n"
699     "      instance.get$capitalized_name$List());\n"
700     "}\n");
701   WriteFieldDocComment(printer, descriptor_);
702   printer->Print(variables_,
703     "$deprecation$public int get$capitalized_name$Count() {\n"
704     "  return instance.get$capitalized_name$Count();\n"
705     "}\n");
706   WriteFieldDocComment(printer, descriptor_);
707   printer->Print(variables_,
708     "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
709     "  return instance.get$capitalized_name$(index);\n"
710     "}\n");
711   WriteFieldDocComment(printer, descriptor_);
712   printer->Print(variables_,
713     "$deprecation$public com.google.protobuf.ByteString\n"
714     "    get$capitalized_name$Bytes(int index) {\n"
715     "  return instance.get$capitalized_name$Bytes(index);\n"
716     "}\n");
717   WriteFieldDocComment(printer, descriptor_);
718   printer->Print(variables_,
719     "$deprecation$public Builder set$capitalized_name$(\n"
720     "    int index, java.lang.String value) {\n"
721     "  copyOnWrite();\n"
722     "  instance.set$capitalized_name$(index, value);\n"
723     "  return this;\n"
724     "}\n");
725   WriteFieldDocComment(printer, descriptor_);
726   printer->Print(variables_,
727     "$deprecation$public Builder add$capitalized_name$(\n"
728     "    java.lang.String value) {\n"
729     "  copyOnWrite();\n"
730     "  instance.add$capitalized_name$(value);\n"
731     "  return this;\n"
732     "}\n");
733   WriteFieldDocComment(printer, descriptor_);
734   printer->Print(variables_,
735     "$deprecation$public Builder addAll$capitalized_name$(\n"
736     "    java.lang.Iterable<java.lang.String> values) {\n"
737     "  copyOnWrite();\n"
738     "  instance.addAll$capitalized_name$(values);\n"
739     "  return this;\n"
740     "}\n");
741   WriteFieldDocComment(printer, descriptor_);
742   printer->Print(variables_,
743     "$deprecation$public Builder clear$capitalized_name$() {\n"
744     "  copyOnWrite();\n"
745     "  instance.clear$capitalized_name$();\n"
746     "  return this;\n"
747     "}\n");
748 
749   WriteFieldDocComment(printer, descriptor_);
750   printer->Print(variables_,
751     "$deprecation$public Builder add$capitalized_name$Bytes(\n"
752     "    com.google.protobuf.ByteString value) {\n"
753     "  copyOnWrite();\n"
754     "  instance.add$capitalized_name$Bytes(value);\n"
755     "  return this;\n"
756     "}\n");
757 }
758 
759 void RepeatedImmutableStringFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const760 GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
761   // noop for strings
762 }
763 
764 void RepeatedImmutableStringFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const765 GenerateInitializationCode(io::Printer* printer) const {
766   printer->Print(variables_, "$name$_ = $empty_list$;\n");
767 }
768 
769 void RepeatedImmutableStringFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const770 GenerateVisitCode(io::Printer* printer) const {
771   printer->Print(variables_,
772       "$name$_= visitor.visitList($name$_, other.$name$_);\n");
773 }
774 
775 void RepeatedImmutableStringFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const776 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
777   printer->Print(variables_,
778     "$name$_.makeImmutable();\n");
779 }
780 
781 void RepeatedImmutableStringFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const782 GenerateParsingCode(io::Printer* printer) const {
783   if (CheckUtf8(descriptor_)) {
784     printer->Print(variables_,
785     "String s = input.readStringRequireUtf8();\n");
786   } else {
787     // Lite runtime should attempt to reduce allocations by attempting to
788     // construct the string directly from the input stream buffer. This avoids
789     // spurious intermediary ByteString allocations, cutting overall allocations
790     // in half.
791     printer->Print(variables_,
792     "String s = input.readString();\n");
793   }
794   printer->Print(variables_,
795     "if (!$is_mutable$) {\n"
796     "  $name$_ =\n"
797     "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
798     "}\n");
799   printer->Print(variables_,
800     "$name$_.add(s);\n");
801 }
802 
803 void RepeatedImmutableStringFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const804 GenerateParsingDoneCode(io::Printer* printer) const {
805   printer->Print(variables_,
806     "if ($is_mutable$) {\n"
807     "  $name$_.makeImmutable();\n"
808     "}\n");
809 }
810 
811 void RepeatedImmutableStringFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const812 GenerateSerializationCode(io::Printer* printer) const {
813   // Lite runtime should reduce allocations by serializing the string directly.
814   // This avoids spurious intermediary ByteString allocations, cutting overall
815   // allocations in half.
816   printer->Print(variables_,
817     "for (int i = 0; i < $name$_.size(); i++) {\n"
818     "  output.writeString($number$, $name$_.get(i));\n"
819     "}\n");
820 }
821 
822 void RepeatedImmutableStringFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const823 GenerateSerializedSizeCode(io::Printer* printer) const {
824   // Lite runtime should reduce allocations by computing on the string directly.
825   // This avoids spurious intermediary ByteString allocations, cutting overall
826   // allocations in half.
827   printer->Print(variables_,
828     "{\n"
829     "  int dataSize = 0;\n");
830   printer->Indent();
831 
832   printer->Print(variables_,
833     "for (int i = 0; i < $name$_.size(); i++) {\n"
834     "  dataSize += com.google.protobuf.CodedOutputStream\n"
835     "    .computeStringSizeNoTag($name$_.get(i));\n"
836     "}\n");
837 
838   printer->Print(
839       "size += dataSize;\n");
840 
841 
842   printer->Print(variables_,
843     "size += $tag_size$ * get$capitalized_name$List().size();\n");
844 
845   printer->Outdent();
846   printer->Print("}\n");
847 }
848 
849 void RepeatedImmutableStringFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const850 GenerateEqualsCode(io::Printer* printer) const {
851   printer->Print(variables_,
852     "result = result && get$capitalized_name$List()\n"
853     "    .equals(other.get$capitalized_name$List());\n");
854 }
855 
856 void RepeatedImmutableStringFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const857 GenerateHashCode(io::Printer* printer) const {
858   printer->Print(variables_,
859     "if (get$capitalized_name$Count() > 0) {\n"
860     "  hash = (37 * hash) + $constant_name$;\n"
861     "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
862     "}\n");
863 }
864 
GetBoxedType() const865 string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
866   return "String";
867 }
868 
869 }  // namespace java
870 }  // namespace compiler
871 }  // namespace protobuf
872 }  // namespace google
873