1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
37 #include <unordered_set>
40 #include <google/protobuf/stubs/stringprintf.h>
41 #include <google/protobuf/compiler/java/java_helpers.h>
42 #include <google/protobuf/compiler/java/java_name_resolver.h>
43 #include <google/protobuf/descriptor.pb.h>
44 #include <google/protobuf/wire_format.h>
45 #include <google/protobuf/stubs/strutil.h>
46 #include <google/protobuf/stubs/substitute.h>
50 #include <google/protobuf/stubs/hash.h> // for hash<T *>
57 using internal::WireFormat;
58 using internal::WireFormatLite;
60 const char kThickSeparator[] =
61 "// ===================================================================\n";
62 const char kThinSeparator[] =
63 "// -------------------------------------------------------------------\n";
67 const char* kDefaultPackage = "";
69 // Names that should be avoided as field names.
70 // Using them will cause the compiler to generate accessors whose names are
71 // colliding with methods defined in base classes.
72 const char* kForbiddenWordList[] = {
73 // message base class:
80 const std::unordered_set<string>* kReservedNames =
81 new std::unordered_set<string>({
82 "abstract", "assert", "boolean", "break", "byte",
83 "case", "catch", "char", "class", "const",
84 "continue", "default", "do", "double", "else",
85 "enum", "extends", "final", "finally", "float",
86 "for", "goto", "if", "implements", "import",
87 "instanceof", "int", "interface", "long", "native",
88 "new", "package", "private", "protected", "public",
89 "return", "short", "static", "strictfp", "super",
90 "switch", "synchronized", "this", "throw", "throws",
91 "transient", "try", "void", "volatile", "while",
94 bool IsForbidden(const std::string& field_name) {
95 for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
96 if (field_name == kForbiddenWordList[i]) {
103 std::string FieldName(const FieldDescriptor* field) {
104 std::string field_name;
105 // Groups are hacky: The name of the field is just the lower-cased name
106 // of the group type. In Java, though, we would like to retain the original
107 // capitalization of the type name.
108 if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
109 field_name = field->message_type()->name();
111 field_name = field->name();
113 if (IsForbidden(field_name)) {
114 // Append a trailing "#" to indicate that the name should be decorated to
115 // avoid collision with other names.
124 void PrintGeneratedAnnotation(io::Printer* printer, char delimiter,
125 const std::string& annotation_file) {
126 if (annotation_file.empty()) {
129 std::string ptemplate =
130 "@javax.annotation.Generated(value=\"protoc\", comments=\"annotations:";
131 ptemplate.push_back(delimiter);
132 ptemplate.append("annotation_file");
133 ptemplate.push_back(delimiter);
134 ptemplate.append("\")\n");
135 printer->Print(ptemplate.c_str(), "annotation_file", annotation_file);
138 void PrintEnumVerifierLogic(io::Printer* printer,
139 const FieldDescriptor* descriptor,
140 const std::map<std::string, std::string>& variables,
141 const char* var_name,
142 const char* terminating_string, bool enforce_lite) {
143 std::string enum_verifier_string =
144 enforce_lite ? StrCat(var_name, ".internalGetVerifier()")
146 "new com.google.protobuf.Internal.EnumVerifier() {\n"
147 " @java.lang.Override\n"
148 " public boolean isInRange(int number) {\n"
151 ".forNumber(number) != null;\n"
156 StrCat(enum_verifier_string, terminating_string).c_str());
159 std::string UnderscoresToCamelCase(const std::string& input,
160 bool cap_next_letter) {
161 GOOGLE_CHECK(!input.empty());
163 // Note: I distrust ctype.h due to locales.
164 for (int i = 0; i < input.size(); i++) {
165 if ('a' <= input[i] && input[i] <= 'z') {
166 if (cap_next_letter) {
167 result += input[i] + ('A' - 'a');
171 cap_next_letter = false;
172 } else if ('A' <= input[i] && input[i] <= 'Z') {
173 if (i == 0 && !cap_next_letter) {
174 // Force first letter to lower-case unless explicitly told to
176 result += input[i] + ('a' - 'A');
178 // Capital letters after the first are left as-is.
181 cap_next_letter = false;
182 } else if ('0' <= input[i] && input[i] <= '9') {
184 cap_next_letter = true;
186 cap_next_letter = true;
189 // Add a trailing "_" if the name should be altered.
190 if (input[input.size() - 1] == '#') {
196 std::string UnderscoresToCamelCase(const FieldDescriptor* field) {
197 return UnderscoresToCamelCase(FieldName(field), false);
200 std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
201 return UnderscoresToCamelCase(FieldName(field), true);
204 std::string CapitalizedFieldName(const FieldDescriptor* field) {
205 return UnderscoresToCapitalizedCamelCase(field);
208 std::string UnderscoresToCamelCase(const MethodDescriptor* method) {
209 return UnderscoresToCamelCase(method->name(), false);
212 std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) {
213 std::string name = UnderscoresToCamelCase(field);
214 if (kReservedNames->find(name) != kReservedNames->end()) {
220 std::string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
221 return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
224 std::string CamelCaseFieldName(const FieldDescriptor* field) {
225 std::string fieldName = UnderscoresToCamelCase(field);
226 if ('0' <= fieldName[0] && fieldName[0] <= '9') {
227 return '_' + fieldName;
232 std::string StripProto(const std::string& filename) {
233 if (HasSuffixString(filename, ".protodevel")) {
234 return StripSuffixString(filename, ".protodevel");
236 return StripSuffixString(filename, ".proto");
240 std::string FileClassName(const FileDescriptor* file, bool immutable) {
241 ClassNameResolver name_resolver;
242 return name_resolver.GetFileClassName(file, immutable);
245 std::string FileJavaPackage(const FileDescriptor* file, bool immutable) {
248 if (file->options().has_java_package()) {
249 result = file->options().java_package();
251 result = kDefaultPackage;
252 if (!file->package().empty()) {
253 if (!result.empty()) result += '.';
254 result += file->package();
261 std::string FileJavaPackage(const FileDescriptor* file) {
262 return FileJavaPackage(file, true /* immutable */);
265 std::string JavaPackageToDir(std::string package_name) {
266 std::string package_dir = StringReplace(package_name, ".", "/", true);
267 if (!package_dir.empty()) package_dir += "/";
271 std::string ClassName(const Descriptor* descriptor) {
272 ClassNameResolver name_resolver;
273 return name_resolver.GetClassName(descriptor, true);
276 std::string ClassName(const EnumDescriptor* descriptor) {
277 ClassNameResolver name_resolver;
278 return name_resolver.GetClassName(descriptor, true);
281 std::string ClassName(const ServiceDescriptor* descriptor) {
282 ClassNameResolver name_resolver;
283 return name_resolver.GetClassName(descriptor, true);
286 std::string ClassName(const FileDescriptor* descriptor) {
287 ClassNameResolver name_resolver;
288 return name_resolver.GetClassName(descriptor, true);
292 std::string ExtraMessageInterfaces(const Descriptor* descriptor) {
293 std::string interfaces = "// @@protoc_insertion_point(message_implements:" +
294 descriptor->full_name() + ")";
299 std::string ExtraBuilderInterfaces(const Descriptor* descriptor) {
300 std::string interfaces = "// @@protoc_insertion_point(builder_implements:" +
301 descriptor->full_name() + ")";
305 std::string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) {
306 std::string interfaces = "// @@protoc_insertion_point(interface_extends:" +
307 descriptor->full_name() + ")";
311 std::string FieldConstantName(const FieldDescriptor* field) {
312 std::string name = field->name() + "_FIELD_NUMBER";
317 FieldDescriptor::Type GetType(const FieldDescriptor* field) {
318 return field->type();
321 JavaType GetJavaType(const FieldDescriptor* field) {
322 switch (GetType(field)) {
323 case FieldDescriptor::TYPE_INT32:
324 case FieldDescriptor::TYPE_UINT32:
325 case FieldDescriptor::TYPE_SINT32:
326 case FieldDescriptor::TYPE_FIXED32:
327 case FieldDescriptor::TYPE_SFIXED32:
330 case FieldDescriptor::TYPE_INT64:
331 case FieldDescriptor::TYPE_UINT64:
332 case FieldDescriptor::TYPE_SINT64:
333 case FieldDescriptor::TYPE_FIXED64:
334 case FieldDescriptor::TYPE_SFIXED64:
335 return JAVATYPE_LONG;
337 case FieldDescriptor::TYPE_FLOAT:
338 return JAVATYPE_FLOAT;
340 case FieldDescriptor::TYPE_DOUBLE:
341 return JAVATYPE_DOUBLE;
343 case FieldDescriptor::TYPE_BOOL:
344 return JAVATYPE_BOOLEAN;
346 case FieldDescriptor::TYPE_STRING:
347 return JAVATYPE_STRING;
349 case FieldDescriptor::TYPE_BYTES:
350 return JAVATYPE_BYTES;
352 case FieldDescriptor::TYPE_ENUM:
353 return JAVATYPE_ENUM;
355 case FieldDescriptor::TYPE_GROUP:
356 case FieldDescriptor::TYPE_MESSAGE:
357 return JAVATYPE_MESSAGE;
359 // No default because we want the compiler to complain if any new
363 GOOGLE_LOG(FATAL) << "Can't get here.";
367 const char* PrimitiveTypeName(JavaType type) {
375 case JAVATYPE_DOUBLE:
377 case JAVATYPE_BOOLEAN:
379 case JAVATYPE_STRING:
380 return "java.lang.String";
382 return "com.google.protobuf.ByteString";
385 case JAVATYPE_MESSAGE:
388 // No default because we want the compiler to complain if any new
389 // JavaTypes are added.
392 GOOGLE_LOG(FATAL) << "Can't get here.";
396 const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
397 return PrimitiveTypeName(GetJavaType(descriptor));
400 const char* BoxedPrimitiveTypeName(JavaType type) {
403 return "java.lang.Integer";
405 return "java.lang.Long";
407 return "java.lang.Float";
408 case JAVATYPE_DOUBLE:
409 return "java.lang.Double";
410 case JAVATYPE_BOOLEAN:
411 return "java.lang.Boolean";
412 case JAVATYPE_STRING:
413 return "java.lang.String";
415 return "com.google.protobuf.ByteString";
418 case JAVATYPE_MESSAGE:
421 // No default because we want the compiler to complain if any new
422 // JavaTypes are added.
425 GOOGLE_LOG(FATAL) << "Can't get here.";
429 const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor) {
430 return BoxedPrimitiveTypeName(GetJavaType(descriptor));
433 std::string GetOneofStoredType(const FieldDescriptor* field) {
434 const JavaType javaType = GetJavaType(field);
437 return "java.lang.Integer";
438 case JAVATYPE_MESSAGE:
439 return ClassName(field->message_type());
441 return BoxedPrimitiveTypeName(javaType);
445 const char* FieldTypeName(FieldDescriptor::Type field_type) {
446 switch (field_type) {
447 case FieldDescriptor::TYPE_INT32:
449 case FieldDescriptor::TYPE_UINT32:
451 case FieldDescriptor::TYPE_SINT32:
453 case FieldDescriptor::TYPE_FIXED32:
455 case FieldDescriptor::TYPE_SFIXED32:
457 case FieldDescriptor::TYPE_INT64:
459 case FieldDescriptor::TYPE_UINT64:
461 case FieldDescriptor::TYPE_SINT64:
463 case FieldDescriptor::TYPE_FIXED64:
465 case FieldDescriptor::TYPE_SFIXED64:
467 case FieldDescriptor::TYPE_FLOAT:
469 case FieldDescriptor::TYPE_DOUBLE:
471 case FieldDescriptor::TYPE_BOOL:
473 case FieldDescriptor::TYPE_STRING:
475 case FieldDescriptor::TYPE_BYTES:
477 case FieldDescriptor::TYPE_ENUM:
479 case FieldDescriptor::TYPE_GROUP:
481 case FieldDescriptor::TYPE_MESSAGE:
484 // No default because we want the compiler to complain if any new
488 GOOGLE_LOG(FATAL) << "Can't get here.";
492 bool AllAscii(const std::string& text) {
493 for (int i = 0; i < text.size(); i++) {
494 if ((text[i] & 0x80) != 0) {
501 std::string DefaultValue(const FieldDescriptor* field, bool immutable,
502 ClassNameResolver* name_resolver) {
503 // Switch on CppType since we need to know which default_value_* method
504 // of FieldDescriptor to call.
505 switch (field->cpp_type()) {
506 case FieldDescriptor::CPPTYPE_INT32:
507 return StrCat(field->default_value_int32());
508 case FieldDescriptor::CPPTYPE_UINT32:
509 // Need to print as a signed int since Java has no unsigned.
510 return StrCat(static_cast<int32>(field->default_value_uint32()));
511 case FieldDescriptor::CPPTYPE_INT64:
512 return StrCat(field->default_value_int64()) + "L";
513 case FieldDescriptor::CPPTYPE_UINT64:
514 return StrCat(static_cast<int64>(field->default_value_uint64())) +
516 case FieldDescriptor::CPPTYPE_DOUBLE: {
517 double value = field->default_value_double();
518 if (value == std::numeric_limits<double>::infinity()) {
519 return "Double.POSITIVE_INFINITY";
520 } else if (value == -std::numeric_limits<double>::infinity()) {
521 return "Double.NEGATIVE_INFINITY";
522 } else if (value != value) {
525 return SimpleDtoa(value) + "D";
528 case FieldDescriptor::CPPTYPE_FLOAT: {
529 float value = field->default_value_float();
530 if (value == std::numeric_limits<float>::infinity()) {
531 return "Float.POSITIVE_INFINITY";
532 } else if (value == -std::numeric_limits<float>::infinity()) {
533 return "Float.NEGATIVE_INFINITY";
534 } else if (value != value) {
537 return SimpleFtoa(value) + "F";
540 case FieldDescriptor::CPPTYPE_BOOL:
541 return field->default_value_bool() ? "true" : "false";
542 case FieldDescriptor::CPPTYPE_STRING:
543 if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
544 if (field->has_default_value()) {
545 // See comments in Internal.java for gory details.
546 return strings::Substitute(
547 "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
548 CEscape(field->default_value_string()));
550 return "com.google.protobuf.ByteString.EMPTY";
553 if (AllAscii(field->default_value_string())) {
554 // All chars are ASCII. In this case CEscape() works fine.
555 return "\"" + CEscape(field->default_value_string()) + "\"";
557 // See comments in Internal.java for gory details.
558 return strings::Substitute(
559 "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
560 CEscape(field->default_value_string()));
564 case FieldDescriptor::CPPTYPE_ENUM:
565 return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
566 field->default_value_enum()->name();
568 case FieldDescriptor::CPPTYPE_MESSAGE:
569 return name_resolver->GetClassName(field->message_type(), immutable) +
570 ".getDefaultInstance()";
572 // No default because we want the compiler to complain if any new
576 GOOGLE_LOG(FATAL) << "Can't get here.";
580 bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
581 // Switch on CppType since we need to know which default_value_* method
582 // of FieldDescriptor to call.
583 switch (field->cpp_type()) {
584 case FieldDescriptor::CPPTYPE_INT32:
585 return field->default_value_int32() == 0;
586 case FieldDescriptor::CPPTYPE_UINT32:
587 return field->default_value_uint32() == 0;
588 case FieldDescriptor::CPPTYPE_INT64:
589 return field->default_value_int64() == 0L;
590 case FieldDescriptor::CPPTYPE_UINT64:
591 return field->default_value_uint64() == 0L;
592 case FieldDescriptor::CPPTYPE_DOUBLE:
593 return field->default_value_double() == 0.0;
594 case FieldDescriptor::CPPTYPE_FLOAT:
595 return field->default_value_float() == 0.0;
596 case FieldDescriptor::CPPTYPE_BOOL:
597 return field->default_value_bool() == false;
598 case FieldDescriptor::CPPTYPE_ENUM:
599 return field->default_value_enum()->number() == 0;
600 case FieldDescriptor::CPPTYPE_STRING:
601 case FieldDescriptor::CPPTYPE_MESSAGE:
604 // No default because we want the compiler to complain if any new
608 GOOGLE_LOG(FATAL) << "Can't get here.";
612 bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field) {
613 return GetJavaType(field) == JAVATYPE_BYTES &&
614 field->default_value_string() != "";
617 const char* bit_masks[] = {
618 "0x00000001", "0x00000002", "0x00000004", "0x00000008",
619 "0x00000010", "0x00000020", "0x00000040", "0x00000080",
621 "0x00000100", "0x00000200", "0x00000400", "0x00000800",
622 "0x00001000", "0x00002000", "0x00004000", "0x00008000",
624 "0x00010000", "0x00020000", "0x00040000", "0x00080000",
625 "0x00100000", "0x00200000", "0x00400000", "0x00800000",
627 "0x01000000", "0x02000000", "0x04000000", "0x08000000",
628 "0x10000000", "0x20000000", "0x40000000", "0x80000000",
631 std::string GetBitFieldName(int index) {
632 std::string varName = "bitField";
633 varName += StrCat(index);
638 std::string GetBitFieldNameForBit(int bitIndex) {
639 return GetBitFieldName(bitIndex / 32);
644 std::string GenerateGetBitInternal(const std::string& prefix, int bitIndex) {
645 std::string varName = prefix + GetBitFieldNameForBit(bitIndex);
646 int bitInVarIndex = bitIndex % 32;
648 std::string mask = bit_masks[bitInVarIndex];
649 std::string result = "((" + varName + " & " + mask + ") != 0)";
653 std::string GenerateSetBitInternal(const std::string& prefix, int bitIndex) {
654 std::string varName = prefix + GetBitFieldNameForBit(bitIndex);
655 int bitInVarIndex = bitIndex % 32;
657 std::string mask = bit_masks[bitInVarIndex];
658 std::string result = varName + " |= " + mask;
664 std::string GenerateGetBit(int bitIndex) {
665 return GenerateGetBitInternal("", bitIndex);
668 std::string GenerateSetBit(int bitIndex) {
669 return GenerateSetBitInternal("", bitIndex);
672 std::string GenerateClearBit(int bitIndex) {
673 std::string varName = GetBitFieldNameForBit(bitIndex);
674 int bitInVarIndex = bitIndex % 32;
676 std::string mask = bit_masks[bitInVarIndex];
677 std::string result = varName + " = (" + varName + " & ~" + mask + ")";
681 std::string GenerateGetBitFromLocal(int bitIndex) {
682 return GenerateGetBitInternal("from_", bitIndex);
685 std::string GenerateSetBitToLocal(int bitIndex) {
686 return GenerateSetBitInternal("to_", bitIndex);
689 std::string GenerateGetBitMutableLocal(int bitIndex) {
690 return GenerateGetBitInternal("mutable_", bitIndex);
693 std::string GenerateSetBitMutableLocal(int bitIndex) {
694 return GenerateSetBitInternal("mutable_", bitIndex);
697 bool IsReferenceType(JavaType type) {
705 case JAVATYPE_DOUBLE:
707 case JAVATYPE_BOOLEAN:
709 case JAVATYPE_STRING:
715 case JAVATYPE_MESSAGE:
718 // No default because we want the compiler to complain if any new
719 // JavaTypes are added.
722 GOOGLE_LOG(FATAL) << "Can't get here.";
726 const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
727 switch (GetType(field)) {
728 case FieldDescriptor::TYPE_INT32:
730 case FieldDescriptor::TYPE_UINT32:
732 case FieldDescriptor::TYPE_SINT32:
734 case FieldDescriptor::TYPE_FIXED32:
736 case FieldDescriptor::TYPE_SFIXED32:
738 case FieldDescriptor::TYPE_INT64:
740 case FieldDescriptor::TYPE_UINT64:
742 case FieldDescriptor::TYPE_SINT64:
744 case FieldDescriptor::TYPE_FIXED64:
746 case FieldDescriptor::TYPE_SFIXED64:
748 case FieldDescriptor::TYPE_FLOAT:
750 case FieldDescriptor::TYPE_DOUBLE:
752 case FieldDescriptor::TYPE_BOOL:
754 case FieldDescriptor::TYPE_STRING:
756 case FieldDescriptor::TYPE_BYTES: {
759 case FieldDescriptor::TYPE_ENUM:
761 case FieldDescriptor::TYPE_GROUP:
763 case FieldDescriptor::TYPE_MESSAGE:
766 // No default because we want the compiler to complain if any new
770 GOOGLE_LOG(FATAL) << "Can't get here.";
774 // For encodings with fixed sizes, returns that size in bytes. Otherwise
776 int FixedSize(FieldDescriptor::Type type) {
778 case FieldDescriptor::TYPE_INT32:
780 case FieldDescriptor::TYPE_INT64:
782 case FieldDescriptor::TYPE_UINT32:
784 case FieldDescriptor::TYPE_UINT64:
786 case FieldDescriptor::TYPE_SINT32:
788 case FieldDescriptor::TYPE_SINT64:
790 case FieldDescriptor::TYPE_FIXED32:
791 return WireFormatLite::kFixed32Size;
792 case FieldDescriptor::TYPE_FIXED64:
793 return WireFormatLite::kFixed64Size;
794 case FieldDescriptor::TYPE_SFIXED32:
795 return WireFormatLite::kSFixed32Size;
796 case FieldDescriptor::TYPE_SFIXED64:
797 return WireFormatLite::kSFixed64Size;
798 case FieldDescriptor::TYPE_FLOAT:
799 return WireFormatLite::kFloatSize;
800 case FieldDescriptor::TYPE_DOUBLE:
801 return WireFormatLite::kDoubleSize;
803 case FieldDescriptor::TYPE_BOOL:
804 return WireFormatLite::kBoolSize;
805 case FieldDescriptor::TYPE_ENUM:
808 case FieldDescriptor::TYPE_STRING:
810 case FieldDescriptor::TYPE_BYTES:
812 case FieldDescriptor::TYPE_GROUP:
814 case FieldDescriptor::TYPE_MESSAGE:
817 // No default because we want the compiler to complain if any new
820 GOOGLE_LOG(FATAL) << "Can't get here.";
824 // Sort the fields of the given Descriptor by number into a new[]'d array
825 // and return it. The caller should delete the returned array.
826 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
827 const FieldDescriptor** fields =
828 new const FieldDescriptor*[descriptor->field_count()];
829 for (int i = 0; i < descriptor->field_count(); i++) {
830 fields[i] = descriptor->field(i);
832 std::sort(fields, fields + descriptor->field_count(),
833 FieldOrderingByNumber());
837 // Returns true if the message type has any required fields. If it doesn't,
838 // we can optimize out calls to its isInitialized() method.
840 // already_seen is used to avoid checking the same type multiple times
841 // (and also to protect against recursion).
842 bool HasRequiredFields(const Descriptor* type,
843 std::unordered_set<const Descriptor*>* already_seen) {
844 if (already_seen->count(type) > 0) {
845 // The type is already in cache. This means that either:
846 // a. The type has no required fields.
847 // b. We are in the midst of checking if the type has required fields,
848 // somewhere up the stack. In this case, we know that if the type
849 // has any required fields, they'll be found when we return to it,
850 // and the whole call to HasRequiredFields() will return true.
851 // Therefore, we don't have to check if this type has required fields
855 already_seen->insert(type);
857 // If the type has extensions, an extension with message type could contain
858 // required fields, so we have to be conservative and assume such an
860 if (type->extension_range_count() > 0) return true;
862 for (int i = 0; i < type->field_count(); i++) {
863 const FieldDescriptor* field = type->field(i);
864 if (field->is_required()) {
867 if (GetJavaType(field) == JAVATYPE_MESSAGE) {
868 if (HasRequiredFields(field->message_type(), already_seen)) {
877 bool HasRequiredFields(const Descriptor* type) {
878 std::unordered_set<const Descriptor*> already_seen;
879 return HasRequiredFields(type, &already_seen);
882 bool HasRepeatedFields(const Descriptor* descriptor) {
883 for (int i = 0; i < descriptor->field_count(); ++i) {
884 const FieldDescriptor* field = descriptor->field(i);
885 if (field->is_repeated()) {
892 // Encode an unsigned 32-bit value into a sequence of UTF-16 characters.
894 // If the value is in [0x0000, 0xD7FF], we encode it with a single character
895 // with the same numeric value.
897 // If the value is larger than 0xD7FF, we encode its lowest 13 bits into a
898 // character in the range [0xE000, 0xFFFF] by combining these 13 bits with
899 // 0xE000 using logic-or. Then we shift the value to the right by 13 bits, and
900 // encode the remaining value by repeating this same process until we get to
901 // a value in [0x0000, 0xD7FF] where we will encode it using a character with
902 // the same numeric value.
904 // Note that we only use code points in [0x0000, 0xD7FF] and [0xE000, 0xFFFF].
905 // There will be no surrogate pairs in the encoded character sequence.
906 void WriteUInt32ToUtf16CharSequence(uint32 number,
907 std::vector<uint16>* output) {
908 // For values in [0x0000, 0xD7FF], only use one char to encode it.
909 if (number < 0xD800) {
910 output->push_back(static_cast<uint16>(number));
913 // Encode into multiple chars. All except the last char will be in the range
914 // [0xE000, 0xFFFF], and the last char will be in the range [0x0000, 0xD7FF].
915 // Note that we don't use any value in range [0xD800, 0xDFFF] because they
916 // have to come in pairs and the encoding is just more space-efficient w/o
918 while (number >= 0xD800) {
919 // [0xE000, 0xFFFF] can represent 13 bits of info.
920 output->push_back(static_cast<uint16>(0xE000 | (number & 0x1FFF)));
923 output->push_back(static_cast<uint16>(number));
926 int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) {
927 // j/c/g/protobuf/FieldType.java lists field types in a slightly different
928 // order from FieldDescriptor::Type so we can't do a simple cast.
930 // TODO(xiaofeng): Make j/c/g/protobuf/FieldType.java follow the same order.
931 int result = field->type();
932 if (result == FieldDescriptor::TYPE_GROUP) {
934 } else if (result < FieldDescriptor::TYPE_GROUP) {
941 int GetExperimentalJavaFieldTypeForRepeated(const FieldDescriptor* field) {
942 if (field->type() == FieldDescriptor::TYPE_GROUP) {
945 return GetExperimentalJavaFieldTypeForSingular(field) + 18;
949 int GetExperimentalJavaFieldTypeForPacked(const FieldDescriptor* field) {
950 int result = field->type();
951 if (result < FieldDescriptor::TYPE_STRING) {
953 } else if (result > FieldDescriptor::TYPE_BYTES) {
956 GOOGLE_LOG(FATAL) << field->full_name() << " can't be packed.";
961 int GetExperimentalJavaFieldType(const FieldDescriptor* field) {
962 static const int kMapFieldType = 50;
963 static const int kOneofFieldTypeOffset = 51;
964 static const int kRequiredBit = 0x100;
965 static const int kUtf8CheckBit = 0x200;
966 static const int kCheckInitialized = 0x400;
967 static const int kMapWithProto2EnumValue = 0x800;
968 int extra_bits = field->is_required() ? kRequiredBit : 0;
969 if (field->type() == FieldDescriptor::TYPE_STRING && CheckUtf8(field)) {
970 extra_bits |= kUtf8CheckBit;
972 if (field->is_required() || (GetJavaType(field) == JAVATYPE_MESSAGE &&
973 HasRequiredFields(field->message_type()))) {
974 extra_bits |= kCheckInitialized;
977 if (field->is_map()) {
978 if (SupportFieldPresence(field->file())) {
979 const FieldDescriptor* value =
980 field->message_type()->FindFieldByName("value");
981 if (GetJavaType(value) == JAVATYPE_ENUM) {
982 extra_bits |= kMapWithProto2EnumValue;
985 return kMapFieldType | extra_bits;
986 } else if (field->is_packed()) {
987 return GetExperimentalJavaFieldTypeForPacked(field);
988 } else if (field->is_repeated()) {
989 return GetExperimentalJavaFieldTypeForRepeated(field) | extra_bits;
990 } else if (field->containing_oneof() != NULL) {
991 return (GetExperimentalJavaFieldTypeForSingular(field) +
992 kOneofFieldTypeOffset) |
995 return GetExperimentalJavaFieldTypeForSingular(field) | extra_bits;
999 // Escape a UTF-16 character to be embedded in a Java string.
1000 void EscapeUtf16ToString(uint16 code, std::string* output) {
1002 output->append("\\t");
1003 } else if (code == '\b') {
1004 output->append("\\b");
1005 } else if (code == '\n') {
1006 output->append("\\n");
1007 } else if (code == '\r') {
1008 output->append("\\r");
1009 } else if (code == '\f') {
1010 output->append("\\f");
1011 } else if (code == '\'') {
1012 output->append("\\'");
1013 } else if (code == '\"') {
1014 output->append("\\\"");
1015 } else if (code == '\\') {
1016 output->append("\\\\");
1017 } else if (code >= 0x20 && code <= 0x7f) {
1018 output->push_back(static_cast<char>(code));
1020 output->append(StringPrintf("\\u%04x", code));
1025 } // namespace compiler
1026 } // namespace protobuf
1027 } // namespace google