• 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 <algorithm>
36 #include <google/protobuf/stubs/hash.h>
37 #include <limits>
38 #include <vector>
39 
40 #include <google/protobuf/compiler/java/java_helpers.h>
41 #include <google/protobuf/compiler/java/java_name_resolver.h>
42 #include <google/protobuf/descriptor.pb.h>
43 #include <google/protobuf/wire_format.h>
44 #include <google/protobuf/stubs/strutil.h>
45 #include <google/protobuf/stubs/substitute.h>
46 
47 namespace google {
48 namespace protobuf {
49 namespace compiler {
50 namespace java {
51 
52 using internal::WireFormat;
53 using internal::WireFormatLite;
54 
55 const char kThickSeparator[] =
56   "// ===================================================================\n";
57 const char kThinSeparator[] =
58   "// -------------------------------------------------------------------\n";
59 
60 namespace {
61 
62 const char* kDefaultPackage = "";
63 
64 // Names that should be avoided as field names.
65 // Using them will cause the compiler to generate accessors whose names are
66 // colliding with methods defined in base classes.
67 const char* kForbiddenWordList[] = {
68   // message base class:
69   "cached_size", "serialized_size",
70   // java.lang.Object:
71   "class",
72 };
73 
IsForbidden(const string & field_name)74 bool IsForbidden(const string& field_name) {
75   for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
76     if (field_name == kForbiddenWordList[i]) {
77       return true;
78     }
79   }
80   return false;
81 }
82 
FieldName(const FieldDescriptor * field)83 string FieldName(const FieldDescriptor* field) {
84   string field_name;
85   // Groups are hacky:  The name of the field is just the lower-cased name
86   // of the group type.  In Java, though, we would like to retain the original
87   // capitalization of the type name.
88   if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
89     field_name = field->message_type()->name();
90   } else {
91     field_name = field->name();
92   }
93   if (IsForbidden(field_name)) {
94     // Append a trailing "#" to indicate that the name should be decorated to
95     // avoid collision with other names.
96     field_name += "#";
97   }
98   return field_name;
99 }
100 
101 
102 }  // namespace
103 
UnderscoresToCamelCase(const string & input,bool cap_next_letter)104 string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
105   string result;
106   // Note:  I distrust ctype.h due to locales.
107   for (int i = 0; i < input.size(); i++) {
108     if ('a' <= input[i] && input[i] <= 'z') {
109       if (cap_next_letter) {
110         result += input[i] + ('A' - 'a');
111       } else {
112         result += input[i];
113       }
114       cap_next_letter = false;
115     } else if ('A' <= input[i] && input[i] <= 'Z') {
116       if (i == 0 && !cap_next_letter) {
117         // Force first letter to lower-case unless explicitly told to
118         // capitalize it.
119         result += input[i] + ('a' - 'A');
120       } else {
121         // Capital letters after the first are left as-is.
122         result += input[i];
123       }
124       cap_next_letter = false;
125     } else if ('0' <= input[i] && input[i] <= '9') {
126       result += input[i];
127       cap_next_letter = true;
128     } else {
129       cap_next_letter = true;
130     }
131   }
132   // Add a trailing "_" if the name should be altered.
133   if (input[input.size() - 1] == '#') {
134     result += '_';
135   }
136   return result;
137 }
138 
UnderscoresToCamelCase(const FieldDescriptor * field)139 string UnderscoresToCamelCase(const FieldDescriptor* field) {
140   return UnderscoresToCamelCase(FieldName(field), false);
141 }
142 
UnderscoresToCapitalizedCamelCase(const FieldDescriptor * field)143 string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
144   return UnderscoresToCamelCase(FieldName(field), true);
145 }
146 
UnderscoresToCamelCase(const MethodDescriptor * method)147 string UnderscoresToCamelCase(const MethodDescriptor* method) {
148   return UnderscoresToCamelCase(method->name(), false);
149 }
150 
UniqueFileScopeIdentifier(const Descriptor * descriptor)151 string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
152   return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
153 }
154 
StripProto(const string & filename)155 string StripProto(const string& filename) {
156   if (HasSuffixString(filename, ".protodevel")) {
157     return StripSuffixString(filename, ".protodevel");
158   } else {
159     return StripSuffixString(filename, ".proto");
160   }
161 }
162 
FileClassName(const FileDescriptor * file,bool immutable)163 string FileClassName(const FileDescriptor* file, bool immutable) {
164   ClassNameResolver name_resolver;
165   return name_resolver.GetFileClassName(file, immutable);
166 }
167 
FileJavaPackage(const FileDescriptor * file,bool immutable)168 string FileJavaPackage(const FileDescriptor* file, bool immutable) {
169   string result;
170 
171   if (file->options().has_java_package()) {
172     result = file->options().java_package();
173   } else {
174     result = kDefaultPackage;
175     if (!file->package().empty()) {
176       if (!result.empty()) result += '.';
177       result += file->package();
178     }
179   }
180 
181   return result;
182 }
183 
JavaPackageToDir(string package_name)184 string JavaPackageToDir(string package_name) {
185   string package_dir =
186     StringReplace(package_name, ".", "/", true);
187   if (!package_dir.empty()) package_dir += "/";
188   return package_dir;
189 }
190 
191 // TODO(xiaofeng): This function is only kept for it's publicly referenced.
192 // It should be removed after mutable API up-integration.
ToJavaName(const string & full_name,const FileDescriptor * file)193 string ToJavaName(const string& full_name,
194                   const FileDescriptor* file) {
195   string result;
196   if (file->options().java_multiple_files()) {
197     result = FileJavaPackage(file);
198   } else {
199     result = ClassName(file);
200   }
201   if (!result.empty()) {
202     result += '.';
203   }
204   if (file->package().empty()) {
205     result += full_name;
206   } else {
207     // Strip the proto package from full_name since we've replaced it with
208     // the Java package.
209     result += full_name.substr(file->package().size() + 1);
210   }
211   return result;
212 }
213 
ClassName(const Descriptor * descriptor)214 string ClassName(const Descriptor* descriptor) {
215   ClassNameResolver name_resolver;
216   return name_resolver.GetClassName(descriptor, true);
217 }
218 
ClassName(const EnumDescriptor * descriptor)219 string ClassName(const EnumDescriptor* descriptor) {
220   ClassNameResolver name_resolver;
221   return name_resolver.GetClassName(descriptor, true);
222 }
223 
ClassName(const ServiceDescriptor * descriptor)224 string ClassName(const ServiceDescriptor* descriptor) {
225   ClassNameResolver name_resolver;
226   return name_resolver.GetClassName(descriptor, true);
227 }
228 
ClassName(const FileDescriptor * descriptor)229 string ClassName(const FileDescriptor* descriptor) {
230   ClassNameResolver name_resolver;
231   return name_resolver.GetClassName(descriptor, true);
232 }
233 
ExtraMessageInterfaces(const Descriptor * descriptor)234 string ExtraMessageInterfaces(const Descriptor* descriptor) {
235   string interfaces = "// @@protoc_insertion_point(message_implements:"
236       + descriptor->full_name() + ")";
237   return interfaces;
238 }
239 
240 
ExtraBuilderInterfaces(const Descriptor * descriptor)241 string ExtraBuilderInterfaces(const Descriptor* descriptor) {
242   string interfaces = "// @@protoc_insertion_point(builder_implements:"
243       + descriptor->full_name() + ")";
244   return interfaces;
245 }
246 
ExtraMessageOrBuilderInterfaces(const Descriptor * descriptor)247 string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) {
248   string interfaces = "// @@protoc_insertion_point(interface_extends:"
249       + descriptor->full_name() + ")";
250   return interfaces;
251 }
252 
FieldConstantName(const FieldDescriptor * field)253 string FieldConstantName(const FieldDescriptor *field) {
254   string name = field->name() + "_FIELD_NUMBER";
255   UpperString(&name);
256   return name;
257 }
258 
GetType(const FieldDescriptor * field)259 FieldDescriptor::Type GetType(const FieldDescriptor* field) {
260   return field->type();
261 }
262 
GetJavaType(const FieldDescriptor * field)263 JavaType GetJavaType(const FieldDescriptor* field) {
264   switch (GetType(field)) {
265     case FieldDescriptor::TYPE_INT32:
266     case FieldDescriptor::TYPE_UINT32:
267     case FieldDescriptor::TYPE_SINT32:
268     case FieldDescriptor::TYPE_FIXED32:
269     case FieldDescriptor::TYPE_SFIXED32:
270       return JAVATYPE_INT;
271 
272     case FieldDescriptor::TYPE_INT64:
273     case FieldDescriptor::TYPE_UINT64:
274     case FieldDescriptor::TYPE_SINT64:
275     case FieldDescriptor::TYPE_FIXED64:
276     case FieldDescriptor::TYPE_SFIXED64:
277       return JAVATYPE_LONG;
278 
279     case FieldDescriptor::TYPE_FLOAT:
280       return JAVATYPE_FLOAT;
281 
282     case FieldDescriptor::TYPE_DOUBLE:
283       return JAVATYPE_DOUBLE;
284 
285     case FieldDescriptor::TYPE_BOOL:
286       return JAVATYPE_BOOLEAN;
287 
288     case FieldDescriptor::TYPE_STRING:
289       return JAVATYPE_STRING;
290 
291     case FieldDescriptor::TYPE_BYTES:
292       return JAVATYPE_BYTES;
293 
294     case FieldDescriptor::TYPE_ENUM:
295       return JAVATYPE_ENUM;
296 
297     case FieldDescriptor::TYPE_GROUP:
298     case FieldDescriptor::TYPE_MESSAGE:
299       return JAVATYPE_MESSAGE;
300 
301     // No default because we want the compiler to complain if any new
302     // types are added.
303   }
304 
305   GOOGLE_LOG(FATAL) << "Can't get here.";
306   return JAVATYPE_INT;
307 }
308 
PrimitiveTypeName(JavaType type)309 const char* PrimitiveTypeName(JavaType type) {
310   switch (type) {
311     case JAVATYPE_INT    : return "int";
312     case JAVATYPE_LONG   : return "long";
313     case JAVATYPE_FLOAT  : return "float";
314     case JAVATYPE_DOUBLE : return "double";
315     case JAVATYPE_BOOLEAN: return "boolean";
316     case JAVATYPE_STRING : return "java.lang.String";
317     case JAVATYPE_BYTES  : return "com.google.protobuf.ByteString";
318     case JAVATYPE_ENUM   : return NULL;
319     case JAVATYPE_MESSAGE: return NULL;
320 
321     // No default because we want the compiler to complain if any new
322     // JavaTypes are added.
323   }
324 
325   GOOGLE_LOG(FATAL) << "Can't get here.";
326   return NULL;
327 }
328 
BoxedPrimitiveTypeName(JavaType type)329 const char* BoxedPrimitiveTypeName(JavaType type) {
330   switch (type) {
331     case JAVATYPE_INT    : return "java.lang.Integer";
332     case JAVATYPE_LONG   : return "java.lang.Long";
333     case JAVATYPE_FLOAT  : return "java.lang.Float";
334     case JAVATYPE_DOUBLE : return "java.lang.Double";
335     case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
336     case JAVATYPE_STRING : return "java.lang.String";
337     case JAVATYPE_BYTES  : return "com.google.protobuf.ByteString";
338     case JAVATYPE_ENUM   : return NULL;
339     case JAVATYPE_MESSAGE: return NULL;
340 
341     // No default because we want the compiler to complain if any new
342     // JavaTypes are added.
343   }
344 
345   GOOGLE_LOG(FATAL) << "Can't get here.";
346   return NULL;
347 }
348 
FieldTypeName(FieldDescriptor::Type field_type)349 const char* FieldTypeName(FieldDescriptor::Type field_type) {
350   switch (field_type) {
351     case FieldDescriptor::TYPE_INT32   : return "INT32";
352     case FieldDescriptor::TYPE_UINT32  : return "UINT32";
353     case FieldDescriptor::TYPE_SINT32  : return "SINT32";
354     case FieldDescriptor::TYPE_FIXED32 : return "FIXED32";
355     case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32";
356     case FieldDescriptor::TYPE_INT64   : return "INT64";
357     case FieldDescriptor::TYPE_UINT64  : return "UINT64";
358     case FieldDescriptor::TYPE_SINT64  : return "SINT64";
359     case FieldDescriptor::TYPE_FIXED64 : return "FIXED64";
360     case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64";
361     case FieldDescriptor::TYPE_FLOAT   : return "FLOAT";
362     case FieldDescriptor::TYPE_DOUBLE  : return "DOUBLE";
363     case FieldDescriptor::TYPE_BOOL    : return "BOOL";
364     case FieldDescriptor::TYPE_STRING  : return "STRING";
365     case FieldDescriptor::TYPE_BYTES   : return "BYTES";
366     case FieldDescriptor::TYPE_ENUM    : return "ENUM";
367     case FieldDescriptor::TYPE_GROUP   : return "GROUP";
368     case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
369 
370     // No default because we want the compiler to complain if any new
371     // types are added.
372   }
373 
374   GOOGLE_LOG(FATAL) << "Can't get here.";
375   return NULL;
376 }
377 
AllAscii(const string & text)378 bool AllAscii(const string& text) {
379   for (int i = 0; i < text.size(); i++) {
380     if ((text[i] & 0x80) != 0) {
381       return false;
382     }
383   }
384   return true;
385 }
386 
DefaultValue(const FieldDescriptor * field,bool immutable,ClassNameResolver * name_resolver)387 string DefaultValue(const FieldDescriptor* field, bool immutable,
388                     ClassNameResolver* name_resolver) {
389   // Switch on CppType since we need to know which default_value_* method
390   // of FieldDescriptor to call.
391   switch (field->cpp_type()) {
392     case FieldDescriptor::CPPTYPE_INT32:
393       return SimpleItoa(field->default_value_int32());
394     case FieldDescriptor::CPPTYPE_UINT32:
395       // Need to print as a signed int since Java has no unsigned.
396       return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
397     case FieldDescriptor::CPPTYPE_INT64:
398       return SimpleItoa(field->default_value_int64()) + "L";
399     case FieldDescriptor::CPPTYPE_UINT64:
400       return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
401              "L";
402     case FieldDescriptor::CPPTYPE_DOUBLE: {
403       double value = field->default_value_double();
404       if (value == numeric_limits<double>::infinity()) {
405         return "Double.POSITIVE_INFINITY";
406       } else if (value == -numeric_limits<double>::infinity()) {
407         return "Double.NEGATIVE_INFINITY";
408       } else if (value != value) {
409         return "Double.NaN";
410       } else {
411         return SimpleDtoa(value) + "D";
412       }
413     }
414     case FieldDescriptor::CPPTYPE_FLOAT: {
415       float value = field->default_value_float();
416       if (value == numeric_limits<float>::infinity()) {
417         return "Float.POSITIVE_INFINITY";
418       } else if (value == -numeric_limits<float>::infinity()) {
419         return "Float.NEGATIVE_INFINITY";
420       } else if (value != value) {
421         return "Float.NaN";
422       } else {
423         return SimpleFtoa(value) + "F";
424       }
425     }
426     case FieldDescriptor::CPPTYPE_BOOL:
427       return field->default_value_bool() ? "true" : "false";
428     case FieldDescriptor::CPPTYPE_STRING:
429       if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
430         if (field->has_default_value()) {
431           // See comments in Internal.java for gory details.
432           return strings::Substitute(
433             "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
434             CEscape(field->default_value_string()));
435         } else {
436           return "com.google.protobuf.ByteString.EMPTY";
437         }
438       } else {
439         if (AllAscii(field->default_value_string())) {
440           // All chars are ASCII.  In this case CEscape() works fine.
441           return "\"" + CEscape(field->default_value_string()) + "\"";
442         } else {
443           // See comments in Internal.java for gory details.
444           return strings::Substitute(
445               "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
446               CEscape(field->default_value_string()));
447         }
448       }
449 
450     case FieldDescriptor::CPPTYPE_ENUM:
451       return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
452           field->default_value_enum()->name();
453 
454     case FieldDescriptor::CPPTYPE_MESSAGE:
455       return name_resolver->GetClassName(field->message_type(), immutable) +
456           ".getDefaultInstance()";
457 
458     // No default because we want the compiler to complain if any new
459     // types are added.
460   }
461 
462   GOOGLE_LOG(FATAL) << "Can't get here.";
463   return "";
464 }
465 
IsDefaultValueJavaDefault(const FieldDescriptor * field)466 bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
467   // Switch on CppType since we need to know which default_value_* method
468   // of FieldDescriptor to call.
469   switch (field->cpp_type()) {
470     case FieldDescriptor::CPPTYPE_INT32:
471       return field->default_value_int32() == 0;
472     case FieldDescriptor::CPPTYPE_UINT32:
473       return field->default_value_uint32() == 0;
474     case FieldDescriptor::CPPTYPE_INT64:
475       return field->default_value_int64() == 0L;
476     case FieldDescriptor::CPPTYPE_UINT64:
477       return field->default_value_uint64() == 0L;
478     case FieldDescriptor::CPPTYPE_DOUBLE:
479       return field->default_value_double() == 0.0;
480     case FieldDescriptor::CPPTYPE_FLOAT:
481       return field->default_value_float() == 0.0;
482     case FieldDescriptor::CPPTYPE_BOOL:
483       return field->default_value_bool() == false;
484 
485     case FieldDescriptor::CPPTYPE_STRING:
486     case FieldDescriptor::CPPTYPE_ENUM:
487     case FieldDescriptor::CPPTYPE_MESSAGE:
488       return false;
489 
490     // No default because we want the compiler to complain if any new
491     // types are added.
492   }
493 
494   GOOGLE_LOG(FATAL) << "Can't get here.";
495   return false;
496 }
497 
498 const char* bit_masks[] = {
499   "0x00000001",
500   "0x00000002",
501   "0x00000004",
502   "0x00000008",
503   "0x00000010",
504   "0x00000020",
505   "0x00000040",
506   "0x00000080",
507 
508   "0x00000100",
509   "0x00000200",
510   "0x00000400",
511   "0x00000800",
512   "0x00001000",
513   "0x00002000",
514   "0x00004000",
515   "0x00008000",
516 
517   "0x00010000",
518   "0x00020000",
519   "0x00040000",
520   "0x00080000",
521   "0x00100000",
522   "0x00200000",
523   "0x00400000",
524   "0x00800000",
525 
526   "0x01000000",
527   "0x02000000",
528   "0x04000000",
529   "0x08000000",
530   "0x10000000",
531   "0x20000000",
532   "0x40000000",
533   "0x80000000",
534 };
535 
GetBitFieldName(int index)536 string GetBitFieldName(int index) {
537   string varName = "bitField";
538   varName += SimpleItoa(index);
539   varName += "_";
540   return varName;
541 }
542 
GetBitFieldNameForBit(int bitIndex)543 string GetBitFieldNameForBit(int bitIndex) {
544   return GetBitFieldName(bitIndex / 32);
545 }
546 
547 namespace {
548 
GenerateGetBitInternal(const string & prefix,int bitIndex)549 string GenerateGetBitInternal(const string& prefix, int bitIndex) {
550   string varName = prefix + GetBitFieldNameForBit(bitIndex);
551   int bitInVarIndex = bitIndex % 32;
552 
553   string mask = bit_masks[bitInVarIndex];
554   string result = "((" + varName + " & " + mask + ") == " + mask + ")";
555   return result;
556 }
557 
GenerateSetBitInternal(const string & prefix,int bitIndex)558 string GenerateSetBitInternal(const string& prefix, int bitIndex) {
559   string varName = prefix + GetBitFieldNameForBit(bitIndex);
560   int bitInVarIndex = bitIndex % 32;
561 
562   string mask = bit_masks[bitInVarIndex];
563   string result = varName + " |= " + mask;
564   return result;
565 }
566 
567 }  // namespace
568 
GenerateGetBit(int bitIndex)569 string GenerateGetBit(int bitIndex) {
570   return GenerateGetBitInternal("", bitIndex);
571 }
572 
GenerateSetBit(int bitIndex)573 string GenerateSetBit(int bitIndex) {
574   return GenerateSetBitInternal("", bitIndex);
575 }
576 
GenerateClearBit(int bitIndex)577 string GenerateClearBit(int bitIndex) {
578   string varName = GetBitFieldNameForBit(bitIndex);
579   int bitInVarIndex = bitIndex % 32;
580 
581   string mask = bit_masks[bitInVarIndex];
582   string result = varName + " = (" + varName + " & ~" + mask + ")";
583   return result;
584 }
585 
GenerateGetBitFromLocal(int bitIndex)586 string GenerateGetBitFromLocal(int bitIndex) {
587   return GenerateGetBitInternal("from_", bitIndex);
588 }
589 
GenerateSetBitToLocal(int bitIndex)590 string GenerateSetBitToLocal(int bitIndex) {
591   return GenerateSetBitInternal("to_", bitIndex);
592 }
593 
GenerateGetBitMutableLocal(int bitIndex)594 string GenerateGetBitMutableLocal(int bitIndex) {
595   return GenerateGetBitInternal("mutable_", bitIndex);
596 }
597 
GenerateSetBitMutableLocal(int bitIndex)598 string GenerateSetBitMutableLocal(int bitIndex) {
599   return GenerateSetBitInternal("mutable_", bitIndex);
600 }
601 
IsReferenceType(JavaType type)602 bool IsReferenceType(JavaType type) {
603   switch (type) {
604     case JAVATYPE_INT    : return false;
605     case JAVATYPE_LONG   : return false;
606     case JAVATYPE_FLOAT  : return false;
607     case JAVATYPE_DOUBLE : return false;
608     case JAVATYPE_BOOLEAN: return false;
609     case JAVATYPE_STRING : return true;
610     case JAVATYPE_BYTES  : return true;
611     case JAVATYPE_ENUM   : return true;
612     case JAVATYPE_MESSAGE: return true;
613 
614     // No default because we want the compiler to complain if any new
615     // JavaTypes are added.
616   }
617 
618   GOOGLE_LOG(FATAL) << "Can't get here.";
619   return false;
620 }
621 
GetCapitalizedType(const FieldDescriptor * field,bool immutable)622 const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
623   switch (GetType(field)) {
624     case FieldDescriptor::TYPE_INT32   : return "Int32";
625     case FieldDescriptor::TYPE_UINT32  : return "UInt32";
626     case FieldDescriptor::TYPE_SINT32  : return "SInt32";
627     case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
628     case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
629     case FieldDescriptor::TYPE_INT64   : return "Int64";
630     case FieldDescriptor::TYPE_UINT64  : return "UInt64";
631     case FieldDescriptor::TYPE_SINT64  : return "SInt64";
632     case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
633     case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
634     case FieldDescriptor::TYPE_FLOAT   : return "Float";
635     case FieldDescriptor::TYPE_DOUBLE  : return "Double";
636     case FieldDescriptor::TYPE_BOOL    : return "Bool";
637     case FieldDescriptor::TYPE_STRING  : return "String";
638     case FieldDescriptor::TYPE_BYTES   : {
639       return "Bytes";
640     }
641     case FieldDescriptor::TYPE_ENUM    : return "Enum";
642     case FieldDescriptor::TYPE_GROUP   : return "Group";
643     case FieldDescriptor::TYPE_MESSAGE : return "Message";
644 
645     // No default because we want the compiler to complain if any new
646     // types are added.
647   }
648 
649   GOOGLE_LOG(FATAL) << "Can't get here.";
650   return NULL;
651 }
652 
653 // For encodings with fixed sizes, returns that size in bytes.  Otherwise
654 // returns -1.
FixedSize(FieldDescriptor::Type type)655 int FixedSize(FieldDescriptor::Type type) {
656   switch (type) {
657     case FieldDescriptor::TYPE_INT32   : return -1;
658     case FieldDescriptor::TYPE_INT64   : return -1;
659     case FieldDescriptor::TYPE_UINT32  : return -1;
660     case FieldDescriptor::TYPE_UINT64  : return -1;
661     case FieldDescriptor::TYPE_SINT32  : return -1;
662     case FieldDescriptor::TYPE_SINT64  : return -1;
663     case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
664     case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
665     case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
666     case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
667     case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
668     case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
669 
670     case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
671     case FieldDescriptor::TYPE_ENUM    : return -1;
672 
673     case FieldDescriptor::TYPE_STRING  : return -1;
674     case FieldDescriptor::TYPE_BYTES   : return -1;
675     case FieldDescriptor::TYPE_GROUP   : return -1;
676     case FieldDescriptor::TYPE_MESSAGE : return -1;
677 
678     // No default because we want the compiler to complain if any new
679     // types are added.
680   }
681   GOOGLE_LOG(FATAL) << "Can't get here.";
682   return -1;
683 }
684 
685 // Sort the fields of the given Descriptor by number into a new[]'d array
686 // and return it. The caller should delete the returned array.
SortFieldsByNumber(const Descriptor * descriptor)687 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
688   const FieldDescriptor** fields =
689     new const FieldDescriptor*[descriptor->field_count()];
690   for (int i = 0; i < descriptor->field_count(); i++) {
691     fields[i] = descriptor->field(i);
692   }
693   std::sort(fields, fields + descriptor->field_count(),
694             FieldOrderingByNumber());
695   return fields;
696 }
697 
698 // Returns true if the message type has any required fields.  If it doesn't,
699 // we can optimize out calls to its isInitialized() method.
700 //
701 // already_seen is used to avoid checking the same type multiple times
702 // (and also to protect against recursion).
HasRequiredFields(const Descriptor * type,hash_set<const Descriptor * > * already_seen)703 bool HasRequiredFields(
704     const Descriptor* type,
705     hash_set<const Descriptor*>* already_seen) {
706   if (already_seen->count(type) > 0) {
707     // The type is already in cache.  This means that either:
708     // a. The type has no required fields.
709     // b. We are in the midst of checking if the type has required fields,
710     //    somewhere up the stack.  In this case, we know that if the type
711     //    has any required fields, they'll be found when we return to it,
712     //    and the whole call to HasRequiredFields() will return true.
713     //    Therefore, we don't have to check if this type has required fields
714     //    here.
715     return false;
716   }
717   already_seen->insert(type);
718 
719   // If the type has extensions, an extension with message type could contain
720   // required fields, so we have to be conservative and assume such an
721   // extension exists.
722   if (type->extension_range_count() > 0) return true;
723 
724   for (int i = 0; i < type->field_count(); i++) {
725     const FieldDescriptor* field = type->field(i);
726     if (field->is_required()) {
727       return true;
728     }
729     if (GetJavaType(field) == JAVATYPE_MESSAGE) {
730       if (HasRequiredFields(field->message_type(), already_seen)) {
731         return true;
732       }
733     }
734   }
735 
736   return false;
737 }
738 
HasRequiredFields(const Descriptor * type)739 bool HasRequiredFields(const Descriptor* type) {
740   hash_set<const Descriptor*> already_seen;
741   return HasRequiredFields(type, &already_seen);
742 }
743 
HasRepeatedFields(const Descriptor * descriptor)744 bool HasRepeatedFields(const Descriptor* descriptor) {
745   for (int i = 0; i < descriptor->field_count(); ++i) {
746     const FieldDescriptor* field = descriptor->field(i);
747     if (field->is_repeated()) {
748       return true;
749     }
750   }
751   return false;
752 }
753 
754 }  // namespace java
755 }  // namespace compiler
756 }  // namespace protobuf
757 }  // namespace google
758