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 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
     36 #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
     37 
     38 #include <map>
     39 #include <string>
     40 #include <google/protobuf/compiler/cpp/cpp_options.h>
     41 #include <google/protobuf/descriptor.pb.h>
     42 #include <google/protobuf/descriptor.h>
     43 
     44 namespace google {
     45 namespace protobuf {
     46 
     47 namespace io {
     48 class Printer;
     49 }
     50 
     51 namespace compiler {
     52 namespace cpp {
     53 
     54 // Commonly-used separator comments.  Thick is a line of '=', thin is a line
     55 // of '-'.
     56 extern const char kThickSeparator[];
     57 extern const char kThinSeparator[];
     58 
     59 // Returns the non-nested type name for the given type.  If "qualified" is
     60 // true, prefix the type with the full namespace.  For example, if you had:
     61 //   package foo.bar;
     62 //   message Baz { message Qux {} }
     63 // Then the qualified ClassName for Qux would be:
     64 //   ::foo::bar::Baz_Qux
     65 // While the non-qualified version would be:
     66 //   Baz_Qux
     67 string ClassName(const Descriptor* descriptor, bool qualified);
     68 string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
     69 
     70 // Name of the CRTP class template (for use with proto_h).
     71 // This is a class name, like "ProtoName_InternalBase".
     72 string DependentBaseClassTemplateName(const Descriptor* descriptor);
     73 
     74 // Name of the base class: either the dependent base class (for use with
     75 // proto_h) or google::protobuf::Message.
     76 string SuperClassName(const Descriptor* descriptor, const Options& options);
     77 
     78 // Returns a string that down-casts from the dependent base class to the
     79 // derived class.
     80 string DependentBaseDownCast();
     81 string DependentBaseConstDownCast();
     82 
     83 // Get the (unqualified) name that should be used for this field in C++ code.
     84 // The name is coerced to lower-case to emulate proto1 behavior.  People
     85 // should be using lowercase-with-underscores style for proto field names
     86 // anyway, so normally this just returns field->name().
     87 string FieldName(const FieldDescriptor* field);
     88 
     89 // Get the sanitized name that should be used for the given enum in C++ code.
     90 string EnumValueName(const EnumValueDescriptor* enum_value);
     91 
     92 // Get the unqualified name that should be used for a field's field
     93 // number constant.
     94 string FieldConstantName(const FieldDescriptor *field);
     95 
     96 // Returns the scope where the field was defined (for extensions, this is
     97 // different from the message type to which the field applies).
     98 inline const Descriptor* FieldScope(const FieldDescriptor* field) {
     99   return field->is_extension() ?
    100     field->extension_scope() : field->containing_type();
    101 }
    102 
    103 // Returns true if the given 'field_descriptor' has a message type that is
    104 // a dependency of the file where the field is defined (i.e., the field
    105 // type is defined in a different file than the message holding the field).
    106 //
    107 // This only applies to Message-typed fields. Enum-typed fields may refer
    108 // to an enum in a dependency; however, enums are specified and
    109 // forward-declared with an enum-base, so the definition is not required to
    110 // manipulate the field value.
    111 bool IsFieldDependent(const FieldDescriptor* field_descriptor);
    112 
    113 // Returns the name that should be used for forcing dependent lookup from a
    114 // dependent base class.
    115 string DependentTypeName(const FieldDescriptor* field);
    116 
    117 // Returns the fully-qualified type name field->message_type().  Usually this
    118 // is just ClassName(field->message_type(), true);
    119 string FieldMessageTypeName(const FieldDescriptor* field);
    120 
    121 // Strips ".proto" or ".protodevel" from the end of a filename.
    122 LIBPROTOC_EXPORT string StripProto(const string& filename);
    123 
    124 // Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
    125 // Note:  non-built-in type names will be qualified, meaning they will start
    126 // with a ::.  If you are using the type as a template parameter, you will
    127 // need to insure there is a space between the < and the ::, because the
    128 // ridiculous C++ standard defines "<:" to be a synonym for "[".
    129 const char* PrimitiveTypeName(FieldDescriptor::CppType type);
    130 
    131 // Get the declared type name in CamelCase format, as is used e.g. for the
    132 // methods of WireFormat.  For example, TYPE_INT32 becomes "Int32".
    133 const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
    134 
    135 // Return the code that evaluates to the number when compiled.
    136 string Int32ToString(int number);
    137 
    138 // Return the code that evaluates to the number when compiled.
    139 string Int64ToString(int64 number);
    140 
    141 // Get code that evaluates to the field's default value.
    142 string DefaultValue(const FieldDescriptor* field);
    143 
    144 // Convert a file name into a valid identifier.
    145 string FilenameIdentifier(const string& filename);
    146 
    147 // Return the name of the AddDescriptors() function for a given file.
    148 string GlobalAddDescriptorsName(const string& filename);
    149 
    150 // Return the name of the AssignDescriptors() function for a given file.
    151 string GlobalAssignDescriptorsName(const string& filename);
    152 
    153 // Return the qualified C++ name for a file level symbol.
    154 string QualifiedFileLevelSymbol(const string& package, const string& name);
    155 
    156 // Return the name of the ShutdownFile() function for a given file.
    157 string GlobalShutdownFileName(const string& filename);
    158 
    159 // Escape C++ trigraphs by escaping question marks to \?
    160 string EscapeTrigraphs(const string& to_escape);
    161 
    162 // Escaped function name to eliminate naming conflict.
    163 string SafeFunctionName(const Descriptor* descriptor,
    164                         const FieldDescriptor* field,
    165                         const string& prefix);
    166 
    167 // Returns true if unknown fields are preseved after parsing.
    168 inline bool PreserveUnknownFields(const Descriptor* message) {
    169   return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
    170 }
    171 
    172 // Returns the optimize mode for <file>, respecting <options.enforce_lite>.
    173 ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
    174     const FileDescriptor* file, const Options& options);
    175 
    176 // If PreserveUnknownFields() is true, determines whether unknown
    177 // fields will be stored in an UnknownFieldSet or a string.
    178 // If PreserveUnknownFields() is false, this method will not be
    179 // used.
    180 inline bool UseUnknownFieldSet(const FileDescriptor* file,
    181                                const Options& options) {
    182   return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
    183 }
    184 
    185 
    186 // Does the file have any map fields, necessitating the file to include
    187 // map_field_inl.h and map.h.
    188 bool HasMapFields(const FileDescriptor* file);
    189 
    190 // Does this file have any enum type definitions?
    191 bool HasEnumDefinitions(const FileDescriptor* file);
    192 
    193 // Does this file have generated parsing, serialization, and other
    194 // standard methods for which reflection-based fallback implementations exist?
    195 inline bool HasGeneratedMethods(const FileDescriptor* file,
    196                                 const Options& options) {
    197   return GetOptimizeFor(file, options) != FileOptions::CODE_SIZE;
    198 }
    199 
    200 // Do message classes in this file have descriptor and reflection methods?
    201 inline bool HasDescriptorMethods(const FileDescriptor* file,
    202                                  const Options& options) {
    203   return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
    204 }
    205 
    206 // Should we generate generic services for this file?
    207 inline bool HasGenericServices(const FileDescriptor* file,
    208                                const Options& options) {
    209   return file->service_count() > 0 &&
    210          GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME &&
    211          file->options().cc_generic_services();
    212 }
    213 
    214 // Should we generate a separate, super-optimized code path for serializing to
    215 // flat arrays?  We don't do this in Lite mode because we'd rather reduce code
    216 // size.
    217 inline bool HasFastArraySerialization(const FileDescriptor* file,
    218                                       const Options& options) {
    219   return GetOptimizeFor(file, options) == FileOptions::SPEED;
    220 }
    221 
    222 // Returns whether we have to generate code with static initializers.
    223 bool StaticInitializersForced(const FileDescriptor* file,
    224                               const Options& options);
    225 
    226 // Prints 'with_static_init' if static initializers have to be used for the
    227 // provided file. Otherwise emits both 'with_static_init' and
    228 // 'without_static_init' using #ifdef.
    229 void PrintHandlingOptionalStaticInitializers(
    230     const FileDescriptor* file, const Options& options, io::Printer* printer,
    231     const char* with_static_init, const char* without_static_init,
    232     const char* var1 = NULL, const string& val1 = "", const char* var2 = NULL,
    233     const string& val2 = "");
    234 
    235 void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars,
    236                                              const FileDescriptor* file,
    237                                              const Options& options,
    238                                              io::Printer* printer,
    239                                              const char* with_static_init,
    240                                              const char* without_static_init);
    241 
    242 
    243 inline bool IsMapEntryMessage(const Descriptor* descriptor) {
    244   return descriptor->options().map_entry();
    245 }
    246 
    247 // Returns true if the field's CPPTYPE is string or message.
    248 bool IsStringOrMessage(const FieldDescriptor* field);
    249 
    250 // For a string field, returns the effective ctype.  If the actual ctype is
    251 // not supported, returns the default of STRING.
    252 FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field);
    253 
    254 string UnderscoresToCamelCase(const string& input, bool cap_next_letter);
    255 
    256 inline bool HasFieldPresence(const FileDescriptor* file) {
    257   return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
    258 }
    259 
    260 // Returns true if 'enum' semantics are such that unknown values are preserved
    261 // in the enum field itself, rather than going to the UnknownFieldSet.
    262 inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
    263   return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
    264 }
    265 
    266 inline bool SupportsArenas(const FileDescriptor* file) {
    267   return file->options().cc_enable_arenas();
    268 }
    269 
    270 inline bool SupportsArenas(const Descriptor* desc) {
    271   return SupportsArenas(desc->file());
    272 }
    273 
    274 inline bool SupportsArenas(const FieldDescriptor* field) {
    275   return SupportsArenas(field->file());
    276 }
    277 
    278 bool IsAnyMessage(const FileDescriptor* descriptor);
    279 bool IsAnyMessage(const Descriptor* descriptor);
    280 
    281 bool IsWellKnownMessage(const FileDescriptor* descriptor);
    282 
    283 void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
    284                                     const Options& options, bool for_parse,
    285                                     const map<string, string>& variables,
    286                                     const char* parameters,
    287                                     io::Printer* printer);
    288 
    289 void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
    290                                   const Options& options, bool for_parse,
    291                                   const map<string, string>& variables,
    292                                   const char* parameters, io::Printer* printer);
    293 
    294 inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
    295     const FileDescriptor* file, const Options& options) {
    296   return options.enforce_lite
    297       ? FileOptions::LITE_RUNTIME
    298       : file->options().optimize_for();
    299 }
    300 
    301 }  // namespace cpp
    302 }  // namespace compiler
    303 }  // namespace protobuf
    304 
    305 }  // namespace google
    306 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
    307