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
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
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
120ImmutableStringFieldLiteGenerator::
121ImmutableStringFieldLiteGenerator(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
133ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
134
135int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
136  return 1;
137}
138
139int 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.
168void ImmutableStringFieldLiteGenerator::
169GenerateInterfaceMembers(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
184void ImmutableStringFieldLiteGenerator::
185GenerateMembers(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
242void ImmutableStringFieldLiteGenerator::
243GenerateBuilderMembers(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
291void ImmutableStringFieldLiteGenerator::
292GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
293  // noop for strings
294}
295
296void ImmutableStringFieldLiteGenerator::
297GenerateInitializationCode(io::Printer* printer) const {
298  printer->Print(variables_, "$name$_ = $default$;\n");
299}
300
301void ImmutableStringFieldLiteGenerator::
302GenerateVisitCode(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
315void ImmutableStringFieldLiteGenerator::
316GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
317  // noop for scalars
318}
319
320void ImmutableStringFieldLiteGenerator::
321GenerateParsingCode(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
339void ImmutableStringFieldLiteGenerator::
340GenerateParsingDoneCode(io::Printer* printer) const {
341  // noop for strings
342}
343
344void ImmutableStringFieldLiteGenerator::
345GenerateSerializationCode(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
355void ImmutableStringFieldLiteGenerator::
356GenerateSerializedSizeCode(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
367void ImmutableStringFieldLiteGenerator::
368GenerateEqualsCode(io::Printer* printer) const {
369  printer->Print(variables_,
370    "result = result && get$capitalized_name$()\n"
371    "    .equals(other.get$capitalized_name$());\n");
372}
373
374void ImmutableStringFieldLiteGenerator::
375GenerateHashCode(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
382string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
383  return "java.lang.String";
384}
385
386// ===================================================================
387
388ImmutableStringOneofFieldLiteGenerator::
389ImmutableStringOneofFieldLiteGenerator(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
400ImmutableStringOneofFieldLiteGenerator::
401~ImmutableStringOneofFieldLiteGenerator() {}
402
403void ImmutableStringOneofFieldLiteGenerator::
404GenerateMembers(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
468void ImmutableStringOneofFieldLiteGenerator::
469GenerateBuilderMembers(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
517void ImmutableStringOneofFieldLiteGenerator::
518GenerateVisitCode(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
524void ImmutableStringOneofFieldLiteGenerator::
525GenerateParsingCode(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
543void ImmutableStringOneofFieldLiteGenerator::
544GenerateSerializationCode(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
554void ImmutableStringOneofFieldLiteGenerator::
555GenerateSerializedSizeCode(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
568RepeatedImmutableStringFieldLiteGenerator::
569RepeatedImmutableStringFieldLiteGenerator(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
581RepeatedImmutableStringFieldLiteGenerator::
582~RepeatedImmutableStringFieldLiteGenerator() {}
583
584int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
585  return 0;
586}
587
588int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
589  return 0;
590}
591
592void RepeatedImmutableStringFieldLiteGenerator::
593GenerateInterfaceMembers(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
611void RepeatedImmutableStringFieldLiteGenerator::
612GenerateMembers(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
692void RepeatedImmutableStringFieldLiteGenerator::
693GenerateBuilderMembers(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
759void RepeatedImmutableStringFieldLiteGenerator::
760GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
761  // noop for strings
762}
763
764void RepeatedImmutableStringFieldLiteGenerator::
765GenerateInitializationCode(io::Printer* printer) const {
766  printer->Print(variables_, "$name$_ = $empty_list$;\n");
767}
768
769void RepeatedImmutableStringFieldLiteGenerator::
770GenerateVisitCode(io::Printer* printer) const {
771  printer->Print(variables_,
772      "$name$_= visitor.visitList($name$_, other.$name$_);\n");
773}
774
775void RepeatedImmutableStringFieldLiteGenerator::
776GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
777  printer->Print(variables_,
778    "$name$_.makeImmutable();\n");
779}
780
781void RepeatedImmutableStringFieldLiteGenerator::
782GenerateParsingCode(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
803void RepeatedImmutableStringFieldLiteGenerator::
804GenerateParsingDoneCode(io::Printer* printer) const {
805  printer->Print(variables_,
806    "if ($is_mutable$) {\n"
807    "  $name$_.makeImmutable();\n"
808    "}\n");
809}
810
811void RepeatedImmutableStringFieldLiteGenerator::
812GenerateSerializationCode(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
822void RepeatedImmutableStringFieldLiteGenerator::
823GenerateSerializedSizeCode(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
849void RepeatedImmutableStringFieldLiteGenerator::
850GenerateEqualsCode(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
856void RepeatedImmutableStringFieldLiteGenerator::
857GenerateHashCode(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
865string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
866  return "String";
867}
868
869}  // namespace java
870}  // namespace compiler
871}  // namespace protobuf
872}  // namespace google
873