• 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 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <map>
36 #include <string>
37 
38 #include <google/protobuf/stubs/logging.h>
39 #include <google/protobuf/stubs/common.h>
40 #include <google/protobuf/compiler/java/java_context.h>
41 #include <google/protobuf/compiler/java/java_doc_comment.h>
42 #include <google/protobuf/compiler/java/java_helpers.h>
43 #include <google/protobuf/compiler/java/java_name_resolver.h>
44 #include <google/protobuf/compiler/java/java_primitive_field.h>
45 #include <google/protobuf/io/printer.h>
46 #include <google/protobuf/wire_format.h>
47 #include <google/protobuf/stubs/strutil.h>
48 
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   JavaType javaType = GetJavaType(descriptor);
67 
68   (*variables)["type"] = PrimitiveTypeName(javaType);
69   (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
70   (*variables)["field_type"] = (*variables)["type"];
71 
72   if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
73       javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT ||
74       javaType == JAVATYPE_LONG) {
75     std::string capitalized_type = UnderscoresToCamelCase(
76         PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
77     (*variables)["field_list_type"] =
78         "com.google.protobuf.Internal." + capitalized_type + "List";
79     (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
80     (*variables)["create_list"] = "new" + capitalized_type + "List()";
81     (*variables)["mutable_copy_list"] =
82         "mutableCopy(" + (*variables)["name"] + "_)";
83     (*variables)["name_make_immutable"] =
84         (*variables)["name"] + "_.makeImmutable()";
85     (*variables)["repeated_get"] =
86         (*variables)["name"] + "_.get" + capitalized_type;
87     (*variables)["repeated_add"] =
88         (*variables)["name"] + "_.add" + capitalized_type;
89     (*variables)["repeated_set"] =
90         (*variables)["name"] + "_.set" + capitalized_type;
91   } else {
92     (*variables)["field_list_type"] =
93         "java.util.List<" + (*variables)["boxed_type"] + ">";
94     (*variables)["create_list"] =
95         "new java.util.ArrayList<" + (*variables)["boxed_type"] + ">()";
96     (*variables)["mutable_copy_list"] = "new java.util.ArrayList<" +
97                                         (*variables)["boxed_type"] + ">(" +
98                                         (*variables)["name"] + "_)";
99     (*variables)["empty_list"] = "java.util.Collections.emptyList()";
100     (*variables)["name_make_immutable"] =
101         (*variables)["name"] + "_ = java.util.Collections.unmodifiableList(" +
102         (*variables)["name"] + "_)";
103     (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
104     (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
105     (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
106   }
107 
108   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
109   (*variables)["default_init"] =
110       IsDefaultValueJavaDefault(descriptor)
111           ? ""
112           : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
113   (*variables)["capitalized_type"] =
114       GetCapitalizedType(descriptor, /* immutable = */ true);
115   (*variables)["tag"] =
116       StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
117   (*variables)["tag_size"] = StrCat(
118       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
119   if (IsReferenceType(GetJavaType(descriptor))) {
120     (*variables)["null_check"] =
121         "  if (value == null) {\n"
122         "    throw new NullPointerException();\n"
123         "  }\n";
124   } else {
125     (*variables)["null_check"] = "";
126   }
127   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
128   // by the proto compiler
129   (*variables)["deprecation"] =
130       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
131   int fixed_size = FixedSize(GetType(descriptor));
132   if (fixed_size != -1) {
133     (*variables)["fixed_size"] = StrCat(fixed_size);
134   }
135   (*variables)["on_changed"] = "onChanged();";
136 
137   if (SupportFieldPresence(descriptor->file())) {
138     // For singular messages and builders, one bit is used for the hasField bit.
139     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
140     (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
141 
142     // Note that these have a trailing ";".
143     (*variables)["set_has_field_bit_message"] =
144         GenerateSetBit(messageBitIndex) + ";";
145     (*variables)["set_has_field_bit_builder"] =
146         GenerateSetBit(builderBitIndex) + ";";
147     (*variables)["clear_has_field_bit_builder"] =
148         GenerateClearBit(builderBitIndex) + ";";
149 
150     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
151   } else {
152     (*variables)["set_has_field_bit_message"] = "";
153     (*variables)["set_has_field_bit_builder"] = "";
154     (*variables)["clear_has_field_bit_builder"] = "";
155 
156     if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
157       (*variables)["is_field_present_message"] =
158           "!" + (*variables)["name"] + "_.isEmpty()";
159     } else {
160       (*variables)["is_field_present_message"] =
161           (*variables)["name"] + "_ != " + (*variables)["default"];
162     }
163   }
164 
165   // For repated builders, one bit is used for whether the array is immutable.
166   (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
167   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
168   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
169 
170   // For repeated fields, one bit is used for whether the array is immutable
171   // in the parsing constructor.
172   (*variables)["get_mutable_bit_parser"] =
173       GenerateGetBitMutableLocal(builderBitIndex);
174   (*variables)["set_mutable_bit_parser"] =
175       GenerateSetBitMutableLocal(builderBitIndex);
176 
177   (*variables)["get_has_field_bit_from_local"] =
178       GenerateGetBitFromLocal(builderBitIndex);
179   (*variables)["set_has_field_bit_to_local"] =
180       GenerateSetBitToLocal(messageBitIndex);
181 }
182 
183 }  // namespace
184 
185 // ===================================================================
186 
ImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)187 ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator(
188     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
189     Context* context)
190     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
191   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
192                         context->GetFieldGeneratorInfo(descriptor),
193                         name_resolver_, &variables_);
194 }
195 
~ImmutablePrimitiveFieldGenerator()196 ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
197 
GetNumBitsForMessage() const198 int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
199   return SupportFieldPresence(descriptor_->file()) ? 1 : 0;
200 }
201 
GetNumBitsForBuilder() const202 int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
203   return GetNumBitsForMessage();
204 }
205 
GenerateInterfaceMembers(io::Printer * printer) const206 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
207     io::Printer* printer) const {
208   if (SupportFieldPresence(descriptor_->file())) {
209     WriteFieldDocComment(printer, descriptor_);
210     printer->Print(variables_,
211                    "$deprecation$boolean has$capitalized_name$();\n");
212   }
213   WriteFieldDocComment(printer, descriptor_);
214   printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
215 }
216 
GenerateMembers(io::Printer * printer) const217 void ImmutablePrimitiveFieldGenerator::GenerateMembers(
218     io::Printer* printer) const {
219   printer->Print(variables_, "private $field_type$ $name$_;\n");
220   PrintExtraFieldInfo(variables_, printer);
221   if (SupportFieldPresence(descriptor_->file())) {
222     WriteFieldDocComment(printer, descriptor_);
223     printer->Print(
224         variables_,
225         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
226         "  return $get_has_field_bit_message$;\n"
227         "}\n");
228     printer->Annotate("{", "}", descriptor_);
229   }
230 
231   WriteFieldDocComment(printer, descriptor_);
232   printer->Print(variables_,
233                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
234                  "  return $name$_;\n"
235                  "}\n");
236   printer->Annotate("{", "}", descriptor_);
237 }
238 
GenerateBuilderMembers(io::Printer * printer) const239 void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
240     io::Printer* printer) const {
241   printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
242 
243   if (SupportFieldPresence(descriptor_->file())) {
244     WriteFieldDocComment(printer, descriptor_);
245     printer->Print(
246         variables_,
247         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
248         "  return $get_has_field_bit_builder$;\n"
249         "}\n");
250     printer->Annotate("{", "}", descriptor_);
251   }
252 
253   WriteFieldDocComment(printer, descriptor_);
254   printer->Print(variables_,
255                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
256                  "  return $name$_;\n"
257                  "}\n");
258   printer->Annotate("{", "}", descriptor_);
259 
260   WriteFieldDocComment(printer, descriptor_);
261   printer->Print(variables_,
262                  "$deprecation$public Builder "
263                  "${$set$capitalized_name$$}$($type$ value) {\n"
264                  "$null_check$"
265                  "  $set_has_field_bit_builder$\n"
266                  "  $name$_ = value;\n"
267                  "  $on_changed$\n"
268                  "  return this;\n"
269                  "}\n");
270   printer->Annotate("{", "}", descriptor_);
271 
272   WriteFieldDocComment(printer, descriptor_);
273   printer->Print(
274       variables_,
275       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
276       "  $clear_has_field_bit_builder$\n");
277   printer->Annotate("{", "}", descriptor_);
278   JavaType type = GetJavaType(descriptor_);
279   if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
280     // The default value is not a simple literal so we want to avoid executing
281     // it multiple times.  Instead, get the default out of the default instance.
282     printer->Print(
283         variables_,
284         "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
285   } else {
286     printer->Print(variables_, "  $name$_ = $default$;\n");
287   }
288   printer->Print(variables_,
289                  "  $on_changed$\n"
290                  "  return this;\n"
291                  "}\n");
292 }
293 
GenerateFieldBuilderInitializationCode(io::Printer * printer) const294 void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
295     io::Printer* printer) const {
296   // noop for primitives
297 }
298 
GenerateInitializationCode(io::Printer * printer) const299 void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
300     io::Printer* printer) const {
301   if (!IsDefaultValueJavaDefault(descriptor_)) {
302     printer->Print(variables_, "$name$_ = $default$;\n");
303   }
304 }
305 
GenerateBuilderClearCode(io::Printer * printer) const306 void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
307     io::Printer* printer) const {
308   printer->Print(variables_,
309                  "$name$_ = $default$;\n"
310                  "$clear_has_field_bit_builder$\n");
311 }
312 
GenerateMergingCode(io::Printer * printer) const313 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
314     io::Printer* printer) const {
315   if (SupportFieldPresence(descriptor_->file())) {
316     printer->Print(variables_,
317                    "if (other.has$capitalized_name$()) {\n"
318                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
319                    "}\n");
320   } else {
321     printer->Print(variables_,
322                    "if (other.get$capitalized_name$() != $default$) {\n"
323                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
324                    "}\n");
325   }
326 }
327 
GenerateBuildingCode(io::Printer * printer) const328 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
329     io::Printer* printer) const {
330   if (SupportFieldPresence(descriptor_->file())) {
331     if (IsDefaultValueJavaDefault(descriptor_)) {
332       printer->Print(variables_,
333                      "if ($get_has_field_bit_from_local$) {\n"
334                      "  result.$name$_ = $name$_;\n"
335                      "  $set_has_field_bit_to_local$;\n"
336                      "}\n");
337     } else {
338       printer->Print(variables_,
339                      "if ($get_has_field_bit_from_local$) {\n"
340                      "  $set_has_field_bit_to_local$;\n"
341                      "}\n"
342                      "result.$name$_ = $name$_;\n");
343     }
344   } else {
345     printer->Print(variables_, "result.$name$_ = $name$_;\n");
346   }
347 }
348 
GenerateParsingCode(io::Printer * printer) const349 void ImmutablePrimitiveFieldGenerator::GenerateParsingCode(
350     io::Printer* printer) const {
351   printer->Print(variables_,
352                  "$set_has_field_bit_message$\n"
353                  "$name$_ = input.read$capitalized_type$();\n");
354 }
355 
GenerateParsingDoneCode(io::Printer * printer) const356 void ImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode(
357     io::Printer* printer) const {
358   // noop for primitives.
359 }
360 
GenerateSerializationCode(io::Printer * printer) const361 void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
362     io::Printer* printer) const {
363   printer->Print(variables_,
364                  "if ($is_field_present_message$) {\n"
365                  "  output.write$capitalized_type$($number$, $name$_);\n"
366                  "}\n");
367 }
368 
GenerateSerializedSizeCode(io::Printer * printer) const369 void ImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
370     io::Printer* printer) const {
371   printer->Print(variables_,
372                  "if ($is_field_present_message$) {\n"
373                  "  size += com.google.protobuf.CodedOutputStream\n"
374                  "    .compute$capitalized_type$Size($number$, $name$_);\n"
375                  "}\n");
376 }
377 
GenerateEqualsCode(io::Printer * printer) const378 void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
379     io::Printer* printer) const {
380   switch (GetJavaType(descriptor_)) {
381     case JAVATYPE_INT:
382     case JAVATYPE_LONG:
383     case JAVATYPE_BOOLEAN:
384       printer->Print(variables_,
385                      "if (get$capitalized_name$()\n"
386                      "    != other.get$capitalized_name$()) return false;\n");
387       break;
388 
389     case JAVATYPE_FLOAT:
390       printer->Print(
391           variables_,
392           "if (java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
393           "    != java.lang.Float.floatToIntBits(\n"
394           "        other.get$capitalized_name$())) return false;\n");
395       break;
396 
397     case JAVATYPE_DOUBLE:
398       printer->Print(
399           variables_,
400           "if (java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
401           "    != java.lang.Double.doubleToLongBits(\n"
402           "        other.get$capitalized_name$())) return false;\n");
403       break;
404 
405     case JAVATYPE_STRING:
406     case JAVATYPE_BYTES:
407       printer->Print(
408           variables_,
409           "if (!get$capitalized_name$()\n"
410           "    .equals(other.get$capitalized_name$())) return false;\n");
411       break;
412 
413     case JAVATYPE_ENUM:
414     case JAVATYPE_MESSAGE:
415     default:
416       GOOGLE_LOG(FATAL) << "Can't get here.";
417       break;
418   }
419 }
420 
GenerateHashCode(io::Printer * printer) const421 void ImmutablePrimitiveFieldGenerator::GenerateHashCode(
422     io::Printer* printer) const {
423   printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
424   switch (GetJavaType(descriptor_)) {
425     case JAVATYPE_INT:
426       printer->Print(variables_,
427                      "hash = (53 * hash) + get$capitalized_name$();\n");
428       break;
429 
430     case JAVATYPE_LONG:
431       printer->Print(
432           variables_,
433           "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
434           "    get$capitalized_name$());\n");
435       break;
436 
437     case JAVATYPE_BOOLEAN:
438       printer->Print(
439           variables_,
440           "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
441           "    get$capitalized_name$());\n");
442       break;
443 
444     case JAVATYPE_FLOAT:
445       printer->Print(variables_,
446                      "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
447                      "    get$capitalized_name$());\n");
448       break;
449 
450     case JAVATYPE_DOUBLE:
451       printer->Print(
452           variables_,
453           "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
454           "    java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
455       break;
456 
457     case JAVATYPE_STRING:
458     case JAVATYPE_BYTES:
459       printer->Print(
460           variables_,
461           "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
462       break;
463 
464     case JAVATYPE_ENUM:
465     case JAVATYPE_MESSAGE:
466     default:
467       GOOGLE_LOG(FATAL) << "Can't get here.";
468       break;
469   }
470 }
471 
GetBoxedType() const472 std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
473   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
474 }
475 
476 // ===================================================================
477 
ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)478 ImmutablePrimitiveOneofFieldGenerator::ImmutablePrimitiveOneofFieldGenerator(
479     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
480     Context* context)
481     : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
482                                        builderBitIndex, context) {
483   const OneofGeneratorInfo* info =
484       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
485   SetCommonOneofVariables(descriptor, info, &variables_);
486 }
487 
488 ImmutablePrimitiveOneofFieldGenerator::
~ImmutablePrimitiveOneofFieldGenerator()489     ~ImmutablePrimitiveOneofFieldGenerator() {}
490 
GenerateMembers(io::Printer * printer) const491 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
492     io::Printer* printer) const {
493   PrintExtraFieldInfo(variables_, printer);
494   if (SupportFieldPresence(descriptor_->file())) {
495     WriteFieldDocComment(printer, descriptor_);
496     printer->Print(
497         variables_,
498         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
499         "  return $has_oneof_case_message$;\n"
500         "}\n");
501     printer->Annotate("{", "}", descriptor_);
502   }
503 
504   WriteFieldDocComment(printer, descriptor_);
505   printer->Print(variables_,
506                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
507                  "  if ($has_oneof_case_message$) {\n"
508                  "    return ($boxed_type$) $oneof_name$_;\n"
509                  "  }\n"
510                  "  return $default$;\n"
511                  "}\n");
512   printer->Annotate("{", "}", descriptor_);
513 }
514 
GenerateBuilderMembers(io::Printer * printer) const515 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
516     io::Printer* printer) const {
517   if (SupportFieldPresence(descriptor_->file())) {
518     WriteFieldDocComment(printer, descriptor_);
519     printer->Print(
520         variables_,
521         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
522         "  return $has_oneof_case_message$;\n"
523         "}\n");
524     printer->Annotate("{", "}", descriptor_);
525   }
526 
527   WriteFieldDocComment(printer, descriptor_);
528   printer->Print(variables_,
529                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
530                  "  if ($has_oneof_case_message$) {\n"
531                  "    return ($boxed_type$) $oneof_name$_;\n"
532                  "  }\n"
533                  "  return $default$;\n"
534                  "}\n");
535   printer->Annotate("{", "}", descriptor_);
536 
537   WriteFieldDocComment(printer, descriptor_);
538   printer->Print(variables_,
539                  "$deprecation$public Builder "
540                  "${$set$capitalized_name$$}$($type$ value) {\n"
541                  "$null_check$"
542                  "  $set_oneof_case_message$;\n"
543                  "  $oneof_name$_ = value;\n"
544                  "  $on_changed$\n"
545                  "  return this;\n"
546                  "}\n");
547   printer->Annotate("{", "}", descriptor_);
548 
549   WriteFieldDocComment(printer, descriptor_);
550   printer->Print(
551       variables_,
552       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
553       "  if ($has_oneof_case_message$) {\n"
554       "    $clear_oneof_case_message$;\n"
555       "    $oneof_name$_ = null;\n"
556       "    $on_changed$\n"
557       "  }\n"
558       "  return this;\n"
559       "}\n");
560   printer->Annotate("{", "}", descriptor_);
561 }
562 
GenerateBuildingCode(io::Printer * printer) const563 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode(
564     io::Printer* printer) const {
565   printer->Print(variables_,
566                  "if ($has_oneof_case_message$) {\n"
567                  "  result.$oneof_name$_ = $oneof_name$_;\n"
568                  "}\n");
569 }
570 
GenerateMergingCode(io::Printer * printer) const571 void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
572     io::Printer* printer) const {
573   printer->Print(variables_,
574                  "set$capitalized_name$(other.get$capitalized_name$());\n");
575 }
576 
GenerateParsingCode(io::Printer * printer) const577 void ImmutablePrimitiveOneofFieldGenerator::GenerateParsingCode(
578     io::Printer* printer) const {
579   printer->Print(variables_,
580                  "$set_oneof_case_message$;\n"
581                  "$oneof_name$_ = input.read$capitalized_type$();\n");
582 }
583 
GenerateSerializationCode(io::Printer * printer) const584 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode(
585     io::Printer* printer) const {
586   printer->Print(variables_,
587                  "if ($has_oneof_case_message$) {\n"
588                  "  output.write$capitalized_type$(\n");
589   // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
590   // do redundant casts.
591   if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
592     printer->Print(variables_, "      $number$, ($type$) $oneof_name$_);\n");
593   } else {
594     printer->Print(
595         variables_,
596         "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
597   }
598   printer->Print("}\n");
599 }
600 
GenerateSerializedSizeCode(io::Printer * printer) const601 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
602     io::Printer* printer) const {
603   printer->Print(variables_,
604                  "if ($has_oneof_case_message$) {\n"
605                  "  size += com.google.protobuf.CodedOutputStream\n"
606                  "    .compute$capitalized_type$Size(\n");
607   // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
608   // do redundant casts.
609   if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
610     printer->Print(variables_, "        $number$, ($type$) $oneof_name$_);\n");
611   } else {
612     printer->Print(
613         variables_,
614         "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
615   }
616   printer->Print("}\n");
617 }
618 
619 // ===================================================================
620 
621 RepeatedImmutablePrimitiveFieldGenerator::
RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)622     RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
623                                              int messageBitIndex,
624                                              int builderBitIndex,
625                                              Context* context)
626     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
627   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
628                         context->GetFieldGeneratorInfo(descriptor),
629                         name_resolver_, &variables_);
630 }
631 
632 RepeatedImmutablePrimitiveFieldGenerator::
~RepeatedImmutablePrimitiveFieldGenerator()633     ~RepeatedImmutablePrimitiveFieldGenerator() {}
634 
GetNumBitsForMessage() const635 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
636   return 0;
637 }
638 
GetNumBitsForBuilder() const639 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
640   return 1;
641 }
642 
GenerateInterfaceMembers(io::Printer * printer) const643 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
644     io::Printer* printer) const {
645   WriteFieldDocComment(printer, descriptor_);
646   printer->Print(variables_,
647                  "$deprecation$java.util.List<$boxed_type$> "
648                  "get$capitalized_name$List();\n");
649   WriteFieldDocComment(printer, descriptor_);
650   printer->Print(variables_,
651                  "$deprecation$int get$capitalized_name$Count();\n");
652   WriteFieldDocComment(printer, descriptor_);
653   printer->Print(variables_,
654                  "$deprecation$$type$ get$capitalized_name$(int index);\n");
655 }
656 
GenerateMembers(io::Printer * printer) const657 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
658     io::Printer* printer) const {
659   printer->Print(variables_, "private $field_list_type$ $name$_;\n");
660   PrintExtraFieldInfo(variables_, printer);
661   WriteFieldDocComment(printer, descriptor_);
662   printer->Print(variables_,
663                  "$deprecation$public java.util.List<$boxed_type$>\n"
664                  "    ${$get$capitalized_name$List$}$() {\n"
665                  "  return $name$_;\n"  // note:  unmodifiable list
666                  "}\n");
667   printer->Annotate("{", "}", descriptor_);
668   WriteFieldDocComment(printer, descriptor_);
669   printer->Print(
670       variables_,
671       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
672       "  return $name$_.size();\n"
673       "}\n");
674   printer->Annotate("{", "}", descriptor_);
675   WriteFieldDocComment(printer, descriptor_);
676   printer->Print(
677       variables_,
678       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
679       "  return $repeated_get$(index);\n"
680       "}\n");
681   printer->Annotate("{", "}", descriptor_);
682 
683   if (descriptor_->is_packed()) {
684     printer->Print(variables_,
685                    "private int $name$MemoizedSerializedSize = -1;\n");
686   }
687 }
688 
GenerateBuilderMembers(io::Printer * printer) const689 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
690     io::Printer* printer) const {
691   // One field is the list and the bit field keeps track of whether the
692   // list is immutable. If it's immutable, the invariant is that it must
693   // either an instance of Collections.emptyList() or it's an ArrayList
694   // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
695   // a refererence to the underlying ArrayList. This invariant allows us to
696   // share instances of lists between protocol buffers avoiding expensive
697   // memory allocations. Note, immutable is a strong guarantee here -- not
698   // just that the list cannot be modified via the reference but that the
699   // list can never be modified.
700   printer->Print(variables_,
701                  "private $field_list_type$ $name$_ = $empty_list$;\n");
702 
703   printer->Print(variables_,
704                  "private void ensure$capitalized_name$IsMutable() {\n"
705                  "  if (!$get_mutable_bit_builder$) {\n"
706                  "    $name$_ = $mutable_copy_list$;\n"
707                  "    $set_mutable_bit_builder$;\n"
708                  "   }\n"
709                  "}\n");
710 
711   // Note:  We return an unmodifiable list because otherwise the caller
712   //   could hold on to the returned list and modify it after the message
713   //   has been built, thus mutating the message which is supposed to be
714   //   immutable.
715   WriteFieldDocComment(printer, descriptor_);
716   printer->Print(
717       variables_,
718       "$deprecation$public java.util.List<$boxed_type$>\n"
719       "    ${$get$capitalized_name$List$}$() {\n"
720       "  return $get_mutable_bit_builder$ ?\n"
721       "           java.util.Collections.unmodifiableList($name$_) : $name$_;\n"
722       "}\n");
723   printer->Annotate("{", "}", descriptor_);
724   WriteFieldDocComment(printer, descriptor_);
725   printer->Print(
726       variables_,
727       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
728       "  return $name$_.size();\n"
729       "}\n");
730   printer->Annotate("{", "}", descriptor_);
731   WriteFieldDocComment(printer, descriptor_);
732   printer->Print(
733       variables_,
734       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
735       "  return $repeated_get$(index);\n"
736       "}\n");
737   printer->Annotate("{", "}", descriptor_);
738   WriteFieldDocComment(printer, descriptor_);
739   printer->Print(variables_,
740                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
741                  "    int index, $type$ value) {\n"
742                  "$null_check$"
743                  "  ensure$capitalized_name$IsMutable();\n"
744                  "  $repeated_set$(index, value);\n"
745                  "  $on_changed$\n"
746                  "  return this;\n"
747                  "}\n");
748   printer->Annotate("{", "}", descriptor_);
749   WriteFieldDocComment(printer, descriptor_);
750   printer->Print(variables_,
751                  "$deprecation$public Builder "
752                  "${$add$capitalized_name$$}$($type$ value) {\n"
753                  "$null_check$"
754                  "  ensure$capitalized_name$IsMutable();\n"
755                  "  $repeated_add$(value);\n"
756                  "  $on_changed$\n"
757                  "  return this;\n"
758                  "}\n");
759   printer->Annotate("{", "}", descriptor_);
760   WriteFieldDocComment(printer, descriptor_);
761   printer->Print(variables_,
762                  "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
763                  "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
764                  "  ensure$capitalized_name$IsMutable();\n"
765                  "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
766                  "      values, $name$_);\n"
767                  "  $on_changed$\n"
768                  "  return this;\n"
769                  "}\n");
770   printer->Annotate("{", "}", descriptor_);
771   WriteFieldDocComment(printer, descriptor_);
772   printer->Print(
773       variables_,
774       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
775       "  $name$_ = $empty_list$;\n"
776       "  $clear_mutable_bit_builder$;\n"
777       "  $on_changed$\n"
778       "  return this;\n"
779       "}\n");
780   printer->Annotate("{", "}", descriptor_);
781 }
782 
783 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const784     GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
785   // noop for primitives
786 }
787 
GenerateInitializationCode(io::Printer * printer) const788 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
789     io::Printer* printer) const {
790   printer->Print(variables_, "$name$_ = $empty_list$;\n");
791 }
792 
GenerateBuilderClearCode(io::Printer * printer) const793 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
794     io::Printer* printer) const {
795   printer->Print(variables_,
796                  "$name$_ = $empty_list$;\n"
797                  "$clear_mutable_bit_builder$;\n");
798 }
799 
GenerateMergingCode(io::Printer * printer) const800 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode(
801     io::Printer* printer) const {
802   // The code below does two optimizations:
803   //   1. If the other list is empty, there's nothing to do. This ensures we
804   //      don't allocate a new array if we already have an immutable one.
805   //   2. If the other list is non-empty and our current list is empty, we can
806   //      reuse the other list which is guaranteed to be immutable.
807   printer->Print(variables_,
808                  "if (!other.$name$_.isEmpty()) {\n"
809                  "  if ($name$_.isEmpty()) {\n"
810                  "    $name$_ = other.$name$_;\n"
811                  "    $clear_mutable_bit_builder$;\n"
812                  "  } else {\n"
813                  "    ensure$capitalized_name$IsMutable();\n"
814                  "    $name$_.addAll(other.$name$_);\n"
815                  "  }\n"
816                  "  $on_changed$\n"
817                  "}\n");
818 }
819 
GenerateBuildingCode(io::Printer * printer) const820 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
821     io::Printer* printer) const {
822   // The code below ensures that the result has an immutable list. If our
823   // list is immutable, we can just reuse it. If not, we make it immutable.
824   printer->Print(variables_,
825                  "if ($get_mutable_bit_builder$) {\n"
826                  "  $name_make_immutable$;\n"
827                  "  $clear_mutable_bit_builder$;\n"
828                  "}\n"
829                  "result.$name$_ = $name$_;\n");
830 }
831 
GenerateParsingCode(io::Printer * printer) const832 void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCode(
833     io::Printer* printer) const {
834   printer->Print(variables_,
835                  "if (!$get_mutable_bit_parser$) {\n"
836                  "  $name$_ = $create_list$;\n"
837                  "  $set_mutable_bit_parser$;\n"
838                  "}\n"
839                  "$repeated_add$(input.read$capitalized_type$());\n");
840 }
841 
GenerateParsingCodeFromPacked(io::Printer * printer) const842 void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCodeFromPacked(
843     io::Printer* printer) const {
844   printer->Print(
845       variables_,
846       "int length = input.readRawVarint32();\n"
847       "int limit = input.pushLimit(length);\n"
848       "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
849       "  $name$_ = $create_list$;\n"
850       "  $set_mutable_bit_parser$;\n"
851       "}\n"
852       "while (input.getBytesUntilLimit() > 0) {\n"
853       "  $repeated_add$(input.read$capitalized_type$());\n"
854       "}\n"
855       "input.popLimit(limit);\n");
856 }
857 
GenerateParsingDoneCode(io::Printer * printer) const858 void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode(
859     io::Printer* printer) const {
860   printer->Print(variables_,
861                  "if ($get_mutable_bit_parser$) {\n"
862                  "  $name_make_immutable$; // C\n"
863                  "}\n");
864 }
865 
GenerateSerializationCode(io::Printer * printer) const866 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
867     io::Printer* printer) const {
868   if (descriptor_->is_packed()) {
869     // We invoke getSerializedSize in writeTo for messages that have packed
870     // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
871     // That makes it safe to rely on the memoized size here.
872     printer->Print(variables_,
873                    "if (get$capitalized_name$List().size() > 0) {\n"
874                    "  output.writeUInt32NoTag($tag$);\n"
875                    "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
876                    "}\n"
877                    "for (int i = 0; i < $name$_.size(); i++) {\n"
878                    "  output.write$capitalized_type$NoTag($repeated_get$(i));\n"
879                    "}\n");
880   } else {
881     printer->Print(
882         variables_,
883         "for (int i = 0; i < $name$_.size(); i++) {\n"
884         "  output.write$capitalized_type$($number$, $repeated_get$(i));\n"
885         "}\n");
886   }
887 }
888 
GenerateSerializedSizeCode(io::Printer * printer) const889 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
890     io::Printer* printer) const {
891   printer->Print(variables_,
892                  "{\n"
893                  "  int dataSize = 0;\n");
894   printer->Indent();
895 
896   if (FixedSize(GetType(descriptor_)) == -1) {
897     printer->Print(
898         variables_,
899         "for (int i = 0; i < $name$_.size(); i++) {\n"
900         "  dataSize += com.google.protobuf.CodedOutputStream\n"
901         "    .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
902         "}\n");
903   } else {
904     printer->Print(
905         variables_,
906         "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
907   }
908 
909   printer->Print("size += dataSize;\n");
910 
911   if (descriptor_->is_packed()) {
912     printer->Print(variables_,
913                    "if (!get$capitalized_name$List().isEmpty()) {\n"
914                    "  size += $tag_size$;\n"
915                    "  size += com.google.protobuf.CodedOutputStream\n"
916                    "      .computeInt32SizeNoTag(dataSize);\n"
917                    "}\n");
918   } else {
919     printer->Print(
920         variables_,
921         "size += $tag_size$ * get$capitalized_name$List().size();\n");
922   }
923 
924   // cache the data size for packed fields.
925   if (descriptor_->is_packed()) {
926     printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
927   }
928 
929   printer->Outdent();
930   printer->Print("}\n");
931 }
932 
GenerateEqualsCode(io::Printer * printer) const933 void RepeatedImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
934     io::Printer* printer) const {
935   printer->Print(
936       variables_,
937       "if (!get$capitalized_name$List()\n"
938       "    .equals(other.get$capitalized_name$List())) return false;\n");
939 }
940 
GenerateHashCode(io::Printer * printer) const941 void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode(
942     io::Printer* printer) const {
943   printer->Print(
944       variables_,
945       "if (get$capitalized_name$Count() > 0) {\n"
946       "  hash = (37 * hash) + $constant_name$;\n"
947       "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
948       "}\n");
949 }
950 
GetBoxedType() const951 std::string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
952   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
953 }
954 
955 }  // namespace java
956 }  // namespace compiler
957 }  // namespace protobuf
958 }  // namespace google
959