| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954 |
- // Protocol Buffers - Google's data interchange format
- // Copyright 2008 Google Inc. All rights reserved.
- // https://developers.google.com/protocol-buffers/
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Google Inc. nor the names of its
- // contributors may be used to endorse or promote products derived from
- // this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- // Author: kenton@google.com (Kenton Varda)
- // Based on original Protocol Buffers design by
- // Sanjay Ghemawat, Jeff Dean, and others.
- #include <algorithm>
- #include <google/protobuf/stubs/hash.h>
- #include <limits>
- #include <vector>
- #include <google/protobuf/stubs/stringprintf.h>
- #include <google/protobuf/compiler/java/java_helpers.h>
- #include <google/protobuf/compiler/java/java_name_resolver.h>
- #include <google/protobuf/descriptor.pb.h>
- #include <google/protobuf/wire_format.h>
- #include <google/protobuf/stubs/strutil.h>
- #include <google/protobuf/stubs/substitute.h>
- #include <google/protobuf/stubs/hash.h> // for hash<T *>
- namespace google {
- namespace protobuf {
- namespace compiler {
- namespace java {
- using internal::WireFormat;
- using internal::WireFormatLite;
- const char kThickSeparator[] =
- "// ===================================================================\n";
- const char kThinSeparator[] =
- "// -------------------------------------------------------------------\n";
- namespace {
- const char* kDefaultPackage = "";
- // Names that should be avoided as field names.
- // Using them will cause the compiler to generate accessors whose names are
- // colliding with methods defined in base classes.
- const char* kForbiddenWordList[] = {
- // message base class:
- "cached_size", "serialized_size",
- // java.lang.Object:
- "class",
- };
- const int kDefaultLookUpStartFieldNumber = 40;
- bool IsForbidden(const string& field_name) {
- for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
- if (field_name == kForbiddenWordList[i]) {
- return true;
- }
- }
- return false;
- }
- string FieldName(const FieldDescriptor* field) {
- string field_name;
- // Groups are hacky: The name of the field is just the lower-cased name
- // of the group type. In Java, though, we would like to retain the original
- // capitalization of the type name.
- if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
- field_name = field->message_type()->name();
- } else {
- field_name = field->name();
- }
- if (IsForbidden(field_name)) {
- // Append a trailing "#" to indicate that the name should be decorated to
- // avoid collision with other names.
- field_name += "#";
- }
- return field_name;
- }
- // Judge whether should use table or use look up.
- // Copied from com.google.protobuf.SchemaUtil.shouldUseTableSwitch
- bool ShouldUseTable(int lo, int hi, int number_of_fields) {
- if (hi < kDefaultLookUpStartFieldNumber) {
- return true;
- }
- int64 table_space_cost = (static_cast<int64>(hi) - lo + 1); // words
- int64 table_time_cost = 3; // comparisons
- int64 lookup_space_cost = 3 + 2 * static_cast<int64>(number_of_fields);
- int64 lookup_time_cost = 3 + number_of_fields;
- return table_space_cost + 3 * table_time_cost <=
- lookup_space_cost + 3 * lookup_time_cost;
- }
- } // namespace
- void PrintGeneratedAnnotation(io::Printer* printer, char delimiter,
- const string& annotation_file) {
- if (annotation_file.empty()) {
- return;
- }
- string ptemplate =
- "@javax.annotation.Generated(value=\"protoc\", comments=\"annotations:";
- ptemplate.push_back(delimiter);
- ptemplate.append("annotation_file");
- ptemplate.push_back(delimiter);
- ptemplate.append("\")\n");
- printer->Print(ptemplate.c_str(), "annotation_file", annotation_file);
- }
- string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
- string result;
- // Note: I distrust ctype.h due to locales.
- for (int i = 0; i < input.size(); i++) {
- if ('a' <= input[i] && input[i] <= 'z') {
- if (cap_next_letter) {
- result += input[i] + ('A' - 'a');
- } else {
- result += input[i];
- }
- cap_next_letter = false;
- } else if ('A' <= input[i] && input[i] <= 'Z') {
- if (i == 0 && !cap_next_letter) {
- // Force first letter to lower-case unless explicitly told to
- // capitalize it.
- result += input[i] + ('a' - 'A');
- } else {
- // Capital letters after the first are left as-is.
- result += input[i];
- }
- cap_next_letter = false;
- } else if ('0' <= input[i] && input[i] <= '9') {
- result += input[i];
- cap_next_letter = true;
- } else {
- cap_next_letter = true;
- }
- }
- // Add a trailing "_" if the name should be altered.
- if (input[input.size() - 1] == '#') {
- result += '_';
- }
- return result;
- }
- string UnderscoresToCamelCase(const FieldDescriptor* field) {
- return UnderscoresToCamelCase(FieldName(field), false);
- }
- string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
- return UnderscoresToCamelCase(FieldName(field), true);
- }
- string UnderscoresToCamelCase(const MethodDescriptor* method) {
- return UnderscoresToCamelCase(method->name(), false);
- }
- string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
- return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
- }
- string CamelCaseFieldName(const FieldDescriptor* field) {
- string fieldName = UnderscoresToCamelCase(field);
- if ('0' <= fieldName[0] && fieldName[0] <= '9') {
- return '_' + fieldName;
- }
- return fieldName;
- }
- string StripProto(const string& filename) {
- if (HasSuffixString(filename, ".protodevel")) {
- return StripSuffixString(filename, ".protodevel");
- } else {
- return StripSuffixString(filename, ".proto");
- }
- }
- string FileClassName(const FileDescriptor* file, bool immutable) {
- ClassNameResolver name_resolver;
- return name_resolver.GetFileClassName(file, immutable);
- }
- string FileJavaPackage(const FileDescriptor* file, bool immutable) {
- string result;
- if (file->options().has_java_package()) {
- result = file->options().java_package();
- } else {
- result = kDefaultPackage;
- if (!file->package().empty()) {
- if (!result.empty()) result += '.';
- result += file->package();
- }
- }
- return result;
- }
- string JavaPackageToDir(string package_name) {
- string package_dir =
- StringReplace(package_name, ".", "/", true);
- if (!package_dir.empty()) package_dir += "/";
- return package_dir;
- }
- // TODO(xiaofeng): This function is only kept for it's publicly referenced.
- // It should be removed after mutable API up-integration.
- string ToJavaName(const string& full_name,
- const FileDescriptor* file) {
- string result;
- if (file->options().java_multiple_files()) {
- result = FileJavaPackage(file);
- } else {
- result = ClassName(file);
- }
- if (!result.empty()) {
- result += '.';
- }
- if (file->package().empty()) {
- result += full_name;
- } else {
- // Strip the proto package from full_name since we've replaced it with
- // the Java package.
- result += full_name.substr(file->package().size() + 1);
- }
- return result;
- }
- string ClassName(const Descriptor* descriptor) {
- ClassNameResolver name_resolver;
- return name_resolver.GetClassName(descriptor, true);
- }
- string ClassName(const EnumDescriptor* descriptor) {
- ClassNameResolver name_resolver;
- return name_resolver.GetClassName(descriptor, true);
- }
- string ClassName(const ServiceDescriptor* descriptor) {
- ClassNameResolver name_resolver;
- return name_resolver.GetClassName(descriptor, true);
- }
- string ClassName(const FileDescriptor* descriptor) {
- ClassNameResolver name_resolver;
- return name_resolver.GetClassName(descriptor, true);
- }
- string ExtraMessageInterfaces(const Descriptor* descriptor) {
- string interfaces = "// @@protoc_insertion_point(message_implements:"
- + descriptor->full_name() + ")";
- return interfaces;
- }
- string ExtraBuilderInterfaces(const Descriptor* descriptor) {
- string interfaces = "// @@protoc_insertion_point(builder_implements:"
- + descriptor->full_name() + ")";
- return interfaces;
- }
- string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) {
- string interfaces = "// @@protoc_insertion_point(interface_extends:"
- + descriptor->full_name() + ")";
- return interfaces;
- }
- string FieldConstantName(const FieldDescriptor *field) {
- string name = field->name() + "_FIELD_NUMBER";
- UpperString(&name);
- return name;
- }
- FieldDescriptor::Type GetType(const FieldDescriptor* field) {
- return field->type();
- }
- JavaType GetJavaType(const FieldDescriptor* field) {
- switch (GetType(field)) {
- case FieldDescriptor::TYPE_INT32:
- case FieldDescriptor::TYPE_UINT32:
- case FieldDescriptor::TYPE_SINT32:
- case FieldDescriptor::TYPE_FIXED32:
- case FieldDescriptor::TYPE_SFIXED32:
- return JAVATYPE_INT;
- case FieldDescriptor::TYPE_INT64:
- case FieldDescriptor::TYPE_UINT64:
- case FieldDescriptor::TYPE_SINT64:
- case FieldDescriptor::TYPE_FIXED64:
- case FieldDescriptor::TYPE_SFIXED64:
- return JAVATYPE_LONG;
- case FieldDescriptor::TYPE_FLOAT:
- return JAVATYPE_FLOAT;
- case FieldDescriptor::TYPE_DOUBLE:
- return JAVATYPE_DOUBLE;
- case FieldDescriptor::TYPE_BOOL:
- return JAVATYPE_BOOLEAN;
- case FieldDescriptor::TYPE_STRING:
- return JAVATYPE_STRING;
- case FieldDescriptor::TYPE_BYTES:
- return JAVATYPE_BYTES;
- case FieldDescriptor::TYPE_ENUM:
- return JAVATYPE_ENUM;
- case FieldDescriptor::TYPE_GROUP:
- case FieldDescriptor::TYPE_MESSAGE:
- return JAVATYPE_MESSAGE;
- // No default because we want the compiler to complain if any new
- // types are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return JAVATYPE_INT;
- }
- const char* PrimitiveTypeName(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return "int";
- case JAVATYPE_LONG : return "long";
- case JAVATYPE_FLOAT : return "float";
- case JAVATYPE_DOUBLE : return "double";
- case JAVATYPE_BOOLEAN: return "boolean";
- case JAVATYPE_STRING : return "java.lang.String";
- case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
- case JAVATYPE_ENUM : return NULL;
- case JAVATYPE_MESSAGE: return NULL;
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return NULL;
- }
- const char* BoxedPrimitiveTypeName(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return "java.lang.Integer";
- case JAVATYPE_LONG : return "java.lang.Long";
- case JAVATYPE_FLOAT : return "java.lang.Float";
- case JAVATYPE_DOUBLE : return "java.lang.Double";
- case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
- case JAVATYPE_STRING : return "java.lang.String";
- case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
- case JAVATYPE_ENUM : return NULL;
- case JAVATYPE_MESSAGE: return NULL;
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return NULL;
- }
- const char* FieldTypeName(FieldDescriptor::Type field_type) {
- switch (field_type) {
- case FieldDescriptor::TYPE_INT32 : return "INT32";
- case FieldDescriptor::TYPE_UINT32 : return "UINT32";
- case FieldDescriptor::TYPE_SINT32 : return "SINT32";
- case FieldDescriptor::TYPE_FIXED32 : return "FIXED32";
- case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32";
- case FieldDescriptor::TYPE_INT64 : return "INT64";
- case FieldDescriptor::TYPE_UINT64 : return "UINT64";
- case FieldDescriptor::TYPE_SINT64 : return "SINT64";
- case FieldDescriptor::TYPE_FIXED64 : return "FIXED64";
- case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64";
- case FieldDescriptor::TYPE_FLOAT : return "FLOAT";
- case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE";
- case FieldDescriptor::TYPE_BOOL : return "BOOL";
- case FieldDescriptor::TYPE_STRING : return "STRING";
- case FieldDescriptor::TYPE_BYTES : return "BYTES";
- case FieldDescriptor::TYPE_ENUM : return "ENUM";
- case FieldDescriptor::TYPE_GROUP : return "GROUP";
- case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
- // No default because we want the compiler to complain if any new
- // types are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return NULL;
- }
- bool AllAscii(const string& text) {
- for (int i = 0; i < text.size(); i++) {
- if ((text[i] & 0x80) != 0) {
- return false;
- }
- }
- return true;
- }
- string DefaultValue(const FieldDescriptor* field, bool immutable,
- ClassNameResolver* name_resolver) {
- // Switch on CppType since we need to know which default_value_* method
- // of FieldDescriptor to call.
- switch (field->cpp_type()) {
- case FieldDescriptor::CPPTYPE_INT32:
- return SimpleItoa(field->default_value_int32());
- case FieldDescriptor::CPPTYPE_UINT32:
- // Need to print as a signed int since Java has no unsigned.
- return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
- case FieldDescriptor::CPPTYPE_INT64:
- return SimpleItoa(field->default_value_int64()) + "L";
- case FieldDescriptor::CPPTYPE_UINT64:
- return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
- "L";
- case FieldDescriptor::CPPTYPE_DOUBLE: {
- double value = field->default_value_double();
- if (value == std::numeric_limits<double>::infinity()) {
- return "Double.POSITIVE_INFINITY";
- } else if (value == -std::numeric_limits<double>::infinity()) {
- return "Double.NEGATIVE_INFINITY";
- } else if (value != value) {
- return "Double.NaN";
- } else {
- return SimpleDtoa(value) + "D";
- }
- }
- case FieldDescriptor::CPPTYPE_FLOAT: {
- float value = field->default_value_float();
- if (value == std::numeric_limits<float>::infinity()) {
- return "Float.POSITIVE_INFINITY";
- } else if (value == -std::numeric_limits<float>::infinity()) {
- return "Float.NEGATIVE_INFINITY";
- } else if (value != value) {
- return "Float.NaN";
- } else {
- return SimpleFtoa(value) + "F";
- }
- }
- case FieldDescriptor::CPPTYPE_BOOL:
- return field->default_value_bool() ? "true" : "false";
- case FieldDescriptor::CPPTYPE_STRING:
- if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
- if (field->has_default_value()) {
- // See comments in Internal.java for gory details.
- return strings::Substitute(
- "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
- CEscape(field->default_value_string()));
- } else {
- return "com.google.protobuf.ByteString.EMPTY";
- }
- } else {
- if (AllAscii(field->default_value_string())) {
- // All chars are ASCII. In this case CEscape() works fine.
- return "\"" + CEscape(field->default_value_string()) + "\"";
- } else {
- // See comments in Internal.java for gory details.
- return strings::Substitute(
- "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
- CEscape(field->default_value_string()));
- }
- }
- case FieldDescriptor::CPPTYPE_ENUM:
- return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
- field->default_value_enum()->name();
- case FieldDescriptor::CPPTYPE_MESSAGE:
- return name_resolver->GetClassName(field->message_type(), immutable) +
- ".getDefaultInstance()";
- // No default because we want the compiler to complain if any new
- // types are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return "";
- }
- bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
- // Switch on CppType since we need to know which default_value_* method
- // of FieldDescriptor to call.
- switch (field->cpp_type()) {
- case FieldDescriptor::CPPTYPE_INT32:
- return field->default_value_int32() == 0;
- case FieldDescriptor::CPPTYPE_UINT32:
- return field->default_value_uint32() == 0;
- case FieldDescriptor::CPPTYPE_INT64:
- return field->default_value_int64() == 0L;
- case FieldDescriptor::CPPTYPE_UINT64:
- return field->default_value_uint64() == 0L;
- case FieldDescriptor::CPPTYPE_DOUBLE:
- return field->default_value_double() == 0.0;
- case FieldDescriptor::CPPTYPE_FLOAT:
- return field->default_value_float() == 0.0;
- case FieldDescriptor::CPPTYPE_BOOL:
- return field->default_value_bool() == false;
- case FieldDescriptor::CPPTYPE_ENUM:
- return field->default_value_enum()->number() == 0;
- case FieldDescriptor::CPPTYPE_STRING:
- case FieldDescriptor::CPPTYPE_MESSAGE:
- return false;
- // No default because we want the compiler to complain if any new
- // types are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return false;
- }
- bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field) {
- return GetJavaType(field) == JAVATYPE_BYTES &&
- field->default_value_string() != "";
- }
- const char* bit_masks[] = {
- "0x00000001",
- "0x00000002",
- "0x00000004",
- "0x00000008",
- "0x00000010",
- "0x00000020",
- "0x00000040",
- "0x00000080",
- "0x00000100",
- "0x00000200",
- "0x00000400",
- "0x00000800",
- "0x00001000",
- "0x00002000",
- "0x00004000",
- "0x00008000",
- "0x00010000",
- "0x00020000",
- "0x00040000",
- "0x00080000",
- "0x00100000",
- "0x00200000",
- "0x00400000",
- "0x00800000",
- "0x01000000",
- "0x02000000",
- "0x04000000",
- "0x08000000",
- "0x10000000",
- "0x20000000",
- "0x40000000",
- "0x80000000",
- };
- string GetBitFieldName(int index) {
- string varName = "bitField";
- varName += SimpleItoa(index);
- varName += "_";
- return varName;
- }
- string GetBitFieldNameForBit(int bitIndex) {
- return GetBitFieldName(bitIndex / 32);
- }
- namespace {
- string GenerateGetBitInternal(const string& prefix, int bitIndex) {
- string varName = prefix + GetBitFieldNameForBit(bitIndex);
- int bitInVarIndex = bitIndex % 32;
- string mask = bit_masks[bitInVarIndex];
- string result = "((" + varName + " & " + mask + ") == " + mask + ")";
- return result;
- }
- string GenerateSetBitInternal(const string& prefix, int bitIndex) {
- string varName = prefix + GetBitFieldNameForBit(bitIndex);
- int bitInVarIndex = bitIndex % 32;
- string mask = bit_masks[bitInVarIndex];
- string result = varName + " |= " + mask;
- return result;
- }
- } // namespace
- string GenerateGetBit(int bitIndex) {
- return GenerateGetBitInternal("", bitIndex);
- }
- string GenerateSetBit(int bitIndex) {
- return GenerateSetBitInternal("", bitIndex);
- }
- string GenerateClearBit(int bitIndex) {
- string varName = GetBitFieldNameForBit(bitIndex);
- int bitInVarIndex = bitIndex % 32;
- string mask = bit_masks[bitInVarIndex];
- string result = varName + " = (" + varName + " & ~" + mask + ")";
- return result;
- }
- string GenerateGetBitFromLocal(int bitIndex) {
- return GenerateGetBitInternal("from_", bitIndex);
- }
- string GenerateSetBitToLocal(int bitIndex) {
- return GenerateSetBitInternal("to_", bitIndex);
- }
- string GenerateGetBitMutableLocal(int bitIndex) {
- return GenerateGetBitInternal("mutable_", bitIndex);
- }
- string GenerateSetBitMutableLocal(int bitIndex) {
- return GenerateSetBitInternal("mutable_", bitIndex);
- }
- bool IsReferenceType(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return false;
- case JAVATYPE_LONG : return false;
- case JAVATYPE_FLOAT : return false;
- case JAVATYPE_DOUBLE : return false;
- case JAVATYPE_BOOLEAN: return false;
- case JAVATYPE_STRING : return true;
- case JAVATYPE_BYTES : return true;
- case JAVATYPE_ENUM : return true;
- case JAVATYPE_MESSAGE: return true;
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return false;
- }
- const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
- switch (GetType(field)) {
- case FieldDescriptor::TYPE_INT32 : return "Int32";
- case FieldDescriptor::TYPE_UINT32 : return "UInt32";
- case FieldDescriptor::TYPE_SINT32 : return "SInt32";
- case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
- case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
- case FieldDescriptor::TYPE_INT64 : return "Int64";
- case FieldDescriptor::TYPE_UINT64 : return "UInt64";
- case FieldDescriptor::TYPE_SINT64 : return "SInt64";
- case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
- case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
- case FieldDescriptor::TYPE_FLOAT : return "Float";
- case FieldDescriptor::TYPE_DOUBLE : return "Double";
- case FieldDescriptor::TYPE_BOOL : return "Bool";
- case FieldDescriptor::TYPE_STRING : return "String";
- case FieldDescriptor::TYPE_BYTES : {
- return "Bytes";
- }
- case FieldDescriptor::TYPE_ENUM : return "Enum";
- case FieldDescriptor::TYPE_GROUP : return "Group";
- case FieldDescriptor::TYPE_MESSAGE : return "Message";
- // No default because we want the compiler to complain if any new
- // types are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return NULL;
- }
- // For encodings with fixed sizes, returns that size in bytes. Otherwise
- // returns -1.
- int FixedSize(FieldDescriptor::Type type) {
- switch (type) {
- case FieldDescriptor::TYPE_INT32 : return -1;
- case FieldDescriptor::TYPE_INT64 : return -1;
- case FieldDescriptor::TYPE_UINT32 : return -1;
- case FieldDescriptor::TYPE_UINT64 : return -1;
- case FieldDescriptor::TYPE_SINT32 : return -1;
- case FieldDescriptor::TYPE_SINT64 : return -1;
- case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
- case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
- case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
- case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
- case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
- case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
- case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
- case FieldDescriptor::TYPE_ENUM : return -1;
- case FieldDescriptor::TYPE_STRING : return -1;
- case FieldDescriptor::TYPE_BYTES : return -1;
- case FieldDescriptor::TYPE_GROUP : return -1;
- case FieldDescriptor::TYPE_MESSAGE : return -1;
- // No default because we want the compiler to complain if any new
- // types are added.
- }
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return -1;
- }
- // Sort the fields of the given Descriptor by number into a new[]'d array
- // and return it. The caller should delete the returned array.
- const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
- const FieldDescriptor** fields =
- new const FieldDescriptor*[descriptor->field_count()];
- for (int i = 0; i < descriptor->field_count(); i++) {
- fields[i] = descriptor->field(i);
- }
- std::sort(fields, fields + descriptor->field_count(),
- FieldOrderingByNumber());
- return fields;
- }
- // Returns true if the message type has any required fields. If it doesn't,
- // we can optimize out calls to its isInitialized() method.
- //
- // already_seen is used to avoid checking the same type multiple times
- // (and also to protect against recursion).
- bool HasRequiredFields(
- const Descriptor* type,
- hash_set<const Descriptor*>* already_seen) {
- if (already_seen->count(type) > 0) {
- // The type is already in cache. This means that either:
- // a. The type has no required fields.
- // b. We are in the midst of checking if the type has required fields,
- // somewhere up the stack. In this case, we know that if the type
- // has any required fields, they'll be found when we return to it,
- // and the whole call to HasRequiredFields() will return true.
- // Therefore, we don't have to check if this type has required fields
- // here.
- return false;
- }
- already_seen->insert(type);
- // If the type has extensions, an extension with message type could contain
- // required fields, so we have to be conservative and assume such an
- // extension exists.
- if (type->extension_range_count() > 0) return true;
- for (int i = 0; i < type->field_count(); i++) {
- const FieldDescriptor* field = type->field(i);
- if (field->is_required()) {
- return true;
- }
- if (GetJavaType(field) == JAVATYPE_MESSAGE) {
- if (HasRequiredFields(field->message_type(), already_seen)) {
- return true;
- }
- }
- }
- return false;
- }
- bool HasRequiredFields(const Descriptor* type) {
- hash_set<const Descriptor*> already_seen;
- return HasRequiredFields(type, &already_seen);
- }
- bool HasRepeatedFields(const Descriptor* descriptor) {
- for (int i = 0; i < descriptor->field_count(); ++i) {
- const FieldDescriptor* field = descriptor->field(i);
- if (field->is_repeated()) {
- return true;
- }
- }
- return false;
- }
- // Encode an unsigned 32-bit value into a sequence of UTF-16 characters.
- //
- // If the value is in [0x0000, 0xD7FF], we encode it with a single character
- // with the same numeric value.
- //
- // If the value is larger than 0xD7FF, we encode its lowest 13 bits into a
- // character in the range [0xE000, 0xFFFF] by combining these 13 bits with
- // 0xE000 using logic-or. Then we shift the value to the right by 13 bits, and
- // encode the remaining value by repeating this same process until we get to
- // a value in [0x0000, 0xD7FF] where we will encode it using a character with
- // the same numeric value.
- //
- // Note that we only use code points in [0x0000, 0xD7FF] and [0xE000, 0xFFFF].
- // There will be no surrogate pairs in the encoded character sequence.
- void WriteUInt32ToUtf16CharSequence(uint32 number,
- std::vector<uint16>* output) {
- // For values in [0x0000, 0xD7FF], only use one char to encode it.
- if (number < 0xD800) {
- output->push_back(static_cast<uint16>(number));
- return;
- }
- // Encode into multiple chars. All except the last char will be in the range
- // [0xE000, 0xFFFF], and the last char will be in the range [0x0000, 0xD7FF].
- // Note that we don't use any value in range [0xD800, 0xDFFF] because they
- // have to come in pairs and the encoding is just more space-efficient w/o
- // them.
- while (number >= 0xD800) {
- // [0xE000, 0xFFFF] can represent 13 bits of info.
- output->push_back(static_cast<uint16>(0xE000 | (number & 0x1FFF)));
- number >>= 13;
- }
- output->push_back(static_cast<uint16>(number));
- }
- int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) {
- // j/c/g/protobuf/FieldType.java lists field types in a slightly different
- // order from FieldDescriptor::Type so we can't do a simple cast.
- //
- // TODO(xiaofeng): Make j/c/g/protobuf/FieldType.java follow the same order.
- int result = field->type();
- if (result == FieldDescriptor::TYPE_GROUP) {
- return 17;
- } else if (result < FieldDescriptor::TYPE_GROUP) {
- return result - 1;
- } else {
- return result - 2;
- }
- }
- int GetExperimentalJavaFieldTypeForRepeated(const FieldDescriptor* field) {
- if (field->type() == FieldDescriptor::TYPE_GROUP) {
- return 49;
- } else {
- return GetExperimentalJavaFieldTypeForSingular(field) + 18;
- }
- }
- int GetExperimentalJavaFieldTypeForPacked(const FieldDescriptor* field) {
- int result = field->type();
- if (result < FieldDescriptor::TYPE_STRING) {
- return result + 34;
- } else if (result > FieldDescriptor::TYPE_BYTES) {
- return result + 30;
- } else {
- GOOGLE_LOG(FATAL) << field->full_name() << " can't be packed.";
- return 0;
- }
- }
- int GetExperimentalJavaFieldType(const FieldDescriptor* field) {
- static const int kMapFieldType = 50;
- static const int kOneofFieldTypeOffset = 51;
- static const int kRequiredBit = 0x100;
- static const int kUtf8CheckBit = 0x200;
- static const int kCheckInitialized = 0x400;
- static const int kMapWithProto2EnumValue = 0x800;
- int extra_bits = field->is_required() ? kRequiredBit : 0;
- if (field->type() == FieldDescriptor::TYPE_STRING && CheckUtf8(field)) {
- extra_bits |= kUtf8CheckBit;
- }
- if (field->is_required() || (GetJavaType(field) == JAVATYPE_MESSAGE &&
- HasRequiredFields(field->message_type()))) {
- extra_bits |= kCheckInitialized;
- }
- if (field->is_map()) {
- if (SupportFieldPresence(field->file())) {
- const FieldDescriptor* value =
- field->message_type()->FindFieldByName("value");
- if (GetJavaType(value) == JAVATYPE_ENUM) {
- extra_bits |= kMapWithProto2EnumValue;
- }
- }
- return kMapFieldType | extra_bits;
- } else if (field->is_packed()) {
- return GetExperimentalJavaFieldTypeForPacked(field);
- } else if (field->is_repeated()) {
- return GetExperimentalJavaFieldTypeForRepeated(field) | extra_bits;
- } else if (field->containing_oneof() != NULL) {
- return (GetExperimentalJavaFieldTypeForSingular(field) +
- kOneofFieldTypeOffset) |
- extra_bits;
- } else {
- return GetExperimentalJavaFieldTypeForSingular(field) | extra_bits;
- }
- }
- // Escape a UTF-16 character to be embedded in a Java string.
- void EscapeUtf16ToString(uint16 code, string* output) {
- if (code == '\t') {
- output->append("\\t");
- } else if (code == '\b') {
- output->append("\\b");
- } else if (code == '\n') {
- output->append("\\n");
- } else if (code == '\r') {
- output->append("\\r");
- } else if (code == '\f') {
- output->append("\\f");
- } else if (code == '\'') {
- output->append("\\'");
- } else if (code == '\"') {
- output->append("\\\"");
- } else if (code == '\\') {
- output->append("\\\\");
- } else if (code >= 0x20 && code <= 0x7f) {
- output->push_back(static_cast<char>(code));
- } else {
- output->append(StringPrintf("\\u%04x", code));
- }
- }
- std::pair<int, int> GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber(
- const FieldDescriptor** fields, int count) {
- GOOGLE_CHECK_GT(count, 0);
- int table_driven_number_of_entries = count;
- int look_up_start_field_number = 0;
- for (int i = 0; i < count; i++) {
- const int field_number = fields[i]->number();
- if (ShouldUseTable(fields[0]->number(), field_number, i + 1)) {
- table_driven_number_of_entries =
- field_number - fields[0]->number() + 1 + count - i - 1;
- look_up_start_field_number = field_number + 1;
- }
- }
- return std::make_pair(
- table_driven_number_of_entries, look_up_start_field_number);
- }
- } // namespace java
- } // namespace compiler
- } // namespace protobuf
- } // namespace google
|