1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// http://code.google.com/p/protobuf/
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/compiler/java/java_string_field.h>
40#include <google/protobuf/compiler/java/java_doc_comment.h>
41#include <google/protobuf/stubs/common.h>
42#include <google/protobuf/compiler/java/java_helpers.h>
43#include <google/protobuf/io/printer.h>
44#include <google/protobuf/wire_format.h>
45#include <google/protobuf/stubs/strutil.h>
46
47namespace google {
48namespace protobuf {
49namespace compiler {
50namespace java {
51
52using internal::WireFormat;
53using internal::WireFormatLite;
54
55namespace {
56
57void SetPrimitiveVariables(const FieldDescriptor* descriptor,
58                           int messageBitIndex,
59                           int builderBitIndex,
60                           map<string, string>* variables) {
61  (*variables)["name"] =
62    UnderscoresToCamelCase(descriptor);
63  (*variables)["capitalized_name"] =
64    UnderscoresToCapitalizedCamelCase(descriptor);
65  (*variables)["constant_name"] = FieldConstantName(descriptor);
66  (*variables)["number"] = SimpleItoa(descriptor->number());
67  (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
68
69  (*variables)["default"] = DefaultValue(descriptor);
70  (*variables)["default_init"] = ("= " + DefaultValue(descriptor));
71  (*variables)["capitalized_type"] = "String";
72  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
73  (*variables)["tag_size"] = SimpleItoa(
74      WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
75  (*variables)["null_check"] =
76      "  if (value == null) {\n"
77      "    throw new NullPointerException();\n"
78      "  }\n";
79
80  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
81  // by the proto compiler
82  (*variables)["deprecation"] = descriptor->options().deprecated()
83      ? "@java.lang.Deprecated " : "";
84  (*variables)["on_changed"] =
85      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
86
87  // For singular messages and builders, one bit is used for the hasField bit.
88  (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
89  (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
90
91  (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
92  (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
93  (*variables)["clear_has_field_bit_builder"] =
94      GenerateClearBit(builderBitIndex);
95
96  // For repated builders, one bit is used for whether the array is immutable.
97  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
98  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
99  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
100
101  // For repeated fields, one bit is used for whether the array is immutable
102  // in the parsing constructor.
103  (*variables)["get_mutable_bit_parser"] =
104      GenerateGetBitMutableLocal(builderBitIndex);
105  (*variables)["set_mutable_bit_parser"] =
106      GenerateSetBitMutableLocal(builderBitIndex);
107
108  (*variables)["get_has_field_bit_from_local"] =
109      GenerateGetBitFromLocal(builderBitIndex);
110  (*variables)["set_has_field_bit_to_local"] =
111      GenerateSetBitToLocal(messageBitIndex);
112}
113
114}  // namespace
115
116// ===================================================================
117
118StringFieldGenerator::
119StringFieldGenerator(const FieldDescriptor* descriptor,
120                     int messageBitIndex,
121                     int builderBitIndex)
122  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
123    builderBitIndex_(builderBitIndex) {
124  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
125                        &variables_);
126}
127
128StringFieldGenerator::~StringFieldGenerator() {}
129
130int StringFieldGenerator::GetNumBitsForMessage() const {
131  return 1;
132}
133
134int StringFieldGenerator::GetNumBitsForBuilder() const {
135  return 1;
136}
137
138// A note about how strings are handled. This code used to just store a String
139// in the Message. This had two issues:
140//
141//  1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
142//     strings, but rather fields that were raw bytes incorrectly marked
143//     as strings in the proto file. This is common because in the proto1
144//     syntax, string was the way to indicate bytes and C++ engineers can
145//     easily make this mistake without affecting the C++ API. By converting to
146//     strings immediately, some java code might corrupt these byte arrays as
147//     it passes through a java server even if the field was never accessed by
148//     application code.
149//
150//  2. There's a performance hit to converting between bytes and strings and
151//     it many cases, the field is never even read by the application code. This
152//     avoids unnecessary conversions in the common use cases.
153//
154// So now, the field for String is maintained as an Object reference which can
155// either store a String or a ByteString. The code uses an instanceof check
156// to see which one it has and converts to the other one if needed. It remembers
157// the last value requested (in a thread safe manner) as this is most likely
158// the one needed next. The thread safety is such that if two threads both
159// convert the field because the changes made by each thread were not visible to
160// the other, they may cause a conversion to happen more times than would
161// otherwise be necessary. This was deemed better than adding synchronization
162// overhead. It will not cause any corruption issues or affect the behavior of
163// the API. The instanceof check is also highly optimized in the JVM and we
164// decided it was better to reduce the memory overhead by not having two
165// separate fields but rather use dynamic type checking.
166//
167// For single fields, the logic for this is done inside the generated code. For
168// repeated fields, the logic is done in LazyStringArrayList and
169// UnmodifiableLazyStringList.
170void StringFieldGenerator::
171GenerateInterfaceMembers(io::Printer* printer) const {
172  WriteFieldDocComment(printer, descriptor_);
173  printer->Print(variables_,
174    "$deprecation$boolean has$capitalized_name$();\n");
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 StringFieldGenerator::
185GenerateMembers(io::Printer* printer) const {
186  printer->Print(variables_,
187    "private java.lang.Object $name$_;\n");
188  WriteFieldDocComment(printer, descriptor_);
189  printer->Print(variables_,
190    "$deprecation$public boolean has$capitalized_name$() {\n"
191    "  return $get_has_field_bit_message$;\n"
192    "}\n");
193
194  WriteFieldDocComment(printer, descriptor_);
195  printer->Print(variables_,
196    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
197    "  java.lang.Object ref = $name$_;\n"
198    "  if (ref instanceof java.lang.String) {\n"
199    "    return (java.lang.String) ref;\n"
200    "  } else {\n"
201    "    com.google.protobuf.ByteString bs = \n"
202    "        (com.google.protobuf.ByteString) ref;\n"
203    "    java.lang.String s = bs.toStringUtf8();\n"
204    "    if (bs.isValidUtf8()) {\n"
205    "      $name$_ = s;\n"
206    "    }\n"
207    "    return s;\n"
208    "  }\n"
209    "}\n");
210  WriteFieldDocComment(printer, descriptor_);
211  printer->Print(variables_,
212    "$deprecation$public com.google.protobuf.ByteString\n"
213    "    get$capitalized_name$Bytes() {\n"
214    "  java.lang.Object ref = $name$_;\n"
215    "  if (ref instanceof java.lang.String) {\n"
216    "    com.google.protobuf.ByteString b = \n"
217    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
218    "            (java.lang.String) ref);\n"
219    "    $name$_ = b;\n"
220    "    return b;\n"
221    "  } else {\n"
222    "    return (com.google.protobuf.ByteString) ref;\n"
223    "  }\n"
224    "}\n");
225}
226
227void StringFieldGenerator::
228GenerateBuilderMembers(io::Printer* printer) const {
229  printer->Print(variables_,
230    "private java.lang.Object $name$_ $default_init$;\n");
231  WriteFieldDocComment(printer, descriptor_);
232  printer->Print(variables_,
233    "$deprecation$public boolean has$capitalized_name$() {\n"
234    "  return $get_has_field_bit_builder$;\n"
235    "}\n");
236
237  WriteFieldDocComment(printer, descriptor_);
238  printer->Print(variables_,
239    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
240    "  java.lang.Object ref = $name$_;\n"
241    "  if (!(ref instanceof java.lang.String)) {\n"
242    "    java.lang.String s = ((com.google.protobuf.ByteString) ref)\n"
243    "        .toStringUtf8();\n"
244    "    $name$_ = s;\n"
245    "    return s;\n"
246    "  } else {\n"
247    "    return (java.lang.String) ref;\n"
248    "  }\n"
249    "}\n");
250
251  WriteFieldDocComment(printer, descriptor_);
252  printer->Print(variables_,
253    "$deprecation$public com.google.protobuf.ByteString\n"
254    "    get$capitalized_name$Bytes() {\n"
255    "  java.lang.Object ref = $name$_;\n"
256    "  if (ref instanceof String) {\n"
257    "    com.google.protobuf.ByteString b = \n"
258    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
259    "            (java.lang.String) ref);\n"
260    "    $name$_ = b;\n"
261    "    return b;\n"
262    "  } else {\n"
263    "    return (com.google.protobuf.ByteString) ref;\n"
264    "  }\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    "$null_check$"
272    "  $set_has_field_bit_builder$;\n"
273    "  $name$_ = value;\n"
274    "  $on_changed$\n"
275    "  return this;\n"
276    "}\n");
277  WriteFieldDocComment(printer, descriptor_);
278  printer->Print(variables_,
279    "$deprecation$public Builder clear$capitalized_name$() {\n"
280    "  $clear_has_field_bit_builder$;\n");
281  // The default value is not a simple literal so we want to avoid executing
282  // it multiple times.  Instead, get the default out of the default instance.
283  printer->Print(variables_,
284    "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
285  printer->Print(variables_,
286    "  $on_changed$\n"
287    "  return this;\n"
288    "}\n");
289
290  WriteFieldDocComment(printer, descriptor_);
291  printer->Print(variables_,
292    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
293    "    com.google.protobuf.ByteString value) {\n"
294    "$null_check$"
295    "  $set_has_field_bit_builder$;\n"
296    "  $name$_ = value;\n"
297    "  $on_changed$\n"
298    "  return this;\n"
299    "}\n");
300}
301
302void StringFieldGenerator::
303GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
304  // noop for primitives
305}
306
307void StringFieldGenerator::
308GenerateInitializationCode(io::Printer* printer) const {
309  printer->Print(variables_, "$name$_ = $default$;\n");
310}
311
312void StringFieldGenerator::
313GenerateBuilderClearCode(io::Printer* printer) const {
314  printer->Print(variables_,
315    "$name$_ = $default$;\n"
316    "$clear_has_field_bit_builder$;\n");
317}
318
319void StringFieldGenerator::
320GenerateMergingCode(io::Printer* printer) const {
321  // Allow a slight breach of abstraction here in order to avoid forcing
322  // all string fields to Strings when copying fields from a Message.
323  printer->Print(variables_,
324    "if (other.has$capitalized_name$()) {\n"
325    "  $set_has_field_bit_builder$;\n"
326    "  $name$_ = other.$name$_;\n"
327    "  $on_changed$\n"
328    "}\n");
329}
330
331void StringFieldGenerator::
332GenerateBuildingCode(io::Printer* printer) const {
333  printer->Print(variables_,
334    "if ($get_has_field_bit_from_local$) {\n"
335    "  $set_has_field_bit_to_local$;\n"
336    "}\n"
337    "result.$name$_ = $name$_;\n");
338}
339
340void StringFieldGenerator::
341GenerateParsingCode(io::Printer* printer) const {
342  printer->Print(variables_,
343    "$set_has_field_bit_message$;\n"
344    "$name$_ = input.readBytes();\n");
345}
346
347void StringFieldGenerator::
348GenerateParsingDoneCode(io::Printer* printer) const {
349  // noop for strings.
350}
351
352void StringFieldGenerator::
353GenerateSerializationCode(io::Printer* printer) const {
354  printer->Print(variables_,
355    "if ($get_has_field_bit_message$) {\n"
356    "  output.writeBytes($number$, get$capitalized_name$Bytes());\n"
357    "}\n");
358}
359
360void StringFieldGenerator::
361GenerateSerializedSizeCode(io::Printer* printer) const {
362  printer->Print(variables_,
363    "if ($get_has_field_bit_message$) {\n"
364    "  size += com.google.protobuf.CodedOutputStream\n"
365    "    .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
366    "}\n");
367}
368
369void StringFieldGenerator::
370GenerateEqualsCode(io::Printer* printer) const {
371  printer->Print(variables_,
372    "result = result && get$capitalized_name$()\n"
373    "    .equals(other.get$capitalized_name$());\n");
374}
375
376void StringFieldGenerator::
377GenerateHashCode(io::Printer* printer) const {
378  printer->Print(variables_,
379    "hash = (37 * hash) + $constant_name$;\n");
380  printer->Print(variables_,
381    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
382}
383
384string StringFieldGenerator::GetBoxedType() const {
385  return "java.lang.String";
386}
387
388
389// ===================================================================
390
391RepeatedStringFieldGenerator::
392RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
393                             int messageBitIndex,
394                             int builderBitIndex)
395  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
396    builderBitIndex_(builderBitIndex) {
397  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
398                        &variables_);
399}
400
401RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
402
403int RepeatedStringFieldGenerator::GetNumBitsForMessage() const {
404  return 0;
405}
406
407int RepeatedStringFieldGenerator::GetNumBitsForBuilder() const {
408  return 1;
409}
410
411void RepeatedStringFieldGenerator::
412GenerateInterfaceMembers(io::Printer* printer) const {
413  WriteFieldDocComment(printer, descriptor_);
414  printer->Print(variables_,
415    "$deprecation$java.util.List<java.lang.String>\n"
416    "get$capitalized_name$List();\n");
417  WriteFieldDocComment(printer, descriptor_);
418  printer->Print(variables_,
419    "$deprecation$int get$capitalized_name$Count();\n");
420  WriteFieldDocComment(printer, descriptor_);
421  printer->Print(variables_,
422    "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
423  WriteFieldDocComment(printer, descriptor_);
424  printer->Print(variables_,
425    "$deprecation$com.google.protobuf.ByteString\n"
426    "    get$capitalized_name$Bytes(int index);\n");
427}
428
429
430void RepeatedStringFieldGenerator::
431GenerateMembers(io::Printer* printer) const {
432  printer->Print(variables_,
433    "private com.google.protobuf.LazyStringList $name$_;\n");
434  WriteFieldDocComment(printer, descriptor_);
435  printer->Print(variables_,
436    "$deprecation$public java.util.List<java.lang.String>\n"
437    "    get$capitalized_name$List() {\n"
438    "  return $name$_;\n"   // note:  unmodifiable list
439    "}\n");
440  WriteFieldDocComment(printer, descriptor_);
441  printer->Print(variables_,
442    "$deprecation$public int get$capitalized_name$Count() {\n"
443    "  return $name$_.size();\n"
444    "}\n");
445  WriteFieldDocComment(printer, descriptor_);
446  printer->Print(variables_,
447    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
448    "  return $name$_.get(index);\n"
449    "}\n");
450  WriteFieldDocComment(printer, descriptor_);
451  printer->Print(variables_,
452    "$deprecation$public com.google.protobuf.ByteString\n"
453    "    get$capitalized_name$Bytes(int index) {\n"
454    "  return $name$_.getByteString(index);\n"
455    "}\n");
456
457  if (descriptor_->options().packed() &&
458      HasGeneratedMethods(descriptor_->containing_type())) {
459    printer->Print(variables_,
460      "private int $name$MemoizedSerializedSize = -1;\n");
461  }
462}
463
464void RepeatedStringFieldGenerator::
465GenerateBuilderMembers(io::Printer* printer) const {
466  // One field is the list and the bit field keeps track of whether the
467  // list is immutable. If it's immutable, the invariant is that it must
468  // either an instance of Collections.emptyList() or it's an ArrayList
469  // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
470  // a refererence to the underlying ArrayList. This invariant allows us to
471  // share instances of lists between protocol buffers avoiding expensive
472  // memory allocations. Note, immutable is a strong guarantee here -- not
473  // just that the list cannot be modified via the reference but that the
474  // list can never be modified.
475  printer->Print(variables_,
476    "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
477
478  printer->Print(variables_,
479    "private void ensure$capitalized_name$IsMutable() {\n"
480    "  if (!$get_mutable_bit_builder$) {\n"
481    "    $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
482    "    $set_mutable_bit_builder$;\n"
483    "   }\n"
484    "}\n");
485
486    // Note:  We return an unmodifiable list because otherwise the caller
487    //   could hold on to the returned list and modify it after the message
488    //   has been built, thus mutating the message which is supposed to be
489    //   immutable.
490  WriteFieldDocComment(printer, descriptor_);
491  printer->Print(variables_,
492    "$deprecation$public java.util.List<java.lang.String>\n"
493    "    get$capitalized_name$List() {\n"
494    "  return java.util.Collections.unmodifiableList($name$_);\n"
495    "}\n");
496  WriteFieldDocComment(printer, descriptor_);
497  printer->Print(variables_,
498    "$deprecation$public int get$capitalized_name$Count() {\n"
499    "  return $name$_.size();\n"
500    "}\n");
501  WriteFieldDocComment(printer, descriptor_);
502  printer->Print(variables_,
503    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
504    "  return $name$_.get(index);\n"
505    "}\n");
506  WriteFieldDocComment(printer, descriptor_);
507  printer->Print(variables_,
508    "$deprecation$public com.google.protobuf.ByteString\n"
509    "    get$capitalized_name$Bytes(int index) {\n"
510    "  return $name$_.getByteString(index);\n"
511    "}\n");
512  WriteFieldDocComment(printer, descriptor_);
513  printer->Print(variables_,
514    "$deprecation$public Builder set$capitalized_name$(\n"
515    "    int index, java.lang.String value) {\n"
516    "$null_check$"
517    "  ensure$capitalized_name$IsMutable();\n"
518    "  $name$_.set(index, value);\n"
519    "  $on_changed$\n"
520    "  return this;\n"
521    "}\n");
522  WriteFieldDocComment(printer, descriptor_);
523  printer->Print(variables_,
524    "$deprecation$public Builder add$capitalized_name$(\n"
525    "    java.lang.String value) {\n"
526    "$null_check$"
527    "  ensure$capitalized_name$IsMutable();\n"
528    "  $name$_.add(value);\n"
529    "  $on_changed$\n"
530    "  return this;\n"
531    "}\n");
532  WriteFieldDocComment(printer, descriptor_);
533  printer->Print(variables_,
534    "$deprecation$public Builder addAll$capitalized_name$(\n"
535    "    java.lang.Iterable<java.lang.String> values) {\n"
536    "  ensure$capitalized_name$IsMutable();\n"
537    "  super.addAll(values, $name$_);\n"
538    "  $on_changed$\n"
539    "  return this;\n"
540    "}\n");
541  WriteFieldDocComment(printer, descriptor_);
542  printer->Print(variables_,
543    "$deprecation$public Builder clear$capitalized_name$() {\n"
544    "  $name$_ = $empty_list$;\n"
545    "  $clear_mutable_bit_builder$;\n"
546    "  $on_changed$\n"
547    "  return this;\n"
548    "}\n");
549
550  WriteFieldDocComment(printer, descriptor_);
551  printer->Print(variables_,
552    "$deprecation$public Builder add$capitalized_name$Bytes(\n"
553    "    com.google.protobuf.ByteString value) {\n"
554    "$null_check$"
555    "  ensure$capitalized_name$IsMutable();\n"
556    "  $name$_.add(value);\n"
557    "  $on_changed$\n"
558    "  return this;\n"
559    "}\n");
560}
561
562void RepeatedStringFieldGenerator::
563GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
564  // noop for primitives
565}
566
567void RepeatedStringFieldGenerator::
568GenerateInitializationCode(io::Printer* printer) const {
569  printer->Print(variables_, "$name$_ = $empty_list$;\n");
570}
571
572void RepeatedStringFieldGenerator::
573GenerateBuilderClearCode(io::Printer* printer) const {
574  printer->Print(variables_,
575    "$name$_ = $empty_list$;\n"
576    "$clear_mutable_bit_builder$;\n");
577}
578
579void RepeatedStringFieldGenerator::
580GenerateMergingCode(io::Printer* printer) const {
581  // The code below does two optimizations:
582  //   1. If the other list is empty, there's nothing to do. This ensures we
583  //      don't allocate a new array if we already have an immutable one.
584  //   2. If the other list is non-empty and our current list is empty, we can
585  //      reuse the other list which is guaranteed to be immutable.
586  printer->Print(variables_,
587    "if (!other.$name$_.isEmpty()) {\n"
588    "  if ($name$_.isEmpty()) {\n"
589    "    $name$_ = other.$name$_;\n"
590    "    $clear_mutable_bit_builder$;\n"
591    "  } else {\n"
592    "    ensure$capitalized_name$IsMutable();\n"
593    "    $name$_.addAll(other.$name$_);\n"
594    "  }\n"
595    "  $on_changed$\n"
596    "}\n");
597}
598
599void RepeatedStringFieldGenerator::
600GenerateBuildingCode(io::Printer* printer) const {
601  // The code below ensures that the result has an immutable list. If our
602  // list is immutable, we can just reuse it. If not, we make it immutable.
603
604  printer->Print(variables_,
605    "if ($get_mutable_bit_builder$) {\n"
606    "  $name$_ = new com.google.protobuf.UnmodifiableLazyStringList(\n"
607    "      $name$_);\n"
608    "  $clear_mutable_bit_builder$;\n"
609    "}\n"
610    "result.$name$_ = $name$_;\n");
611}
612
613void RepeatedStringFieldGenerator::
614GenerateParsingCode(io::Printer* printer) const {
615  printer->Print(variables_,
616    "if (!$get_mutable_bit_parser$) {\n"
617    "  $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
618    "  $set_mutable_bit_parser$;\n"
619    "}\n"
620    "$name$_.add(input.readBytes());\n");
621}
622
623void RepeatedStringFieldGenerator::
624GenerateParsingCodeFromPacked(io::Printer* printer) const {
625  printer->Print(variables_,
626    "int length = input.readRawVarint32();\n"
627    "int limit = input.pushLimit(length);\n"
628    "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
629    "  $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
630    "  $set_mutable_bit_parser$;\n"
631    "}\n"
632    "while (input.getBytesUntilLimit() > 0) {\n"
633    "  $name$.add(input.read$capitalized_type$());\n"
634    "}\n"
635    "input.popLimit(limit);\n");
636}
637
638void RepeatedStringFieldGenerator::
639GenerateParsingDoneCode(io::Printer* printer) const {
640  printer->Print(variables_,
641    "if ($get_mutable_bit_parser$) {\n"
642    "  $name$_ = new com.google.protobuf.UnmodifiableLazyStringList($name$_);\n"
643    "}\n");
644}
645
646void RepeatedStringFieldGenerator::
647GenerateSerializationCode(io::Printer* printer) const {
648  if (descriptor_->options().packed()) {
649    printer->Print(variables_,
650      "if (get$capitalized_name$List().size() > 0) {\n"
651      "  output.writeRawVarint32($tag$);\n"
652      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
653      "}\n"
654      "for (int i = 0; i < $name$_.size(); i++) {\n"
655      "  output.write$capitalized_type$NoTag($name$_.get(i));\n"
656      "}\n");
657  } else {
658    printer->Print(variables_,
659      "for (int i = 0; i < $name$_.size(); i++) {\n"
660      "  output.writeBytes($number$, $name$_.getByteString(i));\n"
661      "}\n");
662  }
663}
664
665void RepeatedStringFieldGenerator::
666GenerateSerializedSizeCode(io::Printer* printer) const {
667  printer->Print(variables_,
668    "{\n"
669    "  int dataSize = 0;\n");
670  printer->Indent();
671
672  printer->Print(variables_,
673    "for (int i = 0; i < $name$_.size(); i++) {\n"
674    "  dataSize += com.google.protobuf.CodedOutputStream\n"
675    "    .computeBytesSizeNoTag($name$_.getByteString(i));\n"
676    "}\n");
677
678  printer->Print(
679      "size += dataSize;\n");
680
681  if (descriptor_->options().packed()) {
682    printer->Print(variables_,
683      "if (!get$capitalized_name$List().isEmpty()) {\n"
684      "  size += $tag_size$;\n"
685      "  size += com.google.protobuf.CodedOutputStream\n"
686      "      .computeInt32SizeNoTag(dataSize);\n"
687      "}\n");
688  } else {
689    printer->Print(variables_,
690      "size += $tag_size$ * get$capitalized_name$List().size();\n");
691  }
692
693  // cache the data size for packed fields.
694  if (descriptor_->options().packed()) {
695    printer->Print(variables_,
696      "$name$MemoizedSerializedSize = dataSize;\n");
697  }
698
699  printer->Outdent();
700  printer->Print("}\n");
701}
702
703void RepeatedStringFieldGenerator::
704GenerateEqualsCode(io::Printer* printer) const {
705  printer->Print(variables_,
706    "result = result && get$capitalized_name$List()\n"
707    "    .equals(other.get$capitalized_name$List());\n");
708}
709
710void RepeatedStringFieldGenerator::
711GenerateHashCode(io::Printer* printer) const {
712  printer->Print(variables_,
713    "if (get$capitalized_name$Count() > 0) {\n"
714    "  hash = (37 * hash) + $constant_name$;\n"
715    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
716    "}\n");
717}
718
719string RepeatedStringFieldGenerator::GetBoxedType() const {
720  return "String";
721}
722
723}  // namespace java
724}  // namespace compiler
725}  // namespace protobuf
726}  // namespace google
727