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