LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf/compiler/cpp - cpp_helpers.cc (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 238 273 87.2 %
Date: 2015-10-10 Functions: 40 46 87.0 %

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

Generated by: LCOV version 1.10