java_string_field.cc revision afb4b72037e3f13db208590fc782c4bc8e27f862
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/common.h>
40#include <google/protobuf/compiler/java/java_context.h>
41#include <google/protobuf/compiler/java/java_doc_comment.h>
42#include <google/protobuf/compiler/java/java_helpers.h>
43#include <google/protobuf/compiler/java/java_name_resolver.h>
44#include <google/protobuf/compiler/java/java_string_field.h>
45#include <google/protobuf/io/printer.h>
46#include <google/protobuf/wire_format.h>
47#include <google/protobuf/stubs/strutil.h>
48
49namespace google {
50namespace protobuf {
51namespace compiler {
52namespace java {
53
54using internal::WireFormat;
55using internal::WireFormatLite;
56
57namespace {
58
59void SetPrimitiveVariables(const FieldDescriptor* descriptor,
60                           int messageBitIndex,
61                           int builderBitIndex,
62                           const FieldGeneratorInfo* info,
63                           ClassNameResolver* name_resolver,
64                           map<string, string>* variables) {
65  SetCommonFieldVariables(descriptor, info, variables);
66
67  (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
68
69  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
70  (*variables)["default_init"] =
71      "= " + ImmutableDefaultValue(descriptor, name_resolver);
72  (*variables)["capitalized_type"] = "String";
73  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
74  (*variables)["tag_size"] = SimpleItoa(
75      WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
76  (*variables)["null_check"] =
77      "  if (value == null) {\n"
78      "    throw new NullPointerException();\n"
79      "  }\n";
80
81  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
82  // by the proto compiler
83  (*variables)["deprecation"] = descriptor->options().deprecated()
84      ? "@java.lang.Deprecated " : "";
85  (*variables)["on_changed"] =
86      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
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    (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
92
93    // Note that these have a trailing ";".
94    (*variables)["set_has_field_bit_message"] =
95        GenerateSetBit(messageBitIndex) + ";";
96    (*variables)["set_has_field_bit_builder"] =
97        GenerateSetBit(builderBitIndex) + ";";
98    (*variables)["clear_has_field_bit_builder"] =
99        GenerateClearBit(builderBitIndex) + ";";
100
101    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
102  } else {
103    (*variables)["set_has_field_bit_message"] = "";
104    (*variables)["set_has_field_bit_builder"] = "";
105    (*variables)["clear_has_field_bit_builder"] = "";
106
107    (*variables)["is_field_present_message"] =
108        "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()";
109  }
110
111  // For repeated builders, one bit is used for whether the array is immutable.
112  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
113  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
114  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
115
116  // For repeated fields, one bit is used for whether the array is immutable
117  // in the parsing constructor.
118  (*variables)["get_mutable_bit_parser"] =
119      GenerateGetBitMutableLocal(builderBitIndex);
120  (*variables)["set_mutable_bit_parser"] =
121      GenerateSetBitMutableLocal(builderBitIndex);
122
123  (*variables)["get_has_field_bit_from_local"] =
124      GenerateGetBitFromLocal(builderBitIndex);
125  (*variables)["set_has_field_bit_to_local"] =
126      GenerateSetBitToLocal(messageBitIndex);
127}
128
129bool CheckUtf8(const FieldDescriptor* descriptor) {
130  return descriptor->file()->options().java_string_check_utf8();
131}
132
133}  // namespace
134
135// ===================================================================
136
137ImmutableStringFieldGenerator::
138ImmutableStringFieldGenerator(const FieldDescriptor* descriptor,
139                              int messageBitIndex,
140                              int builderBitIndex,
141                              Context* context)
142  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
143    builderBitIndex_(builderBitIndex), context_(context),
144    name_resolver_(context->GetNameResolver()) {
145  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
146                        context->GetFieldGeneratorInfo(descriptor),
147                        name_resolver_, &variables_);
148}
149
150ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
151
152int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
153  return 1;
154}
155
156int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
157  return 1;
158}
159
160// A note about how strings are handled. This code used to just store a String
161// in the Message. This had two issues:
162//
163//  1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
164//     strings, but rather fields that were raw bytes incorrectly marked
165//     as strings in the proto file. This is common because in the proto1
166//     syntax, string was the way to indicate bytes and C++ engineers can
167//     easily make this mistake without affecting the C++ API. By converting to
168//     strings immediately, some java code might corrupt these byte arrays as
169//     it passes through a java server even if the field was never accessed by
170//     application code.
171//
172//  2. There's a performance hit to converting between bytes and strings and
173//     it many cases, the field is never even read by the application code. This
174//     avoids unnecessary conversions in the common use cases.
175//
176// So now, the field for String is maintained as an Object reference which can
177// either store a String or a ByteString. The code uses an instanceof check
178// to see which one it has and converts to the other one if needed. It remembers
179// the last value requested (in a thread safe manner) as this is most likely
180// the one needed next. The thread safety is such that if two threads both
181// convert the field because the changes made by each thread were not visible to
182// the other, they may cause a conversion to happen more times than would
183// otherwise be necessary. This was deemed better than adding synchronization
184// overhead. It will not cause any corruption issues or affect the behavior of
185// the API. The instanceof check is also highly optimized in the JVM and we
186// decided it was better to reduce the memory overhead by not having two
187// separate fields but rather use dynamic type checking.
188//
189// For single fields, the logic for this is done inside the generated code. For
190// repeated fields, the logic is done in LazyStringArrayList and
191// UnmodifiableLazyStringList.
192void ImmutableStringFieldGenerator::
193GenerateInterfaceMembers(io::Printer* printer) const {
194  if (SupportFieldPresence(descriptor_->file())) {
195    WriteFieldDocComment(printer, descriptor_);
196    printer->Print(variables_,
197      "$deprecation$boolean has$capitalized_name$();\n");
198  }
199  WriteFieldDocComment(printer, descriptor_);
200  printer->Print(variables_,
201    "$deprecation$java.lang.String get$capitalized_name$();\n");
202  WriteFieldDocComment(printer, descriptor_);
203  printer->Print(variables_,
204    "$deprecation$com.google.protobuf.ByteString\n"
205    "    get$capitalized_name$Bytes();\n");
206}
207
208void ImmutableStringFieldGenerator::
209GenerateMembers(io::Printer* printer) const {
210  printer->Print(variables_,
211    "private java.lang.Object $name$_;\n");
212  PrintExtraFieldInfo(variables_, printer);
213
214  if (SupportFieldPresence(descriptor_->file())) {
215    WriteFieldDocComment(printer, descriptor_);
216    printer->Print(variables_,
217      "$deprecation$public boolean has$capitalized_name$() {\n"
218      "  return $get_has_field_bit_message$;\n"
219      "}\n");
220  }
221
222  WriteFieldDocComment(printer, descriptor_);
223  printer->Print(variables_,
224    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
225    "  java.lang.Object ref = $name$_;\n"
226    "  if (ref instanceof java.lang.String) {\n"
227    "    return (java.lang.String) ref;\n"
228    "  } else {\n"
229    "    com.google.protobuf.ByteString bs = \n"
230    "        (com.google.protobuf.ByteString) ref;\n"
231      "    java.lang.String s = bs.toStringUtf8();\n");
232  if (CheckUtf8(descriptor_)) {
233    printer->Print(variables_,
234      "    $name$_ = s;\n");
235  } else {
236    printer->Print(variables_,
237      "    if (bs.isValidUtf8()) {\n"
238      "      $name$_ = s;\n"
239      "    }\n");
240  }
241  printer->Print(variables_,
242    "    return s;\n"
243    "  }\n"
244    "}\n");
245  WriteFieldDocComment(printer, descriptor_);
246  printer->Print(variables_,
247    "$deprecation$public com.google.protobuf.ByteString\n"
248    "    get$capitalized_name$Bytes() {\n"
249    "  java.lang.Object ref = $name$_;\n"
250    "  if (ref instanceof java.lang.String) {\n"
251    "    com.google.protobuf.ByteString b = \n"
252    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
253    "            (java.lang.String) ref);\n"
254    "    $name$_ = b;\n"
255    "    return b;\n"
256    "  } else {\n"
257    "    return (com.google.protobuf.ByteString) ref;\n"
258    "  }\n"
259    "}\n");
260}
261
262void ImmutableStringFieldGenerator::
263GenerateBuilderMembers(io::Printer* printer) const {
264  printer->Print(variables_,
265    "private java.lang.Object $name$_ $default_init$;\n");
266  if (SupportFieldPresence(descriptor_->file())) {
267    WriteFieldDocComment(printer, descriptor_);
268    printer->Print(variables_,
269      "$deprecation$public boolean has$capitalized_name$() {\n"
270      "  return $get_has_field_bit_builder$;\n"
271      "}\n");
272  }
273
274  WriteFieldDocComment(printer, descriptor_);
275  printer->Print(variables_,
276    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
277    "  java.lang.Object ref = $name$_;\n"
278    "  if (!(ref instanceof java.lang.String)) {\n"
279    "    com.google.protobuf.ByteString bs =\n"
280    "        (com.google.protobuf.ByteString) ref;\n"
281    "    java.lang.String s = bs.toStringUtf8();\n");
282  if (CheckUtf8(descriptor_)) {
283    printer->Print(variables_,
284      "    $name$_ = s;\n");
285  } else {
286    printer->Print(variables_,
287      "    if (bs.isValidUtf8()) {\n"
288      "      $name$_ = s;\n"
289      "    }\n");
290  }
291  printer->Print(variables_,
292    "    return s;\n"
293    "  } else {\n"
294    "    return (java.lang.String) ref;\n"
295    "  }\n"
296    "}\n");
297
298  WriteFieldDocComment(printer, descriptor_);
299  printer->Print(variables_,
300    "$deprecation$public com.google.protobuf.ByteString\n"
301    "    get$capitalized_name$Bytes() {\n"
302    "  java.lang.Object ref = $name$_;\n"
303    "  if (ref instanceof String) {\n"
304    "    com.google.protobuf.ByteString b = \n"
305    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
306    "            (java.lang.String) ref);\n"
307    "    $name$_ = b;\n"
308    "    return b;\n"
309    "  } else {\n"
310    "    return (com.google.protobuf.ByteString) ref;\n"
311    "  }\n"
312    "}\n");
313
314  WriteFieldDocComment(printer, descriptor_);
315  printer->Print(variables_,
316    "$deprecation$public Builder set$capitalized_name$(\n"
317    "    java.lang.String value) {\n"
318    "$null_check$"
319    "  $set_has_field_bit_builder$\n"
320    "  $name$_ = value;\n"
321    "  $on_changed$\n"
322    "  return this;\n"
323    "}\n");
324  WriteFieldDocComment(printer, descriptor_);
325  printer->Print(variables_,
326    "$deprecation$public Builder clear$capitalized_name$() {\n"
327    "  $clear_has_field_bit_builder$\n");
328  // The default value is not a simple literal so we want to avoid executing
329  // it multiple times.  Instead, get the default out of the default instance.
330  printer->Print(variables_,
331    "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
332  printer->Print(variables_,
333    "  $on_changed$\n"
334    "  return this;\n"
335    "}\n");
336
337  WriteFieldDocComment(printer, descriptor_);
338  printer->Print(variables_,
339    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
340    "    com.google.protobuf.ByteString value) {\n"
341    "$null_check$");
342  if (CheckUtf8(descriptor_)) {
343    printer->Print(variables_,
344      "  checkByteStringIsUtf8(value);\n");
345  }
346  printer->Print(variables_,
347    "  $set_has_field_bit_builder$\n"
348    "  $name$_ = value;\n"
349    "  $on_changed$\n"
350    "  return this;\n"
351    "}\n");
352}
353
354void ImmutableStringFieldGenerator::
355GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
356  // noop for primitives
357}
358
359void ImmutableStringFieldGenerator::
360GenerateInitializationCode(io::Printer* printer) const {
361  printer->Print(variables_, "$name$_ = $default$;\n");
362}
363
364void ImmutableStringFieldGenerator::
365GenerateBuilderClearCode(io::Printer* printer) const {
366  printer->Print(variables_,
367    "$name$_ = $default$;\n"
368    "$clear_has_field_bit_builder$\n");
369}
370
371void ImmutableStringFieldGenerator::
372GenerateMergingCode(io::Printer* printer) const {
373  if (SupportFieldPresence(descriptor_->file())) {
374    // Allow a slight breach of abstraction here in order to avoid forcing
375    // all string fields to Strings when copying fields from a Message.
376    printer->Print(variables_,
377      "if (other.has$capitalized_name$()) {\n"
378      "  $set_has_field_bit_builder$\n"
379      "  $name$_ = other.$name$_;\n"
380      "  $on_changed$\n"
381      "}\n");
382  } else {
383    printer->Print(variables_,
384      "if (!other.get$capitalized_name$().isEmpty()) {\n"
385      "  $name$_ = other.$name$_;\n"
386      "  $on_changed$\n"
387      "}\n");
388  }
389}
390
391void ImmutableStringFieldGenerator::
392GenerateBuildingCode(io::Printer* printer) const {
393  if (SupportFieldPresence(descriptor_->file())) {
394    printer->Print(variables_,
395      "if ($get_has_field_bit_from_local$) {\n"
396      "  $set_has_field_bit_to_local$;\n"
397      "}\n");
398  }
399  printer->Print(variables_,
400    "result.$name$_ = $name$_;\n");
401}
402
403void ImmutableStringFieldGenerator::
404GenerateParsingCode(io::Printer* printer) const {
405  if (CheckUtf8(descriptor_)) {
406    printer->Print(variables_,
407      "String s = input.readStringRequireUtf8();\n"
408      "$set_has_field_bit_message$\n"
409      "$name$_ = s;\n");
410  } else {
411    printer->Print(variables_,
412      "com.google.protobuf.ByteString bs = input.readBytes();\n"
413      "$set_has_field_bit_message$\n"
414      "$name$_ = bs;\n");
415  }
416}
417
418void ImmutableStringFieldGenerator::
419GenerateParsingDoneCode(io::Printer* printer) const {
420  // noop for strings.
421}
422
423void ImmutableStringFieldGenerator::
424GenerateSerializationCode(io::Printer* printer) const {
425  printer->Print(variables_,
426    "if ($is_field_present_message$) {\n"
427    "  output.writeBytes($number$, get$capitalized_name$Bytes());\n"
428    "}\n");
429}
430
431void ImmutableStringFieldGenerator::
432GenerateSerializedSizeCode(io::Printer* printer) const {
433  printer->Print(variables_,
434    "if ($is_field_present_message$) {\n"
435    "  size += com.google.protobuf.CodedOutputStream\n"
436    "    .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
437    "}\n");
438}
439
440void ImmutableStringFieldGenerator::
441GenerateEqualsCode(io::Printer* printer) const {
442  printer->Print(variables_,
443    "result = result && get$capitalized_name$()\n"
444    "    .equals(other.get$capitalized_name$());\n");
445}
446
447void ImmutableStringFieldGenerator::
448GenerateHashCode(io::Printer* printer) const {
449  printer->Print(variables_,
450    "hash = (37 * hash) + $constant_name$;\n");
451  printer->Print(variables_,
452    "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
453}
454
455string ImmutableStringFieldGenerator::GetBoxedType() const {
456  return "java.lang.String";
457}
458
459// ===================================================================
460
461ImmutableStringOneofFieldGenerator::
462ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor,
463                                   int messageBitIndex,
464                                   int builderBitIndex,
465                                   Context* context)
466    : ImmutableStringFieldGenerator(
467          descriptor, messageBitIndex, builderBitIndex, context) {
468  const OneofGeneratorInfo* info =
469      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
470  SetCommonOneofVariables(descriptor, info, &variables_);
471}
472
473ImmutableStringOneofFieldGenerator::
474~ImmutableStringOneofFieldGenerator() {}
475
476void ImmutableStringOneofFieldGenerator::
477GenerateMembers(io::Printer* printer) const {
478  PrintExtraFieldInfo(variables_, printer);
479
480  if (SupportFieldPresence(descriptor_->file())) {
481  WriteFieldDocComment(printer, descriptor_);
482  printer->Print(variables_,
483    "$deprecation$public boolean has$capitalized_name$() {\n"
484    "  return $has_oneof_case_message$;\n"
485    "}\n");
486  }
487
488  WriteFieldDocComment(printer, descriptor_);
489  printer->Print(variables_,
490    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
491    "  java.lang.Object ref $default_init$;\n"
492    "  if ($has_oneof_case_message$) {\n"
493    "    ref = $oneof_name$_;\n"
494    "  }\n"
495    "  if (ref instanceof java.lang.String) {\n"
496    "    return (java.lang.String) ref;\n"
497    "  } else {\n"
498    "    com.google.protobuf.ByteString bs = \n"
499    "        (com.google.protobuf.ByteString) ref;\n"
500    "    java.lang.String s = bs.toStringUtf8();\n");
501  if (CheckUtf8(descriptor_)) {
502    printer->Print(variables_,
503    "    if ($has_oneof_case_message$) {\n"
504    "      $oneof_name$_ = s;\n"
505    "    }\n");
506  } else {
507    printer->Print(variables_,
508    "    if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
509    "      $oneof_name$_ = s;\n"
510    "    }\n");
511  }
512  printer->Print(variables_,
513    "    return s;\n"
514    "  }\n"
515    "}\n");
516  WriteFieldDocComment(printer, descriptor_);
517
518  printer->Print(variables_,
519    "$deprecation$public com.google.protobuf.ByteString\n"
520    "    get$capitalized_name$Bytes() {\n"
521    "  java.lang.Object ref $default_init$;\n"
522    "  if ($has_oneof_case_message$) {\n"
523    "    ref = $oneof_name$_;\n"
524    "  }\n"
525    "  if (ref instanceof java.lang.String) {\n"
526    "    com.google.protobuf.ByteString b = \n"
527    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
528    "            (java.lang.String) ref);\n"
529    "    if ($has_oneof_case_message$) {\n"
530    "      $oneof_name$_ = b;\n"
531    "    }\n"
532    "    return b;\n"
533    "  } else {\n"
534    "    return (com.google.protobuf.ByteString) ref;\n"
535    "  }\n"
536    "}\n");
537}
538
539void ImmutableStringOneofFieldGenerator::
540GenerateBuilderMembers(io::Printer* printer) const {
541  if (SupportFieldPresence(descriptor_->file())) {
542    WriteFieldDocComment(printer, descriptor_);
543    printer->Print(variables_,
544      "$deprecation$public boolean has$capitalized_name$() {\n"
545      "  return $has_oneof_case_message$;\n"
546      "}\n");
547  }
548
549  WriteFieldDocComment(printer, descriptor_);
550  printer->Print(variables_,
551    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
552    "  java.lang.Object ref $default_init$;\n"
553    "  if ($has_oneof_case_message$) {\n"
554    "    ref = $oneof_name$_;\n"
555    "  }\n"
556    "  if (!(ref instanceof java.lang.String)) {\n"
557    "    com.google.protobuf.ByteString bs =\n"
558    "        (com.google.protobuf.ByteString) ref;\n"
559    "    java.lang.String s = bs.toStringUtf8();\n"
560    "    if ($has_oneof_case_message$) {\n");
561  if (CheckUtf8(descriptor_)) {
562    printer->Print(variables_,
563      "      $oneof_name$_ = s;\n");
564  } else {
565    printer->Print(variables_,
566      "      if (bs.isValidUtf8()) {\n"
567      "        $oneof_name$_ = s;\n"
568      "      }\n");
569  }
570  printer->Print(variables_,
571    "    }\n"
572    "    return s;\n"
573    "  } else {\n"
574    "    return (java.lang.String) ref;\n"
575    "  }\n"
576    "}\n");
577
578  WriteFieldDocComment(printer, descriptor_);
579  printer->Print(variables_,
580    "$deprecation$public com.google.protobuf.ByteString\n"
581    "    get$capitalized_name$Bytes() {\n"
582    "  java.lang.Object ref $default_init$;\n"
583    "  if ($has_oneof_case_message$) {\n"
584    "    ref = $oneof_name$_;\n"
585    "  }\n"
586    "  if (ref instanceof String) {\n"
587    "    com.google.protobuf.ByteString b = \n"
588    "        com.google.protobuf.ByteString.copyFromUtf8(\n"
589    "            (java.lang.String) ref);\n"
590    "    if ($has_oneof_case_message$) {\n"
591    "      $oneof_name$_ = b;\n"
592    "    }\n"
593    "    return b;\n"
594    "  } else {\n"
595    "    return (com.google.protobuf.ByteString) ref;\n"
596    "  }\n"
597    "}\n");
598
599  WriteFieldDocComment(printer, descriptor_);
600  printer->Print(variables_,
601    "$deprecation$public Builder set$capitalized_name$(\n"
602    "    java.lang.String value) {\n"
603    "$null_check$"
604    "  $set_oneof_case_message$;\n"
605    "  $oneof_name$_ = value;\n"
606    "  $on_changed$\n"
607    "  return this;\n"
608    "}\n");
609  WriteFieldDocComment(printer, descriptor_);
610  printer->Print(variables_,
611    "$deprecation$public Builder clear$capitalized_name$() {\n"
612    "  if ($has_oneof_case_message$) {\n"
613    "    $clear_oneof_case_message$;\n"
614    "    $oneof_name$_ = null;\n"
615    "    $on_changed$\n"
616    "  }\n"
617    "  return this;\n"
618    "}\n");
619
620  WriteFieldDocComment(printer, descriptor_);
621  printer->Print(variables_,
622    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
623    "    com.google.protobuf.ByteString value) {\n"
624    "$null_check$");
625  if (CheckUtf8(descriptor_)) {
626    printer->Print(variables_,
627      "  checkByteStringIsUtf8(value);\n");
628  }
629  printer->Print(variables_,
630    "  $set_oneof_case_message$;\n"
631    "  $oneof_name$_ = value;\n"
632    "  $on_changed$\n"
633    "  return this;\n"
634    "}\n");
635}
636
637void ImmutableStringOneofFieldGenerator::
638GenerateMergingCode(io::Printer* printer) const {
639  // Allow a slight breach of abstraction here in order to avoid forcing
640  // all string fields to Strings when copying fields from a Message.
641  printer->Print(variables_,
642    "$set_oneof_case_message$;\n"
643    "$oneof_name$_ = other.$oneof_name$_;\n"
644    "$on_changed$\n");
645}
646
647void ImmutableStringOneofFieldGenerator::
648GenerateBuildingCode(io::Printer* printer) const {
649  printer->Print(variables_,
650    "if ($has_oneof_case_message$) {\n"
651    "  result.$oneof_name$_ = $oneof_name$_;\n"
652    "}\n");
653}
654
655void ImmutableStringOneofFieldGenerator::
656GenerateParsingCode(io::Printer* printer) const {
657  if (CheckUtf8(descriptor_)) {
658    printer->Print(variables_,
659      "String s = input.readStringRequireUtf8();\n"
660      "$set_oneof_case_message$;\n"
661      "$oneof_name$_ = s;\n}\n");
662  } else {
663    printer->Print(variables_,
664      "com.google.protobuf.ByteString bs = input.readBytes();\n"
665      "$set_oneof_case_message$;\n"
666      "$oneof_name$_ = bs;\n");
667  }
668}
669
670void ImmutableStringOneofFieldGenerator::
671GenerateSerializationCode(io::Printer* printer) const {
672  printer->Print(variables_,
673    "if ($has_oneof_case_message$) {\n"
674    "  output.writeBytes($number$, get$capitalized_name$Bytes());\n"
675    "}\n");
676}
677
678void ImmutableStringOneofFieldGenerator::
679GenerateSerializedSizeCode(io::Printer* printer) const {
680  printer->Print(variables_,
681    "if ($has_oneof_case_message$) {\n"
682    "  size += com.google.protobuf.CodedOutputStream\n"
683    "    .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
684    "}\n");
685}
686
687// ===================================================================
688
689RepeatedImmutableStringFieldGenerator::
690RepeatedImmutableStringFieldGenerator(const FieldDescriptor* descriptor,
691                                      int messageBitIndex,
692                                      int builderBitIndex,
693                                      Context* context)
694  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
695    builderBitIndex_(builderBitIndex), context_(context),
696    name_resolver_(context->GetNameResolver()) {
697  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
698                        context->GetFieldGeneratorInfo(descriptor),
699                        name_resolver_, &variables_);
700}
701
702RepeatedImmutableStringFieldGenerator::
703~RepeatedImmutableStringFieldGenerator() {}
704
705int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const {
706  return 0;
707}
708
709int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
710  return 1;
711}
712
713void RepeatedImmutableStringFieldGenerator::
714GenerateInterfaceMembers(io::Printer* printer) const {
715  WriteFieldDocComment(printer, descriptor_);
716  printer->Print(variables_,
717    "$deprecation$com.google.protobuf.ProtocolStringList\n"
718    "    get$capitalized_name$List();\n");
719  WriteFieldDocComment(printer, descriptor_);
720  printer->Print(variables_,
721    "$deprecation$int get$capitalized_name$Count();\n");
722  WriteFieldDocComment(printer, descriptor_);
723  printer->Print(variables_,
724    "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
725  WriteFieldDocComment(printer, descriptor_);
726  printer->Print(variables_,
727    "$deprecation$com.google.protobuf.ByteString\n"
728    "    get$capitalized_name$Bytes(int index);\n");
729}
730
731
732void RepeatedImmutableStringFieldGenerator::
733GenerateMembers(io::Printer* printer) const {
734  printer->Print(variables_,
735    "private com.google.protobuf.LazyStringList $name$_;\n");
736  PrintExtraFieldInfo(variables_, printer);
737  WriteFieldDocComment(printer, descriptor_);
738  printer->Print(variables_,
739    "$deprecation$public com.google.protobuf.ProtocolStringList\n"
740    "    get$capitalized_name$List() {\n"
741    "  return $name$_;\n"   // note:  unmodifiable list
742    "}\n");
743  WriteFieldDocComment(printer, descriptor_);
744  printer->Print(variables_,
745    "$deprecation$public int get$capitalized_name$Count() {\n"
746    "  return $name$_.size();\n"
747    "}\n");
748  WriteFieldDocComment(printer, descriptor_);
749  printer->Print(variables_,
750    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
751    "  return $name$_.get(index);\n"
752    "}\n");
753  WriteFieldDocComment(printer, descriptor_);
754  printer->Print(variables_,
755    "$deprecation$public com.google.protobuf.ByteString\n"
756    "    get$capitalized_name$Bytes(int index) {\n"
757    "  return $name$_.getByteString(index);\n"
758    "}\n");
759
760  if (descriptor_->options().packed() &&
761      HasGeneratedMethods(descriptor_->containing_type())) {
762    printer->Print(variables_,
763      "private int $name$MemoizedSerializedSize = -1;\n");
764  }
765}
766
767void RepeatedImmutableStringFieldGenerator::
768GenerateBuilderMembers(io::Printer* printer) const {
769  // One field is the list and the bit field keeps track of whether the
770  // list is immutable. If it's immutable, the invariant is that it must
771  // either an instance of Collections.emptyList() or it's an ArrayList
772  // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
773  // a refererence to the underlying ArrayList. This invariant allows us to
774  // share instances of lists between protocol buffers avoiding expensive
775  // memory allocations. Note, immutable is a strong guarantee here -- not
776  // just that the list cannot be modified via the reference but that the
777  // list can never be modified.
778  printer->Print(variables_,
779    "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
780
781  printer->Print(variables_,
782    "private void ensure$capitalized_name$IsMutable() {\n"
783    "  if (!$get_mutable_bit_builder$) {\n"
784    "    $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
785    "    $set_mutable_bit_builder$;\n"
786    "   }\n"
787    "}\n");
788
789    // Note:  We return an unmodifiable list because otherwise the caller
790    //   could hold on to the returned list and modify it after the message
791    //   has been built, thus mutating the message which is supposed to be
792    //   immutable.
793  WriteFieldDocComment(printer, descriptor_);
794  printer->Print(variables_,
795    "$deprecation$public com.google.protobuf.ProtocolStringList\n"
796    "    get$capitalized_name$List() {\n"
797    "  return $name$_.getUnmodifiableView();\n"
798    "}\n");
799  WriteFieldDocComment(printer, descriptor_);
800  printer->Print(variables_,
801    "$deprecation$public int get$capitalized_name$Count() {\n"
802    "  return $name$_.size();\n"
803    "}\n");
804  WriteFieldDocComment(printer, descriptor_);
805  printer->Print(variables_,
806    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
807    "  return $name$_.get(index);\n"
808    "}\n");
809  WriteFieldDocComment(printer, descriptor_);
810  printer->Print(variables_,
811    "$deprecation$public com.google.protobuf.ByteString\n"
812    "    get$capitalized_name$Bytes(int index) {\n"
813    "  return $name$_.getByteString(index);\n"
814    "}\n");
815  WriteFieldDocComment(printer, descriptor_);
816  printer->Print(variables_,
817    "$deprecation$public Builder set$capitalized_name$(\n"
818    "    int index, java.lang.String value) {\n"
819    "$null_check$"
820    "  ensure$capitalized_name$IsMutable();\n"
821    "  $name$_.set(index, value);\n"
822    "  $on_changed$\n"
823    "  return this;\n"
824    "}\n");
825  WriteFieldDocComment(printer, descriptor_);
826  printer->Print(variables_,
827    "$deprecation$public Builder add$capitalized_name$(\n"
828    "    java.lang.String value) {\n"
829    "$null_check$"
830    "  ensure$capitalized_name$IsMutable();\n"
831    "  $name$_.add(value);\n"
832    "  $on_changed$\n"
833    "  return this;\n"
834    "}\n");
835  WriteFieldDocComment(printer, descriptor_);
836  printer->Print(variables_,
837    "$deprecation$public Builder addAll$capitalized_name$(\n"
838    "    java.lang.Iterable<java.lang.String> values) {\n"
839    "  ensure$capitalized_name$IsMutable();\n"
840    "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
841    "      values, $name$_);\n"
842    "  $on_changed$\n"
843    "  return this;\n"
844    "}\n");
845  WriteFieldDocComment(printer, descriptor_);
846  printer->Print(variables_,
847    "$deprecation$public Builder clear$capitalized_name$() {\n"
848    "  $name$_ = $empty_list$;\n"
849    "  $clear_mutable_bit_builder$;\n"
850    "  $on_changed$\n"
851    "  return this;\n"
852    "}\n");
853
854  WriteFieldDocComment(printer, descriptor_);
855  printer->Print(variables_,
856    "$deprecation$public Builder add$capitalized_name$Bytes(\n"
857    "    com.google.protobuf.ByteString value) {\n"
858    "$null_check$");
859  if (CheckUtf8(descriptor_)) {
860    printer->Print(variables_,
861      "  checkByteStringIsUtf8(value);\n");
862  }
863  printer->Print(variables_,
864    "  ensure$capitalized_name$IsMutable();\n"
865    "  $name$_.add(value);\n"
866    "  $on_changed$\n"
867    "  return this;\n"
868    "}\n");
869}
870
871void RepeatedImmutableStringFieldGenerator::
872GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
873  // noop for primitives
874}
875
876void RepeatedImmutableStringFieldGenerator::
877GenerateInitializationCode(io::Printer* printer) const {
878  printer->Print(variables_, "$name$_ = $empty_list$;\n");
879}
880
881void RepeatedImmutableStringFieldGenerator::
882GenerateBuilderClearCode(io::Printer* printer) const {
883  printer->Print(variables_,
884    "$name$_ = $empty_list$;\n"
885    "$clear_mutable_bit_builder$;\n");
886}
887
888void RepeatedImmutableStringFieldGenerator::
889GenerateMergingCode(io::Printer* printer) const {
890  // The code below does two optimizations:
891  //   1. If the other list is empty, there's nothing to do. This ensures we
892  //      don't allocate a new array if we already have an immutable one.
893  //   2. If the other list is non-empty and our current list is empty, we can
894  //      reuse the other list which is guaranteed to be immutable.
895  printer->Print(variables_,
896    "if (!other.$name$_.isEmpty()) {\n"
897    "  if ($name$_.isEmpty()) {\n"
898    "    $name$_ = other.$name$_;\n"
899    "    $clear_mutable_bit_builder$;\n"
900    "  } else {\n"
901    "    ensure$capitalized_name$IsMutable();\n"
902    "    $name$_.addAll(other.$name$_);\n"
903    "  }\n"
904    "  $on_changed$\n"
905    "}\n");
906}
907
908void RepeatedImmutableStringFieldGenerator::
909GenerateBuildingCode(io::Printer* printer) const {
910  // The code below ensures that the result has an immutable list. If our
911  // list is immutable, we can just reuse it. If not, we make it immutable.
912
913  printer->Print(variables_,
914    "if ($get_mutable_bit_builder$) {\n"
915    "  $name$_ = $name$_.getUnmodifiableView();\n"
916    "  $clear_mutable_bit_builder$;\n"
917    "}\n"
918    "result.$name$_ = $name$_;\n");
919}
920
921void RepeatedImmutableStringFieldGenerator::
922GenerateParsingCode(io::Printer* printer) const {
923  if (CheckUtf8(descriptor_)) {
924    printer->Print(variables_,
925    "String s = input.readStringRequireUtf8();\n");
926  } else {
927    printer->Print(variables_,
928    "com.google.protobuf.ByteString bs = input.readBytes();\n");
929  }
930  printer->Print(variables_,
931    "if (!$get_mutable_bit_parser$) {\n"
932    "  $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
933    "  $set_mutable_bit_parser$;\n"
934    "}\n");
935  if (CheckUtf8(descriptor_)) {
936    printer->Print(variables_,
937      "$name$_.add(s);\n");
938  } else {
939    printer->Print(variables_,
940      "$name$_.add(bs);\n");
941  }
942}
943
944void RepeatedImmutableStringFieldGenerator::
945GenerateParsingCodeFromPacked(io::Printer* printer) const {
946  printer->Print(variables_,
947    "int length = input.readRawVarint32();\n"
948    "int limit = input.pushLimit(length);\n"
949    "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
950    "  $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
951    "  $set_mutable_bit_parser$;\n"
952    "}\n"
953    "while (input.getBytesUntilLimit() > 0) {\n");
954  if (CheckUtf8(descriptor_)) {
955    printer->Print(variables_,
956      "  String s = input.readStringRequireUtf8();\n");
957  } else {
958    printer->Print(variables_,
959      "  String s = input.readString();\n");
960  }
961  printer->Print(variables_,
962    "  $name$.add(s);\n");
963  printer->Print(variables_,
964    "}\n"
965    "input.popLimit(limit);\n");
966}
967
968void RepeatedImmutableStringFieldGenerator::
969GenerateParsingDoneCode(io::Printer* printer) const {
970  printer->Print(variables_,
971    "if ($get_mutable_bit_parser$) {\n"
972    "  $name$_ = $name$_.getUnmodifiableView();\n"
973    "}\n");
974}
975
976void RepeatedImmutableStringFieldGenerator::
977GenerateSerializationCode(io::Printer* printer) const {
978  if (descriptor_->options().packed()) {
979    printer->Print(variables_,
980      "if (get$capitalized_name$List().size() > 0) {\n"
981      "  output.writeRawVarint32($tag$);\n"
982      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
983      "}\n"
984      "for (int i = 0; i < $name$_.size(); i++) {\n"
985      "  output.write$capitalized_type$NoTag($name$_.get(i));\n"
986      "}\n");
987  } else {
988    printer->Print(variables_,
989      "for (int i = 0; i < $name$_.size(); i++) {\n"
990      "  output.writeBytes($number$, $name$_.getByteString(i));\n"
991      "}\n");
992  }
993}
994
995void RepeatedImmutableStringFieldGenerator::
996GenerateSerializedSizeCode(io::Printer* printer) const {
997  printer->Print(variables_,
998    "{\n"
999    "  int dataSize = 0;\n");
1000  printer->Indent();
1001
1002  printer->Print(variables_,
1003    "for (int i = 0; i < $name$_.size(); i++) {\n"
1004    "  dataSize += com.google.protobuf.CodedOutputStream\n"
1005    "    .computeBytesSizeNoTag($name$_.getByteString(i));\n"
1006    "}\n");
1007
1008  printer->Print(
1009      "size += dataSize;\n");
1010
1011  if (descriptor_->options().packed()) {
1012    printer->Print(variables_,
1013      "if (!get$capitalized_name$List().isEmpty()) {\n"
1014      "  size += $tag_size$;\n"
1015      "  size += com.google.protobuf.CodedOutputStream\n"
1016      "      .computeInt32SizeNoTag(dataSize);\n"
1017      "}\n");
1018  } else {
1019    printer->Print(variables_,
1020      "size += $tag_size$ * get$capitalized_name$List().size();\n");
1021  }
1022
1023  // cache the data size for packed fields.
1024  if (descriptor_->options().packed()) {
1025    printer->Print(variables_,
1026      "$name$MemoizedSerializedSize = dataSize;\n");
1027  }
1028
1029  printer->Outdent();
1030  printer->Print("}\n");
1031}
1032
1033void RepeatedImmutableStringFieldGenerator::
1034GenerateEqualsCode(io::Printer* printer) const {
1035  printer->Print(variables_,
1036    "result = result && get$capitalized_name$List()\n"
1037    "    .equals(other.get$capitalized_name$List());\n");
1038}
1039
1040void RepeatedImmutableStringFieldGenerator::
1041GenerateHashCode(io::Printer* printer) const {
1042  printer->Print(variables_,
1043    "if (get$capitalized_name$Count() > 0) {\n"
1044    "  hash = (37 * hash) + $constant_name$;\n"
1045    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
1046    "}\n");
1047}
1048
1049string RepeatedImmutableStringFieldGenerator::GetBoxedType() const {
1050  return "String";
1051}
1052
1053}  // namespace java
1054}  // namespace compiler
1055}  // namespace protobuf
1056}  // namespace google
1057