• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 // Author: jonp@google.com (Jon Perlow)
33 //  Based on original Protocol Buffers design by
34 //  Sanjay Ghemawat, Jeff Dean, and others.
35 
36 #include <map>
37 #include <string>
38 
39 #include <google/protobuf/stubs/logging.h>
40 #include <google/protobuf/stubs/common.h>
41 #include <google/protobuf/compiler/java/java_context.h>
42 #include <google/protobuf/compiler/java/java_doc_comment.h>
43 #include <google/protobuf/compiler/java/java_helpers.h>
44 #include <google/protobuf/compiler/java/java_name_resolver.h>
45 #include <google/protobuf/compiler/java/java_string_field.h>
46 #include <google/protobuf/io/printer.h>
47 #include <google/protobuf/wire_format.h>
48 #include <google/protobuf/stubs/strutil.h>
49 
50 namespace google {
51 namespace protobuf {
52 namespace compiler {
53 namespace java {
54 
55 using internal::WireFormat;
56 using internal::WireFormatLite;
57 
58 namespace {
59 
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables)60 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
61                            int messageBitIndex, int builderBitIndex,
62                            const FieldGeneratorInfo* info,
63                            ClassNameResolver* name_resolver,
64                            std::map<std::string, std::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"] =
74       StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
75   (*variables)["tag_size"] = StrCat(
76       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
77   (*variables)["null_check"] =
78       "  if (value == null) {\n"
79       "    throw new NullPointerException();\n"
80       "  }\n";
81   (*variables)["writeString"] = "com.google.protobuf.GeneratedMessage" +
82                                 GeneratedCodeVersionSuffix() + ".writeString";
83   (*variables)["computeStringSize"] = "com.google.protobuf.GeneratedMessage" +
84                                       GeneratedCodeVersionSuffix() +
85                                       ".computeStringSize";
86 
87   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
88   // by the proto compiler
89   (*variables)["deprecation"] =
90       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
91   (*variables)["on_changed"] = "onChanged();";
92 
93   if (HasHasbit(descriptor)) {
94     // For singular messages and builders, one bit is used for the hasField bit.
95     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
96     (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
97 
98     // Note that these have a trailing ";".
99     (*variables)["set_has_field_bit_message"] =
100         GenerateSetBit(messageBitIndex) + ";";
101     (*variables)["set_has_field_bit_builder"] =
102         GenerateSetBit(builderBitIndex) + ";";
103     (*variables)["clear_has_field_bit_builder"] =
104         GenerateClearBit(builderBitIndex) + ";";
105 
106     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
107   } else {
108     (*variables)["set_has_field_bit_message"] = "";
109     (*variables)["set_has_field_bit_builder"] = "";
110     (*variables)["clear_has_field_bit_builder"] = "";
111 
112     (*variables)["is_field_present_message"] =
113         "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()";
114   }
115 
116   // For repeated builders, one bit is used for whether the array is immutable.
117   (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
118   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
119   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
120 
121   (*variables)["get_has_field_bit_from_local"] =
122       GenerateGetBitFromLocal(builderBitIndex);
123   (*variables)["set_has_field_bit_to_local"] =
124       GenerateSetBitToLocal(messageBitIndex);
125 }
126 
127 }  // namespace
128 
129 // ===================================================================
130 
ImmutableStringFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)131 ImmutableStringFieldGenerator::ImmutableStringFieldGenerator(
132     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
133     Context* context)
134     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
135   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
136                         context->GetFieldGeneratorInfo(descriptor),
137                         name_resolver_, &variables_);
138 }
139 
~ImmutableStringFieldGenerator()140 ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
141 
GetNumBitsForMessage() const142 int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
143   return HasHasbit(descriptor_) ? 1 : 0;
144 }
145 
GetNumBitsForBuilder() const146 int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
147   return GetNumBitsForMessage();
148 }
149 
150 // A note about how strings are handled. This code used to just store a String
151 // in the Message. This had two issues:
152 //
153 //  1. It wouldn't roundtrip byte arrays that were not valid UTF-8 encoded
154 //     strings, but rather fields that were raw bytes incorrectly marked
155 //     as strings in the proto file. This is common because in the proto1
156 //     syntax, string was the way to indicate bytes and C++ engineers can
157 //     easily make this mistake without affecting the C++ API. By converting to
158 //     strings immediately, some java code might corrupt these byte arrays as
159 //     it passes through a java server even if the field was never accessed by
160 //     application code.
161 //
162 //  2. There's a performance hit to converting between bytes and strings and
163 //     it many cases, the field is never even read by the application code. This
164 //     avoids unnecessary conversions in the common use cases.
165 //
166 // So now, the field for String is maintained as an Object reference which can
167 // either store a String or a ByteString. The code uses an instanceof check
168 // to see which one it has and converts to the other one if needed. It remembers
169 // the last value requested (in a thread safe manner) as this is most likely
170 // the one needed next. The thread safety is such that if two threads both
171 // convert the field because the changes made by each thread were not visible to
172 // the other, they may cause a conversion to happen more times than would
173 // otherwise be necessary. This was deemed better than adding synchronization
174 // overhead. It will not cause any corruption issues or affect the behavior of
175 // the API. The instanceof check is also highly optimized in the JVM and we
176 // decided it was better to reduce the memory overhead by not having two
177 // separate fields but rather use dynamic type checking.
178 //
179 // For single fields, the logic for this is done inside the generated code. For
180 // repeated fields, the logic is done in LazyStringArrayList and
181 // UnmodifiableLazyStringList.
GenerateInterfaceMembers(io::Printer * printer) const182 void ImmutableStringFieldGenerator::GenerateInterfaceMembers(
183     io::Printer* printer) const {
184   if (SupportFieldPresence(descriptor_)) {
185     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
186     printer->Print(variables_,
187                    "$deprecation$boolean has$capitalized_name$();\n");
188   }
189   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
190   printer->Print(variables_,
191                  "$deprecation$java.lang.String get$capitalized_name$();\n");
192   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
193   printer->Print(variables_,
194                  "$deprecation$com.google.protobuf.ByteString\n"
195                  "    get$capitalized_name$Bytes();\n");
196 }
197 
GenerateMembers(io::Printer * printer) const198 void ImmutableStringFieldGenerator::GenerateMembers(
199     io::Printer* printer) const {
200   printer->Print(variables_, "private volatile java.lang.Object $name$_;\n");
201   PrintExtraFieldInfo(variables_, printer);
202 
203   if (SupportFieldPresence(descriptor_)) {
204     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
205     printer->Print(
206         variables_,
207         "@java.lang.Override\n"
208         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
209         "  return $get_has_field_bit_message$;\n"
210         "}\n");
211     printer->Annotate("{", "}", descriptor_);
212   }
213 
214   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
215   printer->Print(
216       variables_,
217       "@java.lang.Override\n"
218       "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
219       "  java.lang.Object ref = $name$_;\n"
220       "  if (ref instanceof java.lang.String) {\n"
221       "    return (java.lang.String) ref;\n"
222       "  } else {\n"
223       "    com.google.protobuf.ByteString bs = \n"
224       "        (com.google.protobuf.ByteString) ref;\n"
225       "    java.lang.String s = bs.toStringUtf8();\n");
226   printer->Annotate("{", "}", descriptor_);
227   if (CheckUtf8(descriptor_)) {
228     printer->Print(variables_, "    $name$_ = s;\n");
229   } else {
230     printer->Print(variables_,
231                    "    if (bs.isValidUtf8()) {\n"
232                    "      $name$_ = s;\n"
233                    "    }\n");
234   }
235   printer->Print(variables_,
236                  "    return s;\n"
237                  "  }\n"
238                  "}\n");
239   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
240   printer->Print(variables_,
241                  "@java.lang.Override\n"
242                  "$deprecation$public com.google.protobuf.ByteString\n"
243                  "    ${$get$capitalized_name$Bytes$}$() {\n"
244                  "  java.lang.Object ref = $name$_;\n"
245                  "  if (ref instanceof java.lang.String) {\n"
246                  "    com.google.protobuf.ByteString b = \n"
247                  "        com.google.protobuf.ByteString.copyFromUtf8(\n"
248                  "            (java.lang.String) ref);\n"
249                  "    $name$_ = b;\n"
250                  "    return b;\n"
251                  "  } else {\n"
252                  "    return (com.google.protobuf.ByteString) ref;\n"
253                  "  }\n"
254                  "}\n");
255   printer->Annotate("{", "}", descriptor_);
256 }
257 
GenerateBuilderMembers(io::Printer * printer) const258 void ImmutableStringFieldGenerator::GenerateBuilderMembers(
259     io::Printer* printer) const {
260   printer->Print(variables_,
261                  "private java.lang.Object $name$_ $default_init$;\n");
262   if (SupportFieldPresence(descriptor_)) {
263     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
264     printer->Print(
265         variables_,
266         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
267         "  return $get_has_field_bit_builder$;\n"
268         "}\n");
269     printer->Annotate("{", "}", descriptor_);
270   }
271 
272   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
273   printer->Print(
274       variables_,
275       "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
276       "  java.lang.Object ref = $name$_;\n"
277       "  if (!(ref instanceof java.lang.String)) {\n"
278       "    com.google.protobuf.ByteString bs =\n"
279       "        (com.google.protobuf.ByteString) ref;\n"
280       "    java.lang.String s = bs.toStringUtf8();\n");
281   printer->Annotate("{", "}", descriptor_);
282   if (CheckUtf8(descriptor_)) {
283     printer->Print(variables_, "    $name$_ = s;\n");
284   } else {
285     printer->Print(variables_,
286                    "    if (bs.isValidUtf8()) {\n"
287                    "      $name$_ = s;\n"
288                    "    }\n");
289   }
290   printer->Print(variables_,
291                  "    return s;\n"
292                  "  } else {\n"
293                  "    return (java.lang.String) ref;\n"
294                  "  }\n"
295                  "}\n");
296 
297   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
298   printer->Print(variables_,
299                  "$deprecation$public com.google.protobuf.ByteString\n"
300                  "    ${$get$capitalized_name$Bytes$}$() {\n"
301                  "  java.lang.Object ref = $name$_;\n"
302                  "  if (ref instanceof String) {\n"
303                  "    com.google.protobuf.ByteString b = \n"
304                  "        com.google.protobuf.ByteString.copyFromUtf8(\n"
305                  "            (java.lang.String) ref);\n"
306                  "    $name$_ = b;\n"
307                  "    return b;\n"
308                  "  } else {\n"
309                  "    return (com.google.protobuf.ByteString) ref;\n"
310                  "  }\n"
311                  "}\n");
312   printer->Annotate("{", "}", descriptor_);
313 
314   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
315                                /* builder */ true);
316   printer->Print(variables_,
317                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
318                  "    java.lang.String value) {\n"
319                  "$null_check$"
320                  "  $set_has_field_bit_builder$\n"
321                  "  $name$_ = value;\n"
322                  "  $on_changed$\n"
323                  "  return this;\n"
324                  "}\n");
325   printer->Annotate("{", "}", descriptor_);
326   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
327                                /* builder */ true);
328   printer->Print(
329       variables_,
330       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
331       "  $clear_has_field_bit_builder$\n");
332   printer->Annotate("{", "}", descriptor_);
333   // The default value is not a simple literal so we want to avoid executing
334   // it multiple times.  Instead, get the default out of the default instance.
335   printer->Print(variables_,
336                  "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
337   printer->Print(variables_,
338                  "  $on_changed$\n"
339                  "  return this;\n"
340                  "}\n");
341 
342   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
343                                           /* builder */ true);
344   printer->Print(
345       variables_,
346       "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
347       "    com.google.protobuf.ByteString value) {\n"
348       "$null_check$");
349   printer->Annotate("{", "}", descriptor_);
350   if (CheckUtf8(descriptor_)) {
351     printer->Print(variables_, "  checkByteStringIsUtf8(value);\n");
352   }
353   printer->Print(variables_,
354                  "  $set_has_field_bit_builder$\n"
355                  "  $name$_ = value;\n"
356                  "  $on_changed$\n"
357                  "  return this;\n"
358                  "}\n");
359 }
360 
GenerateFieldBuilderInitializationCode(io::Printer * printer) const361 void ImmutableStringFieldGenerator::GenerateFieldBuilderInitializationCode(
362     io::Printer* printer) const {
363   // noop for primitives
364 }
365 
GenerateInitializationCode(io::Printer * printer) const366 void ImmutableStringFieldGenerator::GenerateInitializationCode(
367     io::Printer* printer) const {
368   printer->Print(variables_, "$name$_ = $default$;\n");
369 }
370 
GenerateBuilderClearCode(io::Printer * printer) const371 void ImmutableStringFieldGenerator::GenerateBuilderClearCode(
372     io::Printer* printer) const {
373   printer->Print(variables_,
374                  "$name$_ = $default$;\n"
375                  "$clear_has_field_bit_builder$\n");
376 }
377 
GenerateMergingCode(io::Printer * printer) const378 void ImmutableStringFieldGenerator::GenerateMergingCode(
379     io::Printer* printer) const {
380   if (SupportFieldPresence(descriptor_)) {
381     // Allow a slight breach of abstraction here in order to avoid forcing
382     // all string fields to Strings when copying fields from a Message.
383     printer->Print(variables_,
384                    "if (other.has$capitalized_name$()) {\n"
385                    "  $set_has_field_bit_builder$\n"
386                    "  $name$_ = other.$name$_;\n"
387                    "  $on_changed$\n"
388                    "}\n");
389   } else {
390     printer->Print(variables_,
391                    "if (!other.get$capitalized_name$().isEmpty()) {\n"
392                    "  $name$_ = other.$name$_;\n"
393                    "  $on_changed$\n"
394                    "}\n");
395   }
396 }
397 
GenerateBuildingCode(io::Printer * printer) const398 void ImmutableStringFieldGenerator::GenerateBuildingCode(
399     io::Printer* printer) const {
400   if (SupportFieldPresence(descriptor_)) {
401     printer->Print(variables_,
402                    "if ($get_has_field_bit_from_local$) {\n"
403                    "  $set_has_field_bit_to_local$;\n"
404                    "}\n");
405   }
406   printer->Print(variables_, "result.$name$_ = $name$_;\n");
407 }
408 
GenerateBuilderParsingCode(io::Printer * printer) const409 void ImmutableStringFieldGenerator::GenerateBuilderParsingCode(
410     io::Printer* printer) const {
411   if (CheckUtf8(descriptor_)) {
412     printer->Print(variables_,
413                    "$name$_ = input.readStringRequireUtf8();\n"
414                    "$set_has_field_bit_builder$\n");
415   } else {
416     printer->Print(variables_,
417                    "$name$_ = input.readBytes();\n"
418                    "$set_has_field_bit_builder$\n");
419   }
420 }
421 
GenerateSerializationCode(io::Printer * printer) const422 void ImmutableStringFieldGenerator::GenerateSerializationCode(
423     io::Printer* printer) const {
424   printer->Print(variables_,
425                  "if ($is_field_present_message$) {\n"
426                  "  $writeString$(output, $number$, $name$_);\n"
427                  "}\n");
428 }
429 
GenerateSerializedSizeCode(io::Printer * printer) const430 void ImmutableStringFieldGenerator::GenerateSerializedSizeCode(
431     io::Printer* printer) const {
432   printer->Print(variables_,
433                  "if ($is_field_present_message$) {\n"
434                  "  size += $computeStringSize$($number$, $name$_);\n"
435                  "}\n");
436 }
437 
GenerateEqualsCode(io::Printer * printer) const438 void ImmutableStringFieldGenerator::GenerateEqualsCode(
439     io::Printer* printer) const {
440   printer->Print(variables_,
441                  "if (!get$capitalized_name$()\n"
442                  "    .equals(other.get$capitalized_name$())) return false;\n");
443 }
444 
GenerateHashCode(io::Printer * printer) const445 void ImmutableStringFieldGenerator::GenerateHashCode(
446     io::Printer* printer) const {
447   printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
448   printer->Print(variables_,
449                  "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
450 }
451 
GetBoxedType() const452 std::string ImmutableStringFieldGenerator::GetBoxedType() const {
453   return "java.lang.String";
454 }
455 
456 // ===================================================================
457 
ImmutableStringOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)458 ImmutableStringOneofFieldGenerator::ImmutableStringOneofFieldGenerator(
459     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
460     Context* context)
461     : ImmutableStringFieldGenerator(descriptor, messageBitIndex,
462                                     builderBitIndex, context) {
463   const OneofGeneratorInfo* info =
464       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
465   SetCommonOneofVariables(descriptor, info, &variables_);
466 }
467 
~ImmutableStringOneofFieldGenerator()468 ImmutableStringOneofFieldGenerator::~ImmutableStringOneofFieldGenerator() {}
469 
GenerateMembers(io::Printer * printer) const470 void ImmutableStringOneofFieldGenerator::GenerateMembers(
471     io::Printer* printer) const {
472   PrintExtraFieldInfo(variables_, printer);
473 
474   if (SupportFieldPresence(descriptor_)) {
475     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
476     printer->Print(
477         variables_,
478         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
479         "  return $has_oneof_case_message$;\n"
480         "}\n");
481     printer->Annotate("{", "}", descriptor_);
482   }
483 
484   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
485   printer->Print(
486       variables_,
487       "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
488       "  java.lang.Object ref $default_init$;\n"
489       "  if ($has_oneof_case_message$) {\n"
490       "    ref = $oneof_name$_;\n"
491       "  }\n"
492       "  if (ref instanceof java.lang.String) {\n"
493       "    return (java.lang.String) ref;\n"
494       "  } else {\n"
495       "    com.google.protobuf.ByteString bs = \n"
496       "        (com.google.protobuf.ByteString) ref;\n"
497       "    java.lang.String s = bs.toStringUtf8();\n");
498   printer->Annotate("{", "}", descriptor_);
499   if (CheckUtf8(descriptor_)) {
500     printer->Print(variables_,
501                    "    if ($has_oneof_case_message$) {\n"
502                    "      $oneof_name$_ = s;\n"
503                    "    }\n");
504   } else {
505     printer->Print(variables_,
506                    "    if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
507                    "      $oneof_name$_ = s;\n"
508                    "    }\n");
509   }
510   printer->Print(variables_,
511                  "    return s;\n"
512                  "  }\n"
513                  "}\n");
514   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
515 
516   printer->Print(variables_,
517                  "$deprecation$public com.google.protobuf.ByteString\n"
518                  "    ${$get$capitalized_name$Bytes$}$() {\n"
519                  "  java.lang.Object ref $default_init$;\n"
520                  "  if ($has_oneof_case_message$) {\n"
521                  "    ref = $oneof_name$_;\n"
522                  "  }\n"
523                  "  if (ref instanceof java.lang.String) {\n"
524                  "    com.google.protobuf.ByteString b = \n"
525                  "        com.google.protobuf.ByteString.copyFromUtf8(\n"
526                  "            (java.lang.String) ref);\n"
527                  "    if ($has_oneof_case_message$) {\n"
528                  "      $oneof_name$_ = b;\n"
529                  "    }\n"
530                  "    return b;\n"
531                  "  } else {\n"
532                  "    return (com.google.protobuf.ByteString) ref;\n"
533                  "  }\n"
534                  "}\n");
535   printer->Annotate("{", "}", descriptor_);
536 }
537 
GenerateBuilderMembers(io::Printer * printer) const538 void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
539     io::Printer* printer) const {
540   if (SupportFieldPresence(descriptor_)) {
541     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
542     printer->Print(
543         variables_,
544         "@java.lang.Override\n"
545         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
546         "  return $has_oneof_case_message$;\n"
547         "}\n");
548     printer->Annotate("{", "}", descriptor_);
549   }
550 
551   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
552   printer->Print(
553       variables_,
554       "@java.lang.Override\n"
555       "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
556       "  java.lang.Object ref $default_init$;\n"
557       "  if ($has_oneof_case_message$) {\n"
558       "    ref = $oneof_name$_;\n"
559       "  }\n"
560       "  if (!(ref instanceof java.lang.String)) {\n"
561       "    com.google.protobuf.ByteString bs =\n"
562       "        (com.google.protobuf.ByteString) ref;\n"
563       "    java.lang.String s = bs.toStringUtf8();\n"
564       "    if ($has_oneof_case_message$) {\n");
565   printer->Annotate("{", "}", descriptor_);
566   if (CheckUtf8(descriptor_)) {
567     printer->Print(variables_, "      $oneof_name$_ = s;\n");
568   } else {
569     printer->Print(variables_,
570                    "      if (bs.isValidUtf8()) {\n"
571                    "        $oneof_name$_ = s;\n"
572                    "      }\n");
573   }
574   printer->Print(variables_,
575                  "    }\n"
576                  "    return s;\n"
577                  "  } else {\n"
578                  "    return (java.lang.String) ref;\n"
579                  "  }\n"
580                  "}\n");
581 
582   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
583   printer->Print(variables_,
584                  "@java.lang.Override\n"
585                  "$deprecation$public com.google.protobuf.ByteString\n"
586                  "    ${$get$capitalized_name$Bytes$}$() {\n"
587                  "  java.lang.Object ref $default_init$;\n"
588                  "  if ($has_oneof_case_message$) {\n"
589                  "    ref = $oneof_name$_;\n"
590                  "  }\n"
591                  "  if (ref instanceof String) {\n"
592                  "    com.google.protobuf.ByteString b = \n"
593                  "        com.google.protobuf.ByteString.copyFromUtf8(\n"
594                  "            (java.lang.String) ref);\n"
595                  "    if ($has_oneof_case_message$) {\n"
596                  "      $oneof_name$_ = b;\n"
597                  "    }\n"
598                  "    return b;\n"
599                  "  } else {\n"
600                  "    return (com.google.protobuf.ByteString) ref;\n"
601                  "  }\n"
602                  "}\n");
603   printer->Annotate("{", "}", descriptor_);
604 
605   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
606                                /* builder */ true);
607   printer->Print(variables_,
608                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
609                  "    java.lang.String value) {\n"
610                  "$null_check$"
611                  "  $set_oneof_case_message$;\n"
612                  "  $oneof_name$_ = value;\n"
613                  "  $on_changed$\n"
614                  "  return this;\n"
615                  "}\n");
616   printer->Annotate("{", "}", descriptor_);
617   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
618                                /* builder */ true);
619   printer->Print(
620       variables_,
621       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
622       "  if ($has_oneof_case_message$) {\n"
623       "    $clear_oneof_case_message$;\n"
624       "    $oneof_name$_ = null;\n"
625       "    $on_changed$\n"
626       "  }\n"
627       "  return this;\n"
628       "}\n");
629   printer->Annotate("{", "}", descriptor_);
630 
631   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
632                                           /* builder */ true);
633   printer->Print(
634       variables_,
635       "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
636       "    com.google.protobuf.ByteString value) {\n"
637       "$null_check$");
638   printer->Annotate("{", "}", descriptor_);
639   if (CheckUtf8(descriptor_)) {
640     printer->Print(variables_, "  checkByteStringIsUtf8(value);\n");
641   }
642   printer->Print(variables_,
643                  "  $set_oneof_case_message$;\n"
644                  "  $oneof_name$_ = value;\n"
645                  "  $on_changed$\n"
646                  "  return this;\n"
647                  "}\n");
648 }
649 
GenerateBuilderClearCode(io::Printer * printer) const650 void ImmutableStringOneofFieldGenerator::GenerateBuilderClearCode(
651     io::Printer* printer) const {
652   // No-Op: String fields in oneofs are correctly cleared by clearing the oneof
653 }
654 
GenerateMergingCode(io::Printer * printer) const655 void ImmutableStringOneofFieldGenerator::GenerateMergingCode(
656     io::Printer* printer) const {
657   // Allow a slight breach of abstraction here in order to avoid forcing
658   // all string fields to Strings when copying fields from a Message.
659   printer->Print(variables_,
660                  "$set_oneof_case_message$;\n"
661                  "$oneof_name$_ = other.$oneof_name$_;\n"
662                  "$on_changed$\n");
663 }
664 
GenerateBuildingCode(io::Printer * printer) const665 void ImmutableStringOneofFieldGenerator::GenerateBuildingCode(
666     io::Printer* printer) const {
667   printer->Print(variables_,
668                  "if ($has_oneof_case_message$) {\n"
669                  "  result.$oneof_name$_ = $oneof_name$_;\n"
670                  "}\n");
671 }
672 
GenerateBuilderParsingCode(io::Printer * printer) const673 void ImmutableStringOneofFieldGenerator::GenerateBuilderParsingCode(
674     io::Printer* printer) const {
675   if (CheckUtf8(descriptor_)) {
676     printer->Print(variables_,
677                    "java.lang.String s = input.readStringRequireUtf8();\n"
678                    "$set_oneof_case_message$;\n"
679                    "$oneof_name$_ = s;\n");
680   } else {
681     printer->Print(variables_,
682                    "com.google.protobuf.ByteString bs = input.readBytes();\n"
683                    "$set_oneof_case_message$;\n"
684                    "$oneof_name$_ = bs;\n");
685   }
686 }
687 
GenerateSerializationCode(io::Printer * printer) const688 void ImmutableStringOneofFieldGenerator::GenerateSerializationCode(
689     io::Printer* printer) const {
690   printer->Print(variables_,
691                  "if ($has_oneof_case_message$) {\n"
692                  "  $writeString$(output, $number$, $oneof_name$_);\n"
693                  "}\n");
694 }
695 
GenerateSerializedSizeCode(io::Printer * printer) const696 void ImmutableStringOneofFieldGenerator::GenerateSerializedSizeCode(
697     io::Printer* printer) const {
698   printer->Print(variables_,
699                  "if ($has_oneof_case_message$) {\n"
700                  "  size += $computeStringSize$($number$, $oneof_name$_);\n"
701                  "}\n");
702 }
703 
704 // ===================================================================
705 
RepeatedImmutableStringFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)706 RepeatedImmutableStringFieldGenerator::RepeatedImmutableStringFieldGenerator(
707     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
708     Context* context)
709     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
710   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
711                         context->GetFieldGeneratorInfo(descriptor),
712                         name_resolver_, &variables_);
713 }
714 
715 RepeatedImmutableStringFieldGenerator::
~RepeatedImmutableStringFieldGenerator()716     ~RepeatedImmutableStringFieldGenerator() {}
717 
GetNumBitsForMessage() const718 int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const {
719   return 0;
720 }
721 
GetNumBitsForBuilder() const722 int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
723   return 1;
724 }
725 
GenerateInterfaceMembers(io::Printer * printer) const726 void RepeatedImmutableStringFieldGenerator::GenerateInterfaceMembers(
727     io::Printer* printer) const {
728   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
729   printer->Print(
730       variables_,
731       // NOTE: the same method in the implementation class actually returns
732       // com.google.protobuf.ProtocolStringList (a subclass of List). It's
733       // changed between protobuf 2.5.0 release and protobuf 2.6.1 release.
734       // To retain binary compatibility with both 2.5.0 and 2.6.1 generated
735       // code, we make this interface method return List so both methods
736       // with different return types exist in the compiled byte code.
737       "$deprecation$java.util.List<java.lang.String>\n"
738       "    get$capitalized_name$List();\n");
739   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
740   printer->Print(variables_,
741                  "$deprecation$int get$capitalized_name$Count();\n");
742   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
743   printer->Print(
744       variables_,
745       "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
746   WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
747                                           LIST_INDEXED_GETTER);
748   printer->Print(variables_,
749                  "$deprecation$com.google.protobuf.ByteString\n"
750                  "    get$capitalized_name$Bytes(int index);\n");
751 }
752 
GenerateMembers(io::Printer * printer) const753 void RepeatedImmutableStringFieldGenerator::GenerateMembers(
754     io::Printer* printer) const {
755   printer->Print(variables_,
756                  "private com.google.protobuf.LazyStringList $name$_;\n");
757   PrintExtraFieldInfo(variables_, printer);
758   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
759   printer->Print(variables_,
760                  "$deprecation$public com.google.protobuf.ProtocolStringList\n"
761                  "    ${$get$capitalized_name$List$}$() {\n"
762                  "  return $name$_;\n"  // note:  unmodifiable list
763                  "}\n");
764   printer->Annotate("{", "}", descriptor_);
765   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
766   printer->Print(
767       variables_,
768       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
769       "  return $name$_.size();\n"
770       "}\n");
771   printer->Annotate("{", "}", descriptor_);
772   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
773   printer->Print(variables_,
774                  "$deprecation$public java.lang.String "
775                  "${$get$capitalized_name$$}$(int index) {\n"
776                  "  return $name$_.get(index);\n"
777                  "}\n");
778   printer->Annotate("{", "}", descriptor_);
779   WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
780                                           LIST_INDEXED_GETTER);
781   printer->Print(variables_,
782                  "$deprecation$public com.google.protobuf.ByteString\n"
783                  "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
784                  "  return $name$_.getByteString(index);\n"
785                  "}\n");
786   printer->Annotate("{", "}", descriptor_);
787 }
788 
GenerateBuilderMembers(io::Printer * printer) const789 void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
790     io::Printer* printer) const {
791   // One field is the list and the bit field keeps track of whether the
792   // list is immutable. If it's immutable, the invariant is that it must
793   // either an instance of Collections.emptyList() or it's an ArrayList
794   // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
795   // a reference to the underlying ArrayList. This invariant allows us to
796   // share instances of lists between protocol buffers avoiding expensive
797   // memory allocations. Note, immutable is a strong guarantee here -- not
798   // just that the list cannot be modified via the reference but that the
799   // list can never be modified.
800   printer->Print(
801       variables_,
802       "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
803 
804   printer->Print(
805       variables_,
806       "private void ensure$capitalized_name$IsMutable() {\n"
807       "  if (!$get_mutable_bit_builder$) {\n"
808       "    $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
809       "    $set_mutable_bit_builder$;\n"
810       "   }\n"
811       "}\n");
812 
813   // Note:  We return an unmodifiable list because otherwise the caller
814   //   could hold on to the returned list and modify it after the message
815   //   has been built, thus mutating the message which is supposed to be
816   //   immutable.
817   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
818   printer->Print(variables_,
819                  "$deprecation$public com.google.protobuf.ProtocolStringList\n"
820                  "    ${$get$capitalized_name$List$}$() {\n"
821                  "  return $name$_.getUnmodifiableView();\n"
822                  "}\n");
823   printer->Annotate("{", "}", descriptor_);
824   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
825   printer->Print(
826       variables_,
827       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
828       "  return $name$_.size();\n"
829       "}\n");
830   printer->Annotate("{", "}", descriptor_);
831   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
832   printer->Print(variables_,
833                  "$deprecation$public java.lang.String "
834                  "${$get$capitalized_name$$}$(int index) {\n"
835                  "  return $name$_.get(index);\n"
836                  "}\n");
837   printer->Annotate("{", "}", descriptor_);
838   WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
839                                           LIST_INDEXED_GETTER);
840   printer->Print(variables_,
841                  "$deprecation$public com.google.protobuf.ByteString\n"
842                  "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
843                  "  return $name$_.getByteString(index);\n"
844                  "}\n");
845   printer->Annotate("{", "}", descriptor_);
846   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
847                                /* builder */ true);
848   printer->Print(variables_,
849                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
850                  "    int index, java.lang.String value) {\n"
851                  "$null_check$"
852                  "  ensure$capitalized_name$IsMutable();\n"
853                  "  $name$_.set(index, value);\n"
854                  "  $on_changed$\n"
855                  "  return this;\n"
856                  "}\n");
857   printer->Annotate("{", "}", descriptor_);
858   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
859                                /* builder */ true);
860   printer->Print(variables_,
861                  "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
862                  "    java.lang.String value) {\n"
863                  "$null_check$"
864                  "  ensure$capitalized_name$IsMutable();\n"
865                  "  $name$_.add(value);\n"
866                  "  $on_changed$\n"
867                  "  return this;\n"
868                  "}\n");
869   printer->Annotate("{", "}", descriptor_);
870   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
871                                /* builder */ true);
872   printer->Print(variables_,
873                  "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
874                  "    java.lang.Iterable<java.lang.String> values) {\n"
875                  "  ensure$capitalized_name$IsMutable();\n"
876                  "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
877                  "      values, $name$_);\n"
878                  "  $on_changed$\n"
879                  "  return this;\n"
880                  "}\n");
881   printer->Annotate("{", "}", descriptor_);
882   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
883                                /* builder */ true);
884   printer->Print(
885       variables_,
886       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
887       "  $name$_ = $empty_list$;\n"
888       "  $clear_mutable_bit_builder$;\n"
889       "  $on_changed$\n"
890       "  return this;\n"
891       "}\n");
892   printer->Annotate("{", "}", descriptor_);
893 
894   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER,
895                                           /* builder */ true);
896   printer->Print(
897       variables_,
898       "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
899       "    com.google.protobuf.ByteString value) {\n"
900       "$null_check$");
901   printer->Annotate("{", "}", descriptor_);
902   if (CheckUtf8(descriptor_)) {
903     printer->Print(variables_, "  checkByteStringIsUtf8(value);\n");
904   }
905   printer->Print(variables_,
906                  "  ensure$capitalized_name$IsMutable();\n"
907                  "  $name$_.add(value);\n"
908                  "  $on_changed$\n"
909                  "  return this;\n"
910                  "}\n");
911 }
912 
913 void RepeatedImmutableStringFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const914     GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
915   // noop for primitives
916 }
917 
GenerateInitializationCode(io::Printer * printer) const918 void RepeatedImmutableStringFieldGenerator::GenerateInitializationCode(
919     io::Printer* printer) const {
920   printer->Print(variables_, "$name$_ = $empty_list$;\n");
921 }
922 
GenerateBuilderClearCode(io::Printer * printer) const923 void RepeatedImmutableStringFieldGenerator::GenerateBuilderClearCode(
924     io::Printer* printer) const {
925   printer->Print(variables_,
926                  "$name$_ = $empty_list$;\n"
927                  "$clear_mutable_bit_builder$;\n");
928 }
929 
GenerateMergingCode(io::Printer * printer) const930 void RepeatedImmutableStringFieldGenerator::GenerateMergingCode(
931     io::Printer* printer) const {
932   // The code below does two optimizations:
933   //   1. If the other list is empty, there's nothing to do. This ensures we
934   //      don't allocate a new array if we already have an immutable one.
935   //   2. If the other list is non-empty and our current list is empty, we can
936   //      reuse the other list which is guaranteed to be immutable.
937   printer->Print(variables_,
938                  "if (!other.$name$_.isEmpty()) {\n"
939                  "  if ($name$_.isEmpty()) {\n"
940                  "    $name$_ = other.$name$_;\n"
941                  "    $clear_mutable_bit_builder$;\n"
942                  "  } else {\n"
943                  "    ensure$capitalized_name$IsMutable();\n"
944                  "    $name$_.addAll(other.$name$_);\n"
945                  "  }\n"
946                  "  $on_changed$\n"
947                  "}\n");
948 }
949 
GenerateBuildingCode(io::Printer * printer) const950 void RepeatedImmutableStringFieldGenerator::GenerateBuildingCode(
951     io::Printer* printer) const {
952   // The code below ensures that the result has an immutable list. If our
953   // list is immutable, we can just reuse it. If not, we make it immutable.
954 
955   printer->Print(variables_,
956                  "if ($get_mutable_bit_builder$) {\n"
957                  "  $name$_ = $name$_.getUnmodifiableView();\n"
958                  "  $clear_mutable_bit_builder$;\n"
959                  "}\n"
960                  "result.$name$_ = $name$_;\n");
961 }
962 
GenerateBuilderParsingCode(io::Printer * printer) const963 void RepeatedImmutableStringFieldGenerator::GenerateBuilderParsingCode(
964     io::Printer* printer) const {
965   if (CheckUtf8(descriptor_)) {
966     printer->Print(variables_,
967                    "java.lang.String s = input.readStringRequireUtf8();\n"
968                    "ensure$capitalized_name$IsMutable();\n"
969                    "$name$_.add(s);\n");
970   } else {
971     printer->Print(variables_,
972                    "com.google.protobuf.ByteString bs = input.readBytes();\n"
973                    "ensure$capitalized_name$IsMutable();\n"
974                    "$name$_.add(bs);\n");
975   }
976 }
977 
GenerateSerializationCode(io::Printer * printer) const978 void RepeatedImmutableStringFieldGenerator::GenerateSerializationCode(
979     io::Printer* printer) const {
980   printer->Print(variables_,
981                  "for (int i = 0; i < $name$_.size(); i++) {\n"
982                  "  $writeString$(output, $number$, $name$_.getRaw(i));\n"
983                  "}\n");
984 }
985 
GenerateSerializedSizeCode(io::Printer * printer) const986 void RepeatedImmutableStringFieldGenerator::GenerateSerializedSizeCode(
987     io::Printer* printer) const {
988   printer->Print(variables_,
989                  "{\n"
990                  "  int dataSize = 0;\n");
991   printer->Indent();
992 
993   printer->Print(variables_,
994                  "for (int i = 0; i < $name$_.size(); i++) {\n"
995                  "  dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n"
996                  "}\n");
997 
998   printer->Print("size += dataSize;\n");
999 
1000   printer->Print(variables_,
1001                  "size += $tag_size$ * get$capitalized_name$List().size();\n");
1002 
1003   printer->Outdent();
1004   printer->Print("}\n");
1005 }
1006 
GenerateEqualsCode(io::Printer * printer) const1007 void RepeatedImmutableStringFieldGenerator::GenerateEqualsCode(
1008     io::Printer* printer) const {
1009   printer->Print(
1010       variables_,
1011       "if (!get$capitalized_name$List()\n"
1012       "    .equals(other.get$capitalized_name$List())) return false;\n");
1013 }
1014 
GenerateHashCode(io::Printer * printer) const1015 void RepeatedImmutableStringFieldGenerator::GenerateHashCode(
1016     io::Printer* printer) const {
1017   printer->Print(
1018       variables_,
1019       "if (get$capitalized_name$Count() > 0) {\n"
1020       "  hash = (37 * hash) + $constant_name$;\n"
1021       "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
1022       "}\n");
1023 }
1024 
GetBoxedType() const1025 std::string RepeatedImmutableStringFieldGenerator::GetBoxedType() const {
1026   return "String";
1027 }
1028 
1029 }  // namespace java
1030 }  // namespace compiler
1031 }  // namespace protobuf
1032 }  // namespace google
1033