• 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_lite.h>
45 #include <google/protobuf/io/printer.h>
46 #include <google/protobuf/wire_format.h>
47 #include <google/protobuf/stubs/strutil.h>
48 
49 namespace google {
50 namespace protobuf {
51 namespace compiler {
52 namespace java {
53 
54 using internal::WireFormat;
55 using internal::WireFormatLite;
56 
57 namespace {
58 
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,map<string,string> * variables)59 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
60                            int messageBitIndex,
61                            int builderBitIndex,
62                            const FieldGeneratorInfo* info,
63                            ClassNameResolver* name_resolver,
64                            map<string, string>* variables) {
65   SetCommonFieldVariables(descriptor, info, variables);
66 
67   (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
68   (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
69   (*variables)["field_type"] = (*variables)["type"];
70   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
71   (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
72       "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
73   (*variables)["capitalized_type"] =
74       GetCapitalizedType(descriptor, /* immutable = */ true);
75   (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
76   (*variables)["tag_size"] = SimpleItoa(
77       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
78 
79   string capitalized_type = UnderscoresToCamelCase(PrimitiveTypeName(
80         GetJavaType(descriptor)), true /* cap_next_letter */);
81   switch (GetJavaType(descriptor)) {
82     case JAVATYPE_INT:
83     case JAVATYPE_LONG:
84     case JAVATYPE_FLOAT:
85     case JAVATYPE_DOUBLE:
86     case JAVATYPE_BOOLEAN:
87       (*variables)["field_list_type"] =
88           "com.google.protobuf.Internal." + capitalized_type + "List";
89       (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
90       (*variables)["make_name_unmodifiable"] =
91           (*variables)["name"] + "_.makeImmutable()";
92       (*variables)["repeated_get"] =
93           (*variables)["name"] + "_.get" + capitalized_type;
94       (*variables)["repeated_add"] =
95           (*variables)["name"] + "_.add" + capitalized_type;
96       (*variables)["repeated_set"] =
97           (*variables)["name"] + "_.set" + capitalized_type;
98       (*variables)["visit_type"] = capitalized_type;
99       (*variables)["visit_type_list"] = "visit" + capitalized_type + "List";
100       break;
101     default:
102       (*variables)["field_list_type"] =
103           "com.google.protobuf.Internal.ProtobufList<" +
104           (*variables)["boxed_type"] + ">";
105       (*variables)["empty_list"] = "emptyProtobufList()";
106       (*variables)["make_name_unmodifiable"] =
107           (*variables)["name"] + "_.makeImmutable()";
108       (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
109       (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
110       (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
111       (*variables)["visit_type"] = "ByteString";
112       (*variables)["visit_type_list"] = "visitList";
113   }
114 
115   if (IsReferenceType(GetJavaType(descriptor))) {
116     (*variables)["null_check"] =
117         "  if (value == null) {\n"
118         "    throw new NullPointerException();\n"
119         "  }\n";
120   } else {
121     (*variables)["null_check"] = "";
122   }
123   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
124   // by the proto compiler
125   (*variables)["deprecation"] = descriptor->options().deprecated()
126       ? "@java.lang.Deprecated " : "";
127   int fixed_size = FixedSize(GetType(descriptor));
128   if (fixed_size != -1) {
129     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
130   }
131 
132   if (SupportFieldPresence(descriptor->file())) {
133     // For singular messages and builders, one bit is used for the hasField bit.
134     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
135 
136     // Note that these have a trailing ";".
137     (*variables)["set_has_field_bit_message"] =
138         GenerateSetBit(messageBitIndex) + ";";
139     (*variables)["clear_has_field_bit_message"] =
140         GenerateClearBit(messageBitIndex) + ";";
141 
142     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
143   } else {
144     (*variables)["set_has_field_bit_message"] = "";
145     (*variables)["set_has_field_bit_message"] = "";
146     (*variables)["clear_has_field_bit_message"] = "";
147 
148     if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
149       (*variables)["is_field_present_message"] =
150           "!" + (*variables)["name"] + "_.isEmpty()";
151     } else {
152       (*variables)["is_field_present_message"] =
153           (*variables)["name"] + "_ != " + (*variables)["default"];
154     }
155   }
156 
157   // For repeated builders, the underlying list tracks mutability state.
158   (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
159 
160   (*variables)["get_has_field_bit_from_local"] =
161       GenerateGetBitFromLocal(builderBitIndex);
162   (*variables)["set_has_field_bit_to_local"] =
163       GenerateSetBitToLocal(messageBitIndex);
164 }
165 
166 }  // namespace
167 
168 // ===================================================================
169 
170 ImmutablePrimitiveFieldLiteGenerator::
ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)171 ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
172                                  int messageBitIndex,
173                                  int builderBitIndex,
174                                  Context* context)
175   : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
176     builderBitIndex_(builderBitIndex), context_(context),
177     name_resolver_(context->GetNameResolver()) {
178   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
179                         context->GetFieldGeneratorInfo(descriptor),
180                         name_resolver_, &variables_);
181 }
182 
~ImmutablePrimitiveFieldLiteGenerator()183 ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {}
184 
GetNumBitsForMessage() const185 int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
186   return 1;
187 }
188 
GetNumBitsForBuilder() const189 int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
190   return 0;
191 }
192 
193 void ImmutablePrimitiveFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const194 GenerateInterfaceMembers(io::Printer* printer) const {
195   if (SupportFieldPresence(descriptor_->file())) {
196     WriteFieldDocComment(printer, descriptor_);
197     printer->Print(variables_,
198       "$deprecation$boolean has$capitalized_name$();\n");
199   }
200   WriteFieldDocComment(printer, descriptor_);
201   printer->Print(variables_,
202     "$deprecation$$type$ get$capitalized_name$();\n");
203 }
204 
205 void ImmutablePrimitiveFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const206 GenerateMembers(io::Printer* printer) const {
207   printer->Print(variables_,
208     "private $field_type$ $name$_;\n");
209   PrintExtraFieldInfo(variables_, printer);
210   if (SupportFieldPresence(descriptor_->file())) {
211     WriteFieldDocComment(printer, descriptor_);
212     printer->Print(variables_,
213       "$deprecation$public boolean has$capitalized_name$() {\n"
214       "  return $get_has_field_bit_message$;\n"
215       "}\n");
216   }
217 
218   WriteFieldDocComment(printer, descriptor_);
219   printer->Print(variables_,
220     "$deprecation$public $type$ get$capitalized_name$() {\n"
221     "  return $name$_;\n"
222     "}\n");
223 
224   WriteFieldDocComment(printer, descriptor_);
225   printer->Print(variables_,
226     "private void set$capitalized_name$($type$ value) {\n"
227     "$null_check$"
228     "  $set_has_field_bit_message$\n"
229     "  $name$_ = value;\n"
230     "}\n");
231 
232   WriteFieldDocComment(printer, descriptor_);
233   printer->Print(variables_,
234     "private void clear$capitalized_name$() {\n"
235     "  $clear_has_field_bit_message$\n");
236   JavaType type = GetJavaType(descriptor_);
237   if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
238     // The default value is not a simple literal so we want to avoid executing
239     // it multiple times.  Instead, get the default out of the default instance.
240     printer->Print(variables_,
241       "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
242   } else {
243     printer->Print(variables_,
244       "  $name$_ = $default$;\n");
245   }
246   printer->Print(variables_,
247     "}\n");
248 }
249 
250 void ImmutablePrimitiveFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const251 GenerateBuilderMembers(io::Printer* printer) const {
252   if (SupportFieldPresence(descriptor_->file())) {
253     WriteFieldDocComment(printer, descriptor_);
254     printer->Print(variables_,
255       "$deprecation$public boolean has$capitalized_name$() {\n"
256       "  return instance.has$capitalized_name$();\n"
257       "}\n");
258   }
259 
260   WriteFieldDocComment(printer, descriptor_);
261   printer->Print(variables_,
262     "$deprecation$public $type$ get$capitalized_name$() {\n"
263     "  return instance.get$capitalized_name$();\n"
264     "}\n");
265 
266   WriteFieldDocComment(printer, descriptor_);
267   printer->Print(variables_,
268     "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
269     "  copyOnWrite();\n"
270     "  instance.set$capitalized_name$(value);\n"
271     "  return this;\n"
272     "}\n");
273 
274   WriteFieldDocComment(printer, descriptor_);
275   printer->Print(variables_,
276     "$deprecation$public Builder clear$capitalized_name$() {\n"
277     "  copyOnWrite();\n"
278     "  instance.clear$capitalized_name$();\n"
279     "  return this;\n"
280     "}\n");
281 }
282 
283 void ImmutablePrimitiveFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const284 GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
285   // noop for primitives
286 }
287 
288 void ImmutablePrimitiveFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const289 GenerateInitializationCode(io::Printer* printer) const {
290   printer->Print(variables_, "$name$_ = $default$;\n");
291 }
292 
293 void ImmutablePrimitiveFieldLiteGenerator::
GenerateBuilderClearCode(io::Printer * printer) const294 GenerateBuilderClearCode(io::Printer* printer) const {
295   // noop for primitives
296 }
297 
298 void ImmutablePrimitiveFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const299 GenerateVisitCode(io::Printer* printer) const {
300   if (SupportFieldPresence(descriptor_->file())) {
301     printer->Print(variables_,
302       "$name$_ = visitor.visit$visit_type$(\n"
303       "    has$capitalized_name$(), $name$_,\n"
304       "    other.has$capitalized_name$(), other.$name$_);\n");
305   } else {
306     printer->Print(variables_,
307       "$name$_ = visitor.visit$visit_type$($name$_ != $default$, $name$_,\n"
308       "    other.$name$_ != $default$, other.$name$_);\n");
309   }
310 }
311 
312 void ImmutablePrimitiveFieldLiteGenerator::
GenerateBuildingCode(io::Printer * printer) const313 GenerateBuildingCode(io::Printer* printer) const {
314   // noop for primitives
315 }
316 
317 void ImmutablePrimitiveFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const318 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
319   // noop for scalars
320 }
321 
322 void ImmutablePrimitiveFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const323 GenerateParsingCode(io::Printer* printer) const {
324   printer->Print(variables_,
325     "$set_has_field_bit_message$\n"
326     "$name$_ = input.read$capitalized_type$();\n");
327 }
328 
329 void ImmutablePrimitiveFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const330 GenerateParsingDoneCode(io::Printer* printer) const {
331   // noop for primitives.
332 }
333 
334 void ImmutablePrimitiveFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const335 GenerateSerializationCode(io::Printer* printer) const {
336   printer->Print(variables_,
337     "if ($is_field_present_message$) {\n"
338     "  output.write$capitalized_type$($number$, $name$_);\n"
339     "}\n");
340 }
341 
342 void ImmutablePrimitiveFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const343 GenerateSerializedSizeCode(io::Printer* printer) const {
344   printer->Print(variables_,
345     "if ($is_field_present_message$) {\n"
346     "  size += com.google.protobuf.CodedOutputStream\n"
347     "    .compute$capitalized_type$Size($number$, $name$_);\n"
348     "}\n");
349 }
350 
351 void ImmutablePrimitiveFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const352 GenerateEqualsCode(io::Printer* printer) const {
353   switch (GetJavaType(descriptor_)) {
354     case JAVATYPE_INT:
355     case JAVATYPE_LONG:
356     case JAVATYPE_BOOLEAN:
357       printer->Print(variables_,
358         "result = result && (get$capitalized_name$()\n"
359         "    == other.get$capitalized_name$());\n");
360       break;
361 
362     case JAVATYPE_FLOAT:
363       printer->Print(variables_,
364         "result = result && (\n"
365         "    java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
366         "    == java.lang.Float.floatToIntBits(\n"
367         "        other.get$capitalized_name$()));\n");
368       break;
369 
370     case JAVATYPE_DOUBLE:
371       printer->Print(variables_,
372         "result = result && (\n"
373         "    java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
374         "    == java.lang.Double.doubleToLongBits(\n"
375         "        other.get$capitalized_name$()));\n");
376       break;
377 
378     case JAVATYPE_STRING:
379     case JAVATYPE_BYTES:
380       printer->Print(variables_,
381         "result = result && get$capitalized_name$()\n"
382         "    .equals(other.get$capitalized_name$());\n");
383       break;
384 
385     case JAVATYPE_ENUM:
386     case JAVATYPE_MESSAGE:
387     default:
388       GOOGLE_LOG(FATAL) << "Can't get here.";
389       break;
390   }
391 }
392 
393 void ImmutablePrimitiveFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const394 GenerateHashCode(io::Printer* printer) const {
395   printer->Print(variables_,
396     "hash = (37 * hash) + $constant_name$;\n");
397   switch (GetJavaType(descriptor_)) {
398     case JAVATYPE_INT:
399       printer->Print(variables_,
400         "hash = (53 * hash) + get$capitalized_name$();\n");
401       break;
402 
403     case JAVATYPE_LONG:
404       printer->Print(variables_,
405         "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
406         "    get$capitalized_name$());\n");
407       break;
408 
409     case JAVATYPE_BOOLEAN:
410       printer->Print(variables_,
411         "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
412         "    get$capitalized_name$());\n");
413       break;
414 
415     case JAVATYPE_FLOAT:
416       printer->Print(variables_,
417         "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
418         "    get$capitalized_name$());\n");
419       break;
420 
421     case JAVATYPE_DOUBLE:
422       printer->Print(variables_,
423         "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
424         "    java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
425       break;
426 
427     case JAVATYPE_STRING:
428     case JAVATYPE_BYTES:
429       printer->Print(variables_,
430         "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
431       break;
432 
433     case JAVATYPE_ENUM:
434     case JAVATYPE_MESSAGE:
435     default:
436       GOOGLE_LOG(FATAL) << "Can't get here.";
437       break;
438   }
439 }
440 
GetBoxedType() const441 string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
442   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
443 }
444 
445 // ===================================================================
446 
447 ImmutablePrimitiveOneofFieldLiteGenerator::
ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)448 ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
449                                  int messageBitIndex,
450                                  int builderBitIndex,
451                                  Context* context)
452     : ImmutablePrimitiveFieldLiteGenerator(
453           descriptor, messageBitIndex, builderBitIndex, context) {
454   const OneofGeneratorInfo* info =
455       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
456   SetCommonOneofVariables(descriptor, info, &variables_);
457 }
458 
459 ImmutablePrimitiveOneofFieldLiteGenerator::
~ImmutablePrimitiveOneofFieldLiteGenerator()460 ~ImmutablePrimitiveOneofFieldLiteGenerator() {}
461 
462 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const463 GenerateMembers(io::Printer* printer) const {
464   PrintExtraFieldInfo(variables_, printer);
465   if (SupportFieldPresence(descriptor_->file())) {
466     WriteFieldDocComment(printer, descriptor_);
467     printer->Print(variables_,
468       "$deprecation$public boolean has$capitalized_name$() {\n"
469       "  return $has_oneof_case_message$;\n"
470       "}\n");
471   }
472 
473   WriteFieldDocComment(printer, descriptor_);
474   printer->Print(variables_,
475     "$deprecation$public $type$ get$capitalized_name$() {\n"
476     "  if ($has_oneof_case_message$) {\n"
477     "    return ($boxed_type$) $oneof_name$_;\n"
478     "  }\n"
479     "  return $default$;\n"
480     "}\n");
481 
482   WriteFieldDocComment(printer, descriptor_);
483   printer->Print(variables_,
484     "private void set$capitalized_name$($type$ value) {\n"
485     "$null_check$"
486     "  $set_oneof_case_message$;\n"
487     "  $oneof_name$_ = value;\n"
488     "}\n");
489 
490   WriteFieldDocComment(printer, descriptor_);
491   printer->Print(variables_,
492     "private void clear$capitalized_name$() {\n"
493     "  if ($has_oneof_case_message$) {\n"
494     "    $clear_oneof_case_message$;\n"
495     "    $oneof_name$_ = null;\n"
496     "  }\n"
497     "}\n");
498 }
499 
500 
501 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const502 GenerateBuilderMembers(io::Printer* printer) const {
503   if (SupportFieldPresence(descriptor_->file())) {
504     WriteFieldDocComment(printer, descriptor_);
505     printer->Print(variables_,
506       "$deprecation$public boolean has$capitalized_name$() {\n"
507       "  return instance.has$capitalized_name$();\n"
508       "}\n");
509   }
510 
511   WriteFieldDocComment(printer, descriptor_);
512   printer->Print(variables_,
513     "$deprecation$public $type$ get$capitalized_name$() {\n"
514     "  return instance.get$capitalized_name$();\n"
515     "}\n");
516 
517   WriteFieldDocComment(printer, descriptor_);
518   printer->Print(variables_,
519     "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
520     "  copyOnWrite();\n"
521     "  instance.set$capitalized_name$(value);\n"
522     "  return this;\n"
523     "}\n");
524 
525   WriteFieldDocComment(printer, descriptor_);
526   printer->Print(variables_,
527     "$deprecation$public Builder clear$capitalized_name$() {\n"
528     "  copyOnWrite();\n"
529     "  instance.clear$capitalized_name$();\n"
530     "  return this;\n"
531     "}\n");
532 }
533 
534 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateBuildingCode(io::Printer * printer) const535 GenerateBuildingCode(io::Printer* printer) const {
536   // noop for primitives
537 }
538 
539 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const540 GenerateVisitCode(io::Printer* printer) const {
541   printer->Print(variables_,
542       "$oneof_name$_ = visitor.visitOneof$visit_type$(\n"
543       "    $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n");
544 }
545 
546 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const547 GenerateParsingCode(io::Printer* printer) const {
548   printer->Print(variables_,
549     "$set_oneof_case_message$;\n"
550     "$oneof_name$_ = input.read$capitalized_type$();\n");
551 }
552 
553 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const554 GenerateSerializationCode(io::Printer* printer) const {
555   printer->Print(variables_,
556     "if ($has_oneof_case_message$) {\n"
557     "  output.write$capitalized_type$(\n"
558     "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
559     "}\n");
560 }
561 
562 void ImmutablePrimitiveOneofFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const563 GenerateSerializedSizeCode(io::Printer* printer) const {
564   printer->Print(variables_,
565     "if ($has_oneof_case_message$) {\n"
566     "  size += com.google.protobuf.CodedOutputStream\n"
567     "    .compute$capitalized_type$Size(\n"
568     "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
569     "}\n");
570 }
571 
572 // ===================================================================
573 
574 RepeatedImmutablePrimitiveFieldLiteGenerator::
RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)575 RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
576                                          int messageBitIndex,
577                                          int builderBitIndex,
578                                          Context* context)
579   : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
580     builderBitIndex_(builderBitIndex), context_(context),
581     name_resolver_(context->GetNameResolver()) {
582   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
583                         context->GetFieldGeneratorInfo(descriptor),
584                         name_resolver_, &variables_);
585 }
586 
587 RepeatedImmutablePrimitiveFieldLiteGenerator::
~RepeatedImmutablePrimitiveFieldLiteGenerator()588 ~RepeatedImmutablePrimitiveFieldLiteGenerator() {}
589 
GetNumBitsForMessage() const590 int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
591   return 0;
592 }
593 
GetNumBitsForBuilder() const594 int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
595   return 0;
596 }
597 
598 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer * printer) const599 GenerateInterfaceMembers(io::Printer* printer) const {
600   WriteFieldDocComment(printer, descriptor_);
601   printer->Print(variables_,
602     "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
603   WriteFieldDocComment(printer, descriptor_);
604   printer->Print(variables_,
605     "$deprecation$int get$capitalized_name$Count();\n");
606   WriteFieldDocComment(printer, descriptor_);
607   printer->Print(variables_,
608     "$deprecation$$type$ get$capitalized_name$(int index);\n");
609 }
610 
611 
612 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateMembers(io::Printer * printer) const613 GenerateMembers(io::Printer* printer) const {
614   printer->Print(variables_,
615     "private $field_list_type$ $name$_;\n");
616   PrintExtraFieldInfo(variables_, printer);
617   WriteFieldDocComment(printer, descriptor_);
618   printer->Print(variables_,
619     "$deprecation$public java.util.List<$boxed_type$>\n"
620     "    get$capitalized_name$List() {\n"
621     "  return $name$_;\n"   // note:  unmodifiable list
622     "}\n");
623   WriteFieldDocComment(printer, descriptor_);
624   printer->Print(variables_,
625     "$deprecation$public int get$capitalized_name$Count() {\n"
626     "  return $name$_.size();\n"
627     "}\n");
628   WriteFieldDocComment(printer, descriptor_);
629   printer->Print(variables_,
630     "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
631     "  return $repeated_get$(index);\n"
632     "}\n");
633 
634   if (descriptor_->options().packed() &&
635       context_->HasGeneratedMethods(descriptor_->containing_type())) {
636     printer->Print(variables_,
637       "private int $name$MemoizedSerializedSize = -1;\n");
638   }
639 
640   printer->Print(variables_,
641     "private void ensure$capitalized_name$IsMutable() {\n"
642     "  if (!$is_mutable$) {\n"
643     "    $name$_ =\n"
644     "        com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
645     "   }\n"
646     "}\n");
647 
648   WriteFieldDocComment(printer, descriptor_);
649   printer->Print(variables_,
650     "private void set$capitalized_name$(\n"
651     "    int index, $type$ value) {\n"
652     "$null_check$"
653     "  ensure$capitalized_name$IsMutable();\n"
654     "  $repeated_set$(index, value);\n"
655     "}\n");
656   WriteFieldDocComment(printer, descriptor_);
657   printer->Print(variables_,
658     "private void add$capitalized_name$($type$ value) {\n"
659     "$null_check$"
660     "  ensure$capitalized_name$IsMutable();\n"
661     "  $repeated_add$(value);\n"
662     "}\n");
663   WriteFieldDocComment(printer, descriptor_);
664   printer->Print(variables_,
665     "private void addAll$capitalized_name$(\n"
666     "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
667     "  ensure$capitalized_name$IsMutable();\n"
668     "  com.google.protobuf.AbstractMessageLite.addAll(\n"
669     "      values, $name$_);\n"
670     "}\n");
671   WriteFieldDocComment(printer, descriptor_);
672   printer->Print(variables_,
673     "private void clear$capitalized_name$() {\n"
674     "  $name$_ = $empty_list$;\n"
675     "}\n");
676 }
677 
678 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateBuilderMembers(io::Printer * printer) const679 GenerateBuilderMembers(io::Printer* printer) const {
680   WriteFieldDocComment(printer, descriptor_);
681   printer->Print(variables_,
682     "$deprecation$public java.util.List<$boxed_type$>\n"
683     "    get$capitalized_name$List() {\n"
684     "  return java.util.Collections.unmodifiableList(\n"
685     "      instance.get$capitalized_name$List());\n"
686     "}\n");
687   WriteFieldDocComment(printer, descriptor_);
688   printer->Print(variables_,
689     "$deprecation$public int get$capitalized_name$Count() {\n"
690     "  return instance.get$capitalized_name$Count();\n"
691     "}\n");
692   WriteFieldDocComment(printer, descriptor_);
693   printer->Print(variables_,
694     "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
695     "  return instance.get$capitalized_name$(index);\n"
696     "}\n");
697   WriteFieldDocComment(printer, descriptor_);
698   printer->Print(variables_,
699     "$deprecation$public Builder set$capitalized_name$(\n"
700     "    int index, $type$ value) {\n"
701     "  copyOnWrite();\n"
702     "  instance.set$capitalized_name$(index, value);\n"
703     "  return this;\n"
704     "}\n");
705   WriteFieldDocComment(printer, descriptor_);
706   printer->Print(variables_,
707     "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
708     "  copyOnWrite();\n"
709     "  instance.add$capitalized_name$(value);\n"
710     "  return this;\n"
711     "}\n");
712   WriteFieldDocComment(printer, descriptor_);
713   printer->Print(variables_,
714     "$deprecation$public Builder addAll$capitalized_name$(\n"
715     "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
716     "  copyOnWrite();\n"
717     "  instance.addAll$capitalized_name$(values);\n"
718     "  return this;\n"
719     "}\n");
720   WriteFieldDocComment(printer, descriptor_);
721   printer->Print(variables_,
722     "$deprecation$public Builder clear$capitalized_name$() {\n"
723     "  copyOnWrite();\n"
724     "  instance.clear$capitalized_name$();\n"
725     "  return this;\n"
726     "}\n");
727 }
728 
729 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const730 GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
731   // noop for primitives
732 }
733 
734 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateInitializationCode(io::Printer * printer) const735 GenerateInitializationCode(io::Printer* printer) const {
736   printer->Print(variables_, "$name$_ = $empty_list$;\n");
737 }
738 
739 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateBuilderClearCode(io::Printer * printer) const740 GenerateBuilderClearCode(io::Printer* printer) const {
741   // noop for primitives
742 }
743 
744 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateVisitCode(io::Printer * printer) const745 GenerateVisitCode(io::Printer* printer) const {
746   printer->Print(variables_,
747       "$name$_= visitor.$visit_type_list$($name$_, other.$name$_);\n");
748 }
749 
750 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateBuildingCode(io::Printer * printer) const751 GenerateBuildingCode(io::Printer* printer) const {
752   // noop for primitives
753 }
754 
755 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateDynamicMethodMakeImmutableCode(io::Printer * printer) const756 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
757   printer->Print(variables_,
758     "$name$_.makeImmutable();\n");
759 }
760 
761 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateParsingCode(io::Printer * printer) const762 GenerateParsingCode(io::Printer* printer) const {
763   // TODO(dweis): Scan the input buffer to count, then initialize
764   // appropriately.
765   // TODO(dweis): Scan the input buffer to count and ensure capacity.
766   printer->Print(variables_,
767     "if (!$is_mutable$) {\n"
768     "  $name$_ =\n"
769     "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"
770     "}\n"
771     "$repeated_add$(input.read$capitalized_type$());\n");
772 }
773 
774 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateParsingCodeFromPacked(io::Printer * printer) const775 GenerateParsingCodeFromPacked(io::Printer* printer) const {
776   printer->Print(variables_,
777     "int length = input.readRawVarint32();\n"
778     "int limit = input.pushLimit(length);\n"
779     "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n");
780 
781   int fixed_size = FixedSize(GetType(descriptor_));
782   if (fixed_size == -1) {
783     // TODO(dweis): Scan the input buffer to count, then initialize
784     // appropriately.
785     printer->Print(variables_,
786       "  $name$_ =\n"
787       "      com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n");
788   } else {
789     printer->Print(variables_,
790       "  final int currentSize = $name$_.size();\n"
791       "  $name$_ = $name$_.mutableCopyWithCapacity(\n"
792       "      currentSize + (length/$fixed_size$));\n");
793   }
794 
795   // TODO(dweis): Scan the input buffer to count and ensure capacity.
796   printer->Print(variables_,
797     "}\n"
798     "while (input.getBytesUntilLimit() > 0) {\n"
799     "  $repeated_add$(input.read$capitalized_type$());\n"
800     "}\n"
801     "input.popLimit(limit);\n");
802 }
803 
804 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateParsingDoneCode(io::Printer * printer) const805 GenerateParsingDoneCode(io::Printer* printer) const {
806   printer->Print(variables_,
807     "if ($is_mutable$) {\n"
808     "  $make_name_unmodifiable$;\n"
809     "}\n");
810 }
811 
812 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateSerializationCode(io::Printer * printer) const813 GenerateSerializationCode(io::Printer* printer) const {
814   if (descriptor_->options().packed()) {
815     // We invoke getSerializedSize in writeTo for messages that have packed
816     // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
817     // That makes it safe to rely on the memoized size here.
818     printer->Print(variables_,
819       "if (get$capitalized_name$List().size() > 0) {\n"
820       "  output.writeRawVarint32($tag$);\n"
821       "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
822       "}\n"
823       "for (int i = 0; i < $name$_.size(); i++) {\n"
824       "  output.write$capitalized_type$NoTag($repeated_get$(i));\n"
825       "}\n");
826   } else {
827     printer->Print(variables_,
828       "for (int i = 0; i < $name$_.size(); i++) {\n"
829       "  output.write$capitalized_type$($number$, $repeated_get$(i));\n"
830       "}\n");
831   }
832 }
833 
834 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const835 GenerateSerializedSizeCode(io::Printer* printer) const {
836   printer->Print(variables_,
837     "{\n"
838     "  int dataSize = 0;\n");
839   printer->Indent();
840 
841   if (FixedSize(GetType(descriptor_)) == -1) {
842     printer->Print(variables_,
843       "for (int i = 0; i < $name$_.size(); i++) {\n"
844       "  dataSize += com.google.protobuf.CodedOutputStream\n"
845       "    .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
846       "}\n");
847   } else {
848     printer->Print(variables_,
849       "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
850   }
851 
852   printer->Print(
853       "size += dataSize;\n");
854 
855   if (descriptor_->options().packed()) {
856     printer->Print(variables_,
857       "if (!get$capitalized_name$List().isEmpty()) {\n"
858       "  size += $tag_size$;\n"
859       "  size += com.google.protobuf.CodedOutputStream\n"
860       "      .computeInt32SizeNoTag(dataSize);\n"
861       "}\n");
862   } else {
863     printer->Print(variables_,
864       "size += $tag_size$ * get$capitalized_name$List().size();\n");
865   }
866 
867   // cache the data size for packed fields.
868   if (descriptor_->options().packed()) {
869     printer->Print(variables_,
870       "$name$MemoizedSerializedSize = dataSize;\n");
871   }
872 
873   printer->Outdent();
874   printer->Print("}\n");
875 }
876 
877 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateEqualsCode(io::Printer * printer) const878 GenerateEqualsCode(io::Printer* printer) const {
879   printer->Print(variables_,
880     "result = result && get$capitalized_name$List()\n"
881     "    .equals(other.get$capitalized_name$List());\n");
882 }
883 
884 void RepeatedImmutablePrimitiveFieldLiteGenerator::
GenerateHashCode(io::Printer * printer) const885 GenerateHashCode(io::Printer* printer) const {
886   printer->Print(variables_,
887     "if (get$capitalized_name$Count() > 0) {\n"
888     "  hash = (37 * hash) + $constant_name$;\n"
889     "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
890     "}\n");
891 }
892 
GetBoxedType() const893 string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
894   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
895 }
896 
897 }  // namespace java
898 }  // namespace compiler
899 }  // namespace protobuf
900 }  // namespace google
901