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 (at) 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 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 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 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 139 string UnderscoresToCamelCase(const FieldDescriptor* field) { 140 return UnderscoresToCamelCase(FieldName(field), false); 141 } 142 143 string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { 144 return UnderscoresToCamelCase(FieldName(field), true); 145 } 146 147 string UnderscoresToCamelCase(const MethodDescriptor* method) { 148 return UnderscoresToCamelCase(method->name(), false); 149 } 150 151 string UniqueFileScopeIdentifier(const Descriptor* descriptor) { 152 return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); 153 } 154 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 163 string FileClassName(const FileDescriptor* file, bool immutable) { 164 ClassNameResolver name_resolver; 165 return name_resolver.GetFileClassName(file, immutable); 166 } 167 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 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. 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 214 string ClassName(const Descriptor* descriptor) { 215 ClassNameResolver name_resolver; 216 return name_resolver.GetClassName(descriptor, true); 217 } 218 219 string ClassName(const EnumDescriptor* descriptor) { 220 ClassNameResolver name_resolver; 221 return name_resolver.GetClassName(descriptor, true); 222 } 223 224 string ClassName(const ServiceDescriptor* descriptor) { 225 ClassNameResolver name_resolver; 226 return name_resolver.GetClassName(descriptor, true); 227 } 228 229 string ClassName(const FileDescriptor* descriptor) { 230 ClassNameResolver name_resolver; 231 return name_resolver.GetClassName(descriptor, true); 232 } 233 234 string ExtraMessageInterfaces(const Descriptor* descriptor) { 235 string interfaces = "// @@protoc_insertion_point(message_implements:" 236 + descriptor->full_name() + ")"; 237 return interfaces; 238 } 239 240 241 string ExtraBuilderInterfaces(const Descriptor* descriptor) { 242 string interfaces = "// @@protoc_insertion_point(builder_implements:" 243 + descriptor->full_name() + ")"; 244 return interfaces; 245 } 246 247 string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) { 248 string interfaces = "// @@protoc_insertion_point(interface_extends:" 249 + descriptor->full_name() + ")"; 250 return interfaces; 251 } 252 253 string FieldConstantName(const FieldDescriptor *field) { 254 string name = field->name() + "_FIELD_NUMBER"; 255 UpperString(&name); 256 return name; 257 } 258 259 FieldDescriptor::Type GetType(const FieldDescriptor* field) { 260 return field->type(); 261 } 262 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 309 const 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 329 const 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 358 bool 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 367 string 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 446 bool 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 478 const 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 516 string GetBitFieldName(int index) { 517 string varName = "bitField"; 518 varName += SimpleItoa(index); 519 varName += "_"; 520 return varName; 521 } 522 523 string GetBitFieldNameForBit(int bitIndex) { 524 return GetBitFieldName(bitIndex / 32); 525 } 526 527 namespace { 528 529 string 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 538 string 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 549 string GenerateGetBit(int bitIndex) { 550 return GenerateGetBitInternal("", bitIndex); 551 } 552 553 string GenerateSetBit(int bitIndex) { 554 return GenerateSetBitInternal("", bitIndex); 555 } 556 557 string 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 566 string GenerateGetBitFromLocal(int bitIndex) { 567 return GenerateGetBitInternal("from_", bitIndex); 568 } 569 570 string GenerateSetBitToLocal(int bitIndex) { 571 return GenerateSetBitInternal("to_", bitIndex); 572 } 573 574 string GenerateGetBitMutableLocal(int bitIndex) { 575 return GenerateGetBitInternal("mutable_", bitIndex); 576 } 577 578 string GenerateSetBitMutableLocal(int bitIndex) { 579 return GenerateSetBitInternal("mutable_", bitIndex); 580 } 581 582 bool 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 602 const 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. 635 int 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. 667 const 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). 683 bool 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 719 bool HasRequiredFields(const Descriptor* type) { 720 hash_set<const Descriptor*> already_seen; 721 return HasRequiredFields(type, &already_seen); 722 } 723 724 bool 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