Home | History | Annotate | Download | only in cpp
      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 <limits>
     36 #include <map>
     37 #include <vector>
     38 #include <google/protobuf/stubs/hash.h>
     39 
     40 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
     41 #include <google/protobuf/io/printer.h>
     42 #include <google/protobuf/stubs/logging.h>
     43 #include <google/protobuf/stubs/common.h>
     44 #include <google/protobuf/stubs/strutil.h>
     45 #include <google/protobuf/stubs/substitute.h>
     46 
     47 
     48 namespace google {
     49 namespace protobuf {
     50 namespace compiler {
     51 namespace cpp {
     52 
     53 namespace {
     54 
     55 static const char kAnyMessageName[] = "Any";
     56 static const char kAnyProtoFile[] = "google/protobuf/any.proto";
     57 static const char kGoogleProtobufPrefix[] = "google/protobuf/";
     58 
     59 string DotsToUnderscores(const string& name) {
     60   return StringReplace(name, ".", "_", true);
     61 }
     62 
     63 string DotsToColons(const string& name) {
     64   return StringReplace(name, ".", "::", true);
     65 }
     66 
     67 const char* const kKeywordList[] = {
     68   "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
     69   "bool", "break", "case", "catch", "char", "class", "compl", "const",
     70   "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
     71   "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern",
     72   "false", "float", "for", "friend", "goto", "if", "inline", "int", "long",
     73   "mutable", "namespace", "new", "noexcept", "not", "not_eq", "NULL",
     74   "operator", "or", "or_eq", "private", "protected", "public", "register",
     75   "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
     76   "static_assert", "static_cast", "struct", "switch", "template", "this",
     77   "thread_local", "throw", "true", "try", "typedef", "typeid", "typename",
     78   "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t",
     79   "while", "xor", "xor_eq"
     80 };
     81 
     82 hash_set<string> MakeKeywordsMap() {
     83   hash_set<string> result;
     84   for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); i++) {
     85     result.insert(kKeywordList[i]);
     86   }
     87   return result;
     88 }
     89 
     90 hash_set<string> kKeywords = MakeKeywordsMap();
     91 
     92 // Returns whether the provided descriptor has an extension. This includes its
     93 // nested types.
     94 bool HasExtension(const Descriptor* descriptor) {
     95   if (descriptor->extension_count() > 0) {
     96     return true;
     97   }
     98   for (int i = 0; i < descriptor->nested_type_count(); ++i) {
     99     if (HasExtension(descriptor->nested_type(i))) {
    100       return true;
    101     }
    102   }
    103   return false;
    104 }
    105 
    106 }  // namespace
    107 
    108 string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
    109   string result;
    110   // Note:  I distrust ctype.h due to locales.
    111   for (int i = 0; i < input.size(); i++) {
    112     if ('a' <= input[i] && input[i] <= 'z') {
    113       if (cap_next_letter) {
    114         result += input[i] + ('A' - 'a');
    115       } else {
    116         result += input[i];
    117       }
    118       cap_next_letter = false;
    119     } else if ('A' <= input[i] && input[i] <= 'Z') {
    120       // Capital letters are left as-is.
    121       result += input[i];
    122       cap_next_letter = false;
    123     } else if ('0' <= input[i] && input[i] <= '9') {
    124       result += input[i];
    125       cap_next_letter = true;
    126     } else {
    127       cap_next_letter = true;
    128     }
    129   }
    130   return result;
    131 }
    132 
    133 const char kThickSeparator[] =
    134   "// ===================================================================\n";
    135 const char kThinSeparator[] =
    136   "// -------------------------------------------------------------------\n";
    137 
    138 string ClassName(const Descriptor* descriptor, bool qualified) {
    139 
    140   // Find "outer", the descriptor of the top-level message in which
    141   // "descriptor" is embedded.
    142   const Descriptor* outer = descriptor;
    143   while (outer->containing_type() != NULL) outer = outer->containing_type();
    144 
    145   const string& outer_name = outer->full_name();
    146   string inner_name = descriptor->full_name().substr(outer_name.size());
    147 
    148   if (qualified) {
    149     return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name);
    150   } else {
    151     return outer->name() + DotsToUnderscores(inner_name);
    152   }
    153 }
    154 
    155 string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
    156   if (enum_descriptor->containing_type() == NULL) {
    157     if (qualified) {
    158       return "::" + DotsToColons(enum_descriptor->full_name());
    159     } else {
    160       return enum_descriptor->name();
    161     }
    162   } else {
    163     string result = ClassName(enum_descriptor->containing_type(), qualified);
    164     result += '_';
    165     result += enum_descriptor->name();
    166     return result;
    167   }
    168 }
    169 
    170 
    171 string DependentBaseClassTemplateName(const Descriptor* descriptor) {
    172   return ClassName(descriptor, false) + "_InternalBase";
    173 }
    174 
    175 string SuperClassName(const Descriptor* descriptor, const Options& options) {
    176   return HasDescriptorMethods(descriptor->file(), options)
    177              ? "::google::protobuf::Message"
    178              : "::google::protobuf::MessageLite";
    179 }
    180 
    181 string DependentBaseDownCast() {
    182   return "reinterpret_cast<T*>(this)->";
    183 }
    184 
    185 string DependentBaseConstDownCast() {
    186   return "reinterpret_cast<const T*>(this)->";
    187 }
    188 
    189 string FieldName(const FieldDescriptor* field) {
    190   string result = field->name();
    191   LowerString(&result);
    192   if (kKeywords.count(result) > 0) {
    193     result.append("_");
    194   }
    195   return result;
    196 }
    197 
    198 string EnumValueName(const EnumValueDescriptor* enum_value) {
    199   string result = enum_value->name();
    200   if (kKeywords.count(result) > 0) {
    201     result.append("_");
    202   }
    203   return result;
    204 }
    205 
    206 string FieldConstantName(const FieldDescriptor *field) {
    207   string field_name = UnderscoresToCamelCase(field->name(), true);
    208   string result = "k" + field_name + "FieldNumber";
    209 
    210   if (!field->is_extension() &&
    211       field->containing_type()->FindFieldByCamelcaseName(
    212         field->camelcase_name()) != field) {
    213     // This field's camelcase name is not unique.  As a hack, add the field
    214     // number to the constant name.  This makes the constant rather useless,
    215     // but what can we do?
    216     result += "_" + SimpleItoa(field->number());
    217   }
    218 
    219   return result;
    220 }
    221 
    222 bool IsFieldDependent(const FieldDescriptor* field) {
    223   if (field->containing_oneof() != NULL &&
    224       field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
    225     return true;
    226   }
    227   if (field->is_map()) {
    228     const Descriptor* map_descriptor = field->message_type();
    229     for (int i = 0; i < map_descriptor->field_count(); i++) {
    230       if (IsFieldDependent(map_descriptor->field(i))) {
    231         return true;
    232       }
    233     }
    234     return false;
    235   }
    236   if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
    237     return false;
    238   }
    239   if (field->containing_oneof() != NULL) {
    240     // Oneof fields will always be dependent.
    241     //
    242     // This is a unique case for field codegen. Field generators are
    243     // responsible for generating all the field-specific accessor
    244     // functions, except for the clear_*() function; instead, field
    245     // generators produce inline clearing code.
    246     //
    247     // For non-oneof fields, the Message class uses the inline clearing
    248     // code to define the field's clear_*() function, as well as in the
    249     // destructor. For oneof fields, the Message class generates a much
    250     // more complicated clear_*() function, which clears only the oneof
    251     // member that is set, in addition to clearing methods for each of the
    252     // oneof members individually.
    253     //
    254     // Since oneofs do not have their own generator class, the Message code
    255     // generation logic would be significantly complicated in order to
    256     // split dependent and non-dependent manipulation logic based on
    257     // whether the oneof truly needs to be dependent; so, for oneof fields,
    258     // we just assume it (and its constituents) should be manipulated by a
    259     // dependent base class function.
    260     //
    261     // This is less precise than how dependent message-typed fields are
    262     // handled, but the cost is limited to only the generated code for the
    263     // oneof field, which seems like an acceptable tradeoff.
    264     return true;
    265   }
    266   if (field->file() == field->message_type()->file()) {
    267     return false;
    268   }
    269   return true;
    270 }
    271 
    272 string DependentTypeName(const FieldDescriptor* field) {
    273   return "InternalBase_" + field->name() + "_T";
    274 }
    275 
    276 string FieldMessageTypeName(const FieldDescriptor* field) {
    277   // Note:  The Google-internal version of Protocol Buffers uses this function
    278   //   as a hook point for hacks to support legacy code.
    279   return ClassName(field->message_type(), true);
    280 }
    281 
    282 string StripProto(const string& filename) {
    283   if (HasSuffixString(filename, ".protodevel")) {
    284     return StripSuffixString(filename, ".protodevel");
    285   } else {
    286     return StripSuffixString(filename, ".proto");
    287   }
    288 }
    289 
    290 const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
    291   switch (type) {
    292     case FieldDescriptor::CPPTYPE_INT32  : return "::google::protobuf::int32";
    293     case FieldDescriptor::CPPTYPE_INT64  : return "::google::protobuf::int64";
    294     case FieldDescriptor::CPPTYPE_UINT32 : return "::google::protobuf::uint32";
    295     case FieldDescriptor::CPPTYPE_UINT64 : return "::google::protobuf::uint64";
    296     case FieldDescriptor::CPPTYPE_DOUBLE : return "double";
    297     case FieldDescriptor::CPPTYPE_FLOAT  : return "float";
    298     case FieldDescriptor::CPPTYPE_BOOL   : return "bool";
    299     case FieldDescriptor::CPPTYPE_ENUM   : return "int";
    300     case FieldDescriptor::CPPTYPE_STRING : return "::std::string";
    301     case FieldDescriptor::CPPTYPE_MESSAGE: return NULL;
    302 
    303     // No default because we want the compiler to complain if any new
    304     // CppTypes are added.
    305   }
    306 
    307   GOOGLE_LOG(FATAL) << "Can't get here.";
    308   return NULL;
    309 }
    310 
    311 const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
    312   switch (type) {
    313     case FieldDescriptor::TYPE_INT32   : return "Int32";
    314     case FieldDescriptor::TYPE_INT64   : return "Int64";
    315     case FieldDescriptor::TYPE_UINT32  : return "UInt32";
    316     case FieldDescriptor::TYPE_UINT64  : return "UInt64";
    317     case FieldDescriptor::TYPE_SINT32  : return "SInt32";
    318     case FieldDescriptor::TYPE_SINT64  : return "SInt64";
    319     case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
    320     case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
    321     case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
    322     case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
    323     case FieldDescriptor::TYPE_FLOAT   : return "Float";
    324     case FieldDescriptor::TYPE_DOUBLE  : return "Double";
    325 
    326     case FieldDescriptor::TYPE_BOOL    : return "Bool";
    327     case FieldDescriptor::TYPE_ENUM    : return "Enum";
    328 
    329     case FieldDescriptor::TYPE_STRING  : return "String";
    330     case FieldDescriptor::TYPE_BYTES   : return "Bytes";
    331     case FieldDescriptor::TYPE_GROUP   : return "Group";
    332     case FieldDescriptor::TYPE_MESSAGE : return "Message";
    333 
    334     // No default because we want the compiler to complain if any new
    335     // types are added.
    336   }
    337   GOOGLE_LOG(FATAL) << "Can't get here.";
    338   return "";
    339 }
    340 
    341 string Int32ToString(int number) {
    342   // gcc rejects the decimal form of kint32min.
    343   if (number == kint32min) {
    344     GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error);
    345     return "(~0x7fffffff)";
    346   } else {
    347     return SimpleItoa(number);
    348   }
    349 }
    350 
    351 string Int64ToString(int64 number) {
    352   // gcc rejects the decimal form of kint64min
    353   if (number == kint64min) {
    354     // Make sure we are in a 2's complement system.
    355     GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(~0x7fffffffffffffff),
    356                    kint64min_value_error);
    357     return "GOOGLE_LONGLONG(~0x7fffffffffffffff)";
    358   }
    359   return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")";
    360 }
    361 
    362 string DefaultValue(const FieldDescriptor* field) {
    363   switch (field->cpp_type()) {
    364     case FieldDescriptor::CPPTYPE_INT32:
    365       return Int32ToString(field->default_value_int32());
    366     case FieldDescriptor::CPPTYPE_UINT32:
    367       return SimpleItoa(field->default_value_uint32()) + "u";
    368     case FieldDescriptor::CPPTYPE_INT64:
    369       return Int64ToString(field->default_value_int64());
    370     case FieldDescriptor::CPPTYPE_UINT64:
    371       return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
    372     case FieldDescriptor::CPPTYPE_DOUBLE: {
    373       double value = field->default_value_double();
    374       if (value == numeric_limits<double>::infinity()) {
    375         return "::google::protobuf::internal::Infinity()";
    376       } else if (value == -numeric_limits<double>::infinity()) {
    377         return "-::google::protobuf::internal::Infinity()";
    378       } else if (value != value) {
    379         return "::google::protobuf::internal::NaN()";
    380       } else {
    381         return SimpleDtoa(value);
    382       }
    383     }
    384     case FieldDescriptor::CPPTYPE_FLOAT:
    385       {
    386         float value = field->default_value_float();
    387         if (value == numeric_limits<float>::infinity()) {
    388           return "static_cast<float>(::google::protobuf::internal::Infinity())";
    389         } else if (value == -numeric_limits<float>::infinity()) {
    390           return "static_cast<float>(-::google::protobuf::internal::Infinity())";
    391         } else if (value != value) {
    392           return "static_cast<float>(::google::protobuf::internal::NaN())";
    393         } else {
    394           string float_value = SimpleFtoa(value);
    395           // If floating point value contains a period (.) or an exponent
    396           // (either E or e), then append suffix 'f' to make it a float
    397           // literal.
    398           if (float_value.find_first_of(".eE") != string::npos) {
    399             float_value.push_back('f');
    400           }
    401           return float_value;
    402         }
    403       }
    404     case FieldDescriptor::CPPTYPE_BOOL:
    405       return field->default_value_bool() ? "true" : "false";
    406     case FieldDescriptor::CPPTYPE_ENUM:
    407       // Lazy:  Generate a static_cast because we don't have a helper function
    408       //   that constructs the full name of an enum value.
    409       return strings::Substitute(
    410           "static_cast< $0 >($1)",
    411           ClassName(field->enum_type(), true),
    412           Int32ToString(field->default_value_enum()->number()));
    413     case FieldDescriptor::CPPTYPE_STRING:
    414       return "\"" + EscapeTrigraphs(
    415         CEscape(field->default_value_string())) +
    416         "\"";
    417     case FieldDescriptor::CPPTYPE_MESSAGE:
    418       return FieldMessageTypeName(field) + "::default_instance()";
    419   }
    420   // Can't actually get here; make compiler happy.  (We could add a default
    421   // case above but then we wouldn't get the nice compiler warning when a
    422   // new type is added.)
    423   GOOGLE_LOG(FATAL) << "Can't get here.";
    424   return "";
    425 }
    426 
    427 // Convert a file name into a valid identifier.
    428 string FilenameIdentifier(const string& filename) {
    429   string result;
    430   for (int i = 0; i < filename.size(); i++) {
    431     if (ascii_isalnum(filename[i])) {
    432       result.push_back(filename[i]);
    433     } else {
    434       // Not alphanumeric.  To avoid any possibility of name conflicts we
    435       // use the hex code for the character.
    436       StrAppend(&result, "_", strings::Hex(static_cast<uint8>(filename[i])));
    437     }
    438   }
    439   return result;
    440 }
    441 
    442 // Return the name of the AddDescriptors() function for a given file.
    443 string GlobalAddDescriptorsName(const string& filename) {
    444   return "protobuf_AddDesc_" + FilenameIdentifier(filename);
    445 }
    446 
    447 // Return the name of the AssignDescriptors() function for a given file.
    448 string GlobalAssignDescriptorsName(const string& filename) {
    449   return "protobuf_AssignDesc_" + FilenameIdentifier(filename);
    450 }
    451 
    452 // Return the name of the ShutdownFile() function for a given file.
    453 string GlobalShutdownFileName(const string& filename) {
    454   return "protobuf_ShutdownFile_" + FilenameIdentifier(filename);
    455 }
    456 
    457 // Return the qualified C++ name for a file level symbol.
    458 string QualifiedFileLevelSymbol(const string& package, const string& name) {
    459   if (package.empty()) {
    460     return StrCat("::", name);
    461   }
    462   return StrCat("::", DotsToColons(package), "::", name);
    463 }
    464 
    465 // Escape C++ trigraphs by escaping question marks to \?
    466 string EscapeTrigraphs(const string& to_escape) {
    467   return StringReplace(to_escape, "?", "\\?", true);
    468 }
    469 
    470 // Escaped function name to eliminate naming conflict.
    471 string SafeFunctionName(const Descriptor* descriptor,
    472                         const FieldDescriptor* field,
    473                         const string& prefix) {
    474   // Do not use FieldName() since it will escape keywords.
    475   string name = field->name();
    476   LowerString(&name);
    477   string function_name = prefix + name;
    478   if (descriptor->FindFieldByName(function_name)) {
    479     // Single underscore will also make it conflicting with the private data
    480     // member. We use double underscore to escape function names.
    481     function_name.append("__");
    482   } else if (kKeywords.count(name) > 0) {
    483     // If the field name is a keyword, we append the underscore back to keep it
    484     // consistent with other function names.
    485     function_name.append("_");
    486   }
    487   return function_name;
    488 }
    489 
    490 bool StaticInitializersForced(const FileDescriptor* file,
    491                               const Options& options) {
    492   if (HasDescriptorMethods(file, options) || file->extension_count() > 0) {
    493     return true;
    494   }
    495   for (int i = 0; i < file->message_type_count(); ++i) {
    496     if (HasExtension(file->message_type(i))) {
    497       return true;
    498     }
    499   }
    500   return false;
    501 }
    502 
    503 void PrintHandlingOptionalStaticInitializers(
    504     const FileDescriptor* file, const Options& options, io::Printer* printer,
    505     const char* with_static_init, const char* without_static_init,
    506     const char* var1, const string& val1, const char* var2,
    507     const string& val2) {
    508   map<string, string> vars;
    509   if (var1) {
    510     vars[var1] = val1;
    511   }
    512   if (var2) {
    513     vars[var2] = val2;
    514   }
    515   PrintHandlingOptionalStaticInitializers(
    516       vars, file, options, printer, with_static_init, without_static_init);
    517 }
    518 
    519 void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars,
    520                                              const FileDescriptor* file,
    521                                              const Options& options,
    522                                              io::Printer* printer,
    523                                              const char* with_static_init,
    524                                              const char* without_static_init) {
    525   if (StaticInitializersForced(file, options)) {
    526     printer->Print(vars, with_static_init);
    527   } else {
    528     printer->Print(vars, (string(
    529       "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n") +
    530       without_static_init +
    531       "#else\n" +
    532       with_static_init +
    533       "#endif\n").c_str());
    534   }
    535 }
    536 
    537 
    538 static bool HasMapFields(const Descriptor* descriptor) {
    539   for (int i = 0; i < descriptor->field_count(); ++i) {
    540     if (descriptor->field(i)->is_map()) {
    541       return true;
    542     }
    543   }
    544   for (int i = 0; i < descriptor->nested_type_count(); ++i) {
    545     if (HasMapFields(descriptor->nested_type(i))) return true;
    546   }
    547   return false;
    548 }
    549 
    550 bool HasMapFields(const FileDescriptor* file) {
    551   for (int i = 0; i < file->message_type_count(); ++i) {
    552     if (HasMapFields(file->message_type(i))) return true;
    553   }
    554   return false;
    555 }
    556 
    557 static bool HasEnumDefinitions(const Descriptor* message_type) {
    558   if (message_type->enum_type_count() > 0) return true;
    559   for (int i = 0; i < message_type->nested_type_count(); ++i) {
    560     if (HasEnumDefinitions(message_type->nested_type(i))) return true;
    561   }
    562   return false;
    563 }
    564 
    565 bool HasEnumDefinitions(const FileDescriptor* file) {
    566   if (file->enum_type_count() > 0) return true;
    567   for (int i = 0; i < file->message_type_count(); ++i) {
    568     if (HasEnumDefinitions(file->message_type(i))) return true;
    569   }
    570   return false;
    571 }
    572 
    573 bool IsStringOrMessage(const FieldDescriptor* field) {
    574   switch (field->cpp_type()) {
    575     case FieldDescriptor::CPPTYPE_INT32:
    576     case FieldDescriptor::CPPTYPE_INT64:
    577     case FieldDescriptor::CPPTYPE_UINT32:
    578     case FieldDescriptor::CPPTYPE_UINT64:
    579     case FieldDescriptor::CPPTYPE_DOUBLE:
    580     case FieldDescriptor::CPPTYPE_FLOAT:
    581     case FieldDescriptor::CPPTYPE_BOOL:
    582     case FieldDescriptor::CPPTYPE_ENUM:
    583       return false;
    584     case FieldDescriptor::CPPTYPE_STRING:
    585     case FieldDescriptor::CPPTYPE_MESSAGE:
    586       return true;
    587   }
    588 
    589   GOOGLE_LOG(FATAL) << "Can't get here.";
    590   return false;
    591 }
    592 
    593 FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) {
    594   GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
    595   // Open-source protobuf release only supports STRING ctype.
    596   return FieldOptions::STRING;
    597 
    598 }
    599 
    600 bool IsAnyMessage(const FileDescriptor* descriptor) {
    601   return descriptor->name() == kAnyProtoFile;
    602 }
    603 
    604 bool IsAnyMessage(const Descriptor* descriptor) {
    605   return descriptor->name() == kAnyMessageName &&
    606          descriptor->file()->name() == kAnyProtoFile;
    607 }
    608 
    609 bool IsWellKnownMessage(const FileDescriptor* descriptor) {
    610   return !descriptor->name().compare(0, 16, kGoogleProtobufPrefix);
    611 }
    612 
    613 enum Utf8CheckMode {
    614   STRICT = 0,  // Parsing will fail if non UTF-8 data is in string fields.
    615   VERIFY = 1,  // Only log an error but parsing will succeed.
    616   NONE = 2,  // No UTF-8 check.
    617 };
    618 
    619 // Which level of UTF-8 enforcemant is placed on this file.
    620 static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
    621                                       const Options& options) {
    622   if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
    623     return STRICT;
    624   } else if (GetOptimizeFor(field->file(), options) !=
    625              FileOptions::LITE_RUNTIME) {
    626     return VERIFY;
    627   } else {
    628     return NONE;
    629   }
    630 }
    631 
    632 static void GenerateUtf8CheckCode(const FieldDescriptor* field,
    633                                   const Options& options, bool for_parse,
    634                                   const map<string, string>& variables,
    635                                   const char* parameters,
    636                                   const char* strict_function,
    637                                   const char* verify_function,
    638                                   io::Printer* printer) {
    639   switch (GetUtf8CheckMode(field, options)) {
    640     case STRICT: {
    641       if (for_parse) {
    642         printer->Print("DO_(");
    643       }
    644       printer->Print(
    645           "::google::protobuf::internal::WireFormatLite::$function$(\n",
    646           "function", strict_function);
    647       printer->Indent();
    648       printer->Print(variables, parameters);
    649       if (for_parse) {
    650         printer->Print("::google::protobuf::internal::WireFormatLite::PARSE,\n");
    651       } else {
    652         printer->Print("::google::protobuf::internal::WireFormatLite::SERIALIZE,\n");
    653       }
    654       printer->Print("\"$full_name$\")", "full_name", field->full_name());
    655       if (for_parse) {
    656         printer->Print(")");
    657       }
    658       printer->Print(";\n");
    659       printer->Outdent();
    660       break;
    661     }
    662     case VERIFY: {
    663       printer->Print(
    664           "::google::protobuf::internal::WireFormat::$function$(\n",
    665           "function", verify_function);
    666       printer->Indent();
    667       printer->Print(variables, parameters);
    668       if (for_parse) {
    669         printer->Print("::google::protobuf::internal::WireFormat::PARSE,\n");
    670       } else {
    671         printer->Print("::google::protobuf::internal::WireFormat::SERIALIZE,\n");
    672       }
    673       printer->Print("\"$full_name$\");\n", "full_name", field->full_name());
    674       printer->Outdent();
    675       break;
    676     }
    677     case NONE:
    678       break;
    679   }
    680 }
    681 
    682 void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
    683                                     const Options& options, bool for_parse,
    684                                     const map<string, string>& variables,
    685                                     const char* parameters,
    686                                     io::Printer* printer) {
    687   GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
    688                         "VerifyUtf8String", "VerifyUTF8StringNamedField",
    689                         printer);
    690 }
    691 
    692 void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
    693                                   const Options& options, bool for_parse,
    694                                   const map<string, string>& variables,
    695                                   const char* parameters,
    696                                   io::Printer* printer) {
    697   GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
    698                         "VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer);
    699 }
    700 
    701 }  // namespace cpp
    702 }  // namespace compiler
    703 }  // namespace protobuf
    704 }  // namespace google
    705