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
47namespace google {
48namespace protobuf {
49namespace compiler {
50namespace java {
51
52using internal::WireFormat;
53using internal::WireFormatLite;
54
55const char kThickSeparator[] =
56  "// ===================================================================\n";
57const char kThinSeparator[] =
58  "// -------------------------------------------------------------------\n";
59
60namespace {
61
62const 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.
67const char* kForbiddenWordList[] = {
68  // message base class:
69  "cached_size", "serialized_size",
70  // java.lang.Object:
71  "class",
72};
73
74bool 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
83string 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
104string 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
139string UnderscoresToCamelCase(const FieldDescriptor* field) {
140  return UnderscoresToCamelCase(FieldName(field), false);
141}
142
143string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
144  return UnderscoresToCamelCase(FieldName(field), true);
145}
146
147string UnderscoresToCamelCase(const MethodDescriptor* method) {
148  return UnderscoresToCamelCase(method->name(), false);
149}
150
151string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
152  return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
153}
154
155string StripProto(const string& filename) {
156  if (HasSuffixString(filename, ".protodevel")) {
157    return StripSuffixString(filename, ".protodevel");
158  } else {
159    return StripSuffixString(filename, ".proto");
160  }
161}
162
163string FileClassName(const FileDescriptor* file, bool immutable) {
164  ClassNameResolver name_resolver;
165  return name_resolver.GetFileClassName(file, immutable);
166}
167
168string 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
184string 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.
193string 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
214string ClassName(const Descriptor* descriptor) {
215  ClassNameResolver name_resolver;
216  return name_resolver.GetClassName(descriptor, true);
217}
218
219string ClassName(const EnumDescriptor* descriptor) {
220  ClassNameResolver name_resolver;
221  return name_resolver.GetClassName(descriptor, true);
222}
223
224string ClassName(const ServiceDescriptor* descriptor) {
225  ClassNameResolver name_resolver;
226  return name_resolver.GetClassName(descriptor, true);
227}
228
229string ClassName(const FileDescriptor* descriptor) {
230  ClassNameResolver name_resolver;
231  return name_resolver.GetClassName(descriptor, true);
232}
233
234string ExtraMessageInterfaces(const Descriptor* descriptor) {
235  string interfaces = "// @@protoc_insertion_point(message_implements:"
236      + descriptor->full_name() + ")";
237  return interfaces;
238}
239
240
241string ExtraBuilderInterfaces(const Descriptor* descriptor) {
242  string interfaces = "// @@protoc_insertion_point(builder_implements:"
243      + descriptor->full_name() + ")";
244  return interfaces;
245}
246
247string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) {
248  string interfaces = "// @@protoc_insertion_point(interface_extends:"
249      + descriptor->full_name() + ")";
250  return interfaces;
251}
252
253string FieldConstantName(const FieldDescriptor *field) {
254  string name = field->name() + "_FIELD_NUMBER";
255  UpperString(&name);
256  return name;
257}
258
259FieldDescriptor::Type GetType(const FieldDescriptor* field) {
260  return field->type();
261}
262
263JavaType 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
309const char* BoxedPrimitiveTypeName(JavaType type) {
310  switch (type) {
311    case JAVATYPE_INT    : return "java.lang.Integer";
312    case JAVATYPE_LONG   : return "java.lang.Long";
313    case JAVATYPE_FLOAT  : return "java.lang.Float";
314    case JAVATYPE_DOUBLE : return "java.lang.Double";
315    case JAVATYPE_BOOLEAN: return "java.lang.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
329const char* FieldTypeName(FieldDescriptor::Type field_type) {
330  switch (field_type) {
331    case FieldDescriptor::TYPE_INT32   : return "INT32";
332    case FieldDescriptor::TYPE_UINT32  : return "UINT32";
333    case FieldDescriptor::TYPE_SINT32  : return "SINT32";
334    case FieldDescriptor::TYPE_FIXED32 : return "FIXED32";
335    case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32";
336    case FieldDescriptor::TYPE_INT64   : return "INT64";
337    case FieldDescriptor::TYPE_UINT64  : return "UINT64";
338    case FieldDescriptor::TYPE_SINT64  : return "SINT64";
339    case FieldDescriptor::TYPE_FIXED64 : return "FIXED64";
340    case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64";
341    case FieldDescriptor::TYPE_FLOAT   : return "FLOAT";
342    case FieldDescriptor::TYPE_DOUBLE  : return "DOUBLE";
343    case FieldDescriptor::TYPE_BOOL    : return "BOOL";
344    case FieldDescriptor::TYPE_STRING  : return "STRING";
345    case FieldDescriptor::TYPE_BYTES   : return "BYTES";
346    case FieldDescriptor::TYPE_ENUM    : return "ENUM";
347    case FieldDescriptor::TYPE_GROUP   : return "GROUP";
348    case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
349
350    // No default because we want the compiler to complain if any new
351    // types are added.
352  }
353
354  GOOGLE_LOG(FATAL) << "Can't get here.";
355  return NULL;
356}
357
358bool AllAscii(const string& text) {
359  for (int i = 0; i < text.size(); i++) {
360    if ((text[i] & 0x80) != 0) {
361      return false;
362    }
363  }
364  return true;
365}
366
367string DefaultValue(const FieldDescriptor* field, bool immutable,
368                    ClassNameResolver* name_resolver) {
369  // Switch on CppType since we need to know which default_value_* method
370  // of FieldDescriptor to call.
371  switch (field->cpp_type()) {
372    case FieldDescriptor::CPPTYPE_INT32:
373      return SimpleItoa(field->default_value_int32());
374    case FieldDescriptor::CPPTYPE_UINT32:
375      // Need to print as a signed int since Java has no unsigned.
376      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
377    case FieldDescriptor::CPPTYPE_INT64:
378      return SimpleItoa(field->default_value_int64()) + "L";
379    case FieldDescriptor::CPPTYPE_UINT64:
380      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
381             "L";
382    case FieldDescriptor::CPPTYPE_DOUBLE: {
383      double value = field->default_value_double();
384      if (value == numeric_limits<double>::infinity()) {
385        return "Double.POSITIVE_INFINITY";
386      } else if (value == -numeric_limits<double>::infinity()) {
387        return "Double.NEGATIVE_INFINITY";
388      } else if (value != value) {
389        return "Double.NaN";
390      } else {
391        return SimpleDtoa(value) + "D";
392      }
393    }
394    case FieldDescriptor::CPPTYPE_FLOAT: {
395      float value = field->default_value_float();
396      if (value == numeric_limits<float>::infinity()) {
397        return "Float.POSITIVE_INFINITY";
398      } else if (value == -numeric_limits<float>::infinity()) {
399        return "Float.NEGATIVE_INFINITY";
400      } else if (value != value) {
401        return "Float.NaN";
402      } else {
403        return SimpleFtoa(value) + "F";
404      }
405    }
406    case FieldDescriptor::CPPTYPE_BOOL:
407      return field->default_value_bool() ? "true" : "false";
408    case FieldDescriptor::CPPTYPE_STRING:
409      if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
410        if (field->has_default_value()) {
411          // See comments in Internal.java for gory details.
412          return strings::Substitute(
413            "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
414            CEscape(field->default_value_string()));
415        } else {
416          return "com.google.protobuf.ByteString.EMPTY";
417        }
418      } else {
419        if (AllAscii(field->default_value_string())) {
420          // All chars are ASCII.  In this case CEscape() works fine.
421          return "\"" + CEscape(field->default_value_string()) + "\"";
422        } else {
423          // See comments in Internal.java for gory details.
424          return strings::Substitute(
425              "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
426              CEscape(field->default_value_string()));
427        }
428      }
429
430    case FieldDescriptor::CPPTYPE_ENUM:
431      return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
432          field->default_value_enum()->name();
433
434    case FieldDescriptor::CPPTYPE_MESSAGE:
435      return name_resolver->GetClassName(field->message_type(), immutable) +
436          ".getDefaultInstance()";
437
438    // No default because we want the compiler to complain if any new
439    // types are added.
440  }
441
442  GOOGLE_LOG(FATAL) << "Can't get here.";
443  return "";
444}
445
446bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
447  // Switch on CppType since we need to know which default_value_* method
448  // of FieldDescriptor to call.
449  switch (field->cpp_type()) {
450    case FieldDescriptor::CPPTYPE_INT32:
451      return field->default_value_int32() == 0;
452    case FieldDescriptor::CPPTYPE_UINT32:
453      return field->default_value_uint32() == 0;
454    case FieldDescriptor::CPPTYPE_INT64:
455      return field->default_value_int64() == 0L;
456    case FieldDescriptor::CPPTYPE_UINT64:
457      return field->default_value_uint64() == 0L;
458    case FieldDescriptor::CPPTYPE_DOUBLE:
459      return field->default_value_double() == 0.0;
460    case FieldDescriptor::CPPTYPE_FLOAT:
461      return field->default_value_float() == 0.0;
462    case FieldDescriptor::CPPTYPE_BOOL:
463      return field->default_value_bool() == false;
464
465    case FieldDescriptor::CPPTYPE_STRING:
466    case FieldDescriptor::CPPTYPE_ENUM:
467    case FieldDescriptor::CPPTYPE_MESSAGE:
468      return false;
469
470    // No default because we want the compiler to complain if any new
471    // types are added.
472  }
473
474  GOOGLE_LOG(FATAL) << "Can't get here.";
475  return false;
476}
477
478const char* bit_masks[] = {
479  "0x00000001",
480  "0x00000002",
481  "0x00000004",
482  "0x00000008",
483  "0x00000010",
484  "0x00000020",
485  "0x00000040",
486  "0x00000080",
487
488  "0x00000100",
489  "0x00000200",
490  "0x00000400",
491  "0x00000800",
492  "0x00001000",
493  "0x00002000",
494  "0x00004000",
495  "0x00008000",
496
497  "0x00010000",
498  "0x00020000",
499  "0x00040000",
500  "0x00080000",
501  "0x00100000",
502  "0x00200000",
503  "0x00400000",
504  "0x00800000",
505
506  "0x01000000",
507  "0x02000000",
508  "0x04000000",
509  "0x08000000",
510  "0x10000000",
511  "0x20000000",
512  "0x40000000",
513  "0x80000000",
514};
515
516string GetBitFieldName(int index) {
517  string varName = "bitField";
518  varName += SimpleItoa(index);
519  varName += "_";
520  return varName;
521}
522
523string GetBitFieldNameForBit(int bitIndex) {
524  return GetBitFieldName(bitIndex / 32);
525}
526
527namespace {
528
529string GenerateGetBitInternal(const string& prefix, int bitIndex) {
530  string varName = prefix + GetBitFieldNameForBit(bitIndex);
531  int bitInVarIndex = bitIndex % 32;
532
533  string mask = bit_masks[bitInVarIndex];
534  string result = "((" + varName + " & " + mask + ") == " + mask + ")";
535  return result;
536}
537
538string GenerateSetBitInternal(const string& prefix, int bitIndex) {
539  string varName = prefix + GetBitFieldNameForBit(bitIndex);
540  int bitInVarIndex = bitIndex % 32;
541
542  string mask = bit_masks[bitInVarIndex];
543  string result = varName + " |= " + mask;
544  return result;
545}
546
547}  // namespace
548
549string GenerateGetBit(int bitIndex) {
550  return GenerateGetBitInternal("", bitIndex);
551}
552
553string GenerateSetBit(int bitIndex) {
554  return GenerateSetBitInternal("", bitIndex);
555}
556
557string GenerateClearBit(int bitIndex) {
558  string varName = GetBitFieldNameForBit(bitIndex);
559  int bitInVarIndex = bitIndex % 32;
560
561  string mask = bit_masks[bitInVarIndex];
562  string result = varName + " = (" + varName + " & ~" + mask + ")";
563  return result;
564}
565
566string GenerateGetBitFromLocal(int bitIndex) {
567  return GenerateGetBitInternal("from_", bitIndex);
568}
569
570string GenerateSetBitToLocal(int bitIndex) {
571  return GenerateSetBitInternal("to_", bitIndex);
572}
573
574string GenerateGetBitMutableLocal(int bitIndex) {
575  return GenerateGetBitInternal("mutable_", bitIndex);
576}
577
578string GenerateSetBitMutableLocal(int bitIndex) {
579  return GenerateSetBitInternal("mutable_", bitIndex);
580}
581
582bool IsReferenceType(JavaType type) {
583  switch (type) {
584    case JAVATYPE_INT    : return false;
585    case JAVATYPE_LONG   : return false;
586    case JAVATYPE_FLOAT  : return false;
587    case JAVATYPE_DOUBLE : return false;
588    case JAVATYPE_BOOLEAN: return false;
589    case JAVATYPE_STRING : return true;
590    case JAVATYPE_BYTES  : return true;
591    case JAVATYPE_ENUM   : return true;
592    case JAVATYPE_MESSAGE: return true;
593
594    // No default because we want the compiler to complain if any new
595    // JavaTypes are added.
596  }
597
598  GOOGLE_LOG(FATAL) << "Can't get here.";
599  return false;
600}
601
602const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
603  switch (GetType(field)) {
604    case FieldDescriptor::TYPE_INT32   : return "Int32";
605    case FieldDescriptor::TYPE_UINT32  : return "UInt32";
606    case FieldDescriptor::TYPE_SINT32  : return "SInt32";
607    case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
608    case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
609    case FieldDescriptor::TYPE_INT64   : return "Int64";
610    case FieldDescriptor::TYPE_UINT64  : return "UInt64";
611    case FieldDescriptor::TYPE_SINT64  : return "SInt64";
612    case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
613    case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
614    case FieldDescriptor::TYPE_FLOAT   : return "Float";
615    case FieldDescriptor::TYPE_DOUBLE  : return "Double";
616    case FieldDescriptor::TYPE_BOOL    : return "Bool";
617    case FieldDescriptor::TYPE_STRING  : return "String";
618    case FieldDescriptor::TYPE_BYTES   : {
619      return "Bytes";
620    }
621    case FieldDescriptor::TYPE_ENUM    : return "Enum";
622    case FieldDescriptor::TYPE_GROUP   : return "Group";
623    case FieldDescriptor::TYPE_MESSAGE : return "Message";
624
625    // No default because we want the compiler to complain if any new
626    // types are added.
627  }
628
629  GOOGLE_LOG(FATAL) << "Can't get here.";
630  return NULL;
631}
632
633// For encodings with fixed sizes, returns that size in bytes.  Otherwise
634// returns -1.
635int FixedSize(FieldDescriptor::Type type) {
636  switch (type) {
637    case FieldDescriptor::TYPE_INT32   : return -1;
638    case FieldDescriptor::TYPE_INT64   : return -1;
639    case FieldDescriptor::TYPE_UINT32  : return -1;
640    case FieldDescriptor::TYPE_UINT64  : return -1;
641    case FieldDescriptor::TYPE_SINT32  : return -1;
642    case FieldDescriptor::TYPE_SINT64  : return -1;
643    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
644    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
645    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
646    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
647    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
648    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
649
650    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
651    case FieldDescriptor::TYPE_ENUM    : return -1;
652
653    case FieldDescriptor::TYPE_STRING  : return -1;
654    case FieldDescriptor::TYPE_BYTES   : return -1;
655    case FieldDescriptor::TYPE_GROUP   : return -1;
656    case FieldDescriptor::TYPE_MESSAGE : return -1;
657
658    // No default because we want the compiler to complain if any new
659    // types are added.
660  }
661  GOOGLE_LOG(FATAL) << "Can't get here.";
662  return -1;
663}
664
665// Sort the fields of the given Descriptor by number into a new[]'d array
666// and return it. The caller should delete the returned array.
667const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
668  const FieldDescriptor** fields =
669    new const FieldDescriptor*[descriptor->field_count()];
670  for (int i = 0; i < descriptor->field_count(); i++) {
671    fields[i] = descriptor->field(i);
672  }
673  sort(fields, fields + descriptor->field_count(),
674       FieldOrderingByNumber());
675  return fields;
676}
677
678// Returns true if the message type has any required fields.  If it doesn't,
679// we can optimize out calls to its isInitialized() method.
680//
681// already_seen is used to avoid checking the same type multiple times
682// (and also to protect against recursion).
683bool HasRequiredFields(
684    const Descriptor* type,
685    hash_set<const Descriptor*>* already_seen) {
686  if (already_seen->count(type) > 0) {
687    // The type is already in cache.  This means that either:
688    // a. The type has no required fields.
689    // b. We are in the midst of checking if the type has required fields,
690    //    somewhere up the stack.  In this case, we know that if the type
691    //    has any required fields, they'll be found when we return to it,
692    //    and the whole call to HasRequiredFields() will return true.
693    //    Therefore, we don't have to check if this type has required fields
694    //    here.
695    return false;
696  }
697  already_seen->insert(type);
698
699  // If the type has extensions, an extension with message type could contain
700  // required fields, so we have to be conservative and assume such an
701  // extension exists.
702  if (type->extension_range_count() > 0) return true;
703
704  for (int i = 0; i < type->field_count(); i++) {
705    const FieldDescriptor* field = type->field(i);
706    if (field->is_required()) {
707      return true;
708    }
709    if (GetJavaType(field) == JAVATYPE_MESSAGE) {
710      if (HasRequiredFields(field->message_type(), already_seen)) {
711        return true;
712      }
713    }
714  }
715
716  return false;
717}
718
719bool HasRequiredFields(const Descriptor* type) {
720  hash_set<const Descriptor*> already_seen;
721  return HasRequiredFields(type, &already_seen);
722}
723
724bool HasRepeatedFields(const Descriptor* descriptor) {
725  for (int i = 0; i < descriptor->field_count(); ++i) {
726    const FieldDescriptor* field = descriptor->field(i);
727    if (field->is_repeated()) {
728      return true;
729    }
730  }
731  return false;
732}
733
734}  // namespace java
735}  // namespace compiler
736}  // namespace protobuf
737}  // namespace google
738