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 <google/protobuf/compiler/cpp/cpp_field.h>
     36 #include <memory>
     37 #ifndef _SHARED_PTR_H
     38 #include <google/protobuf/stubs/shared_ptr.h>
     39 #endif
     40 
     41 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
     42 #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
     43 #include <google/protobuf/compiler/cpp/cpp_string_field.h>
     44 #include <google/protobuf/compiler/cpp/cpp_enum_field.h>
     45 #include <google/protobuf/compiler/cpp/cpp_map_field.h>
     46 #include <google/protobuf/compiler/cpp/cpp_message_field.h>
     47 #include <google/protobuf/descriptor.pb.h>
     48 #include <google/protobuf/wire_format.h>
     49 #include <google/protobuf/io/printer.h>
     50 #include <google/protobuf/stubs/logging.h>
     51 #include <google/protobuf/stubs/common.h>
     52 #include <google/protobuf/stubs/strutil.h>
     53 
     54 namespace google {
     55 namespace protobuf {
     56 namespace compiler {
     57 namespace cpp {
     58 
     59 using internal::WireFormat;
     60 
     61 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
     62                              map<string, string>* variables,
     63                              const Options& options) {
     64   (*variables)["name"] = FieldName(descriptor);
     65   (*variables)["index"] = SimpleItoa(descriptor->index());
     66   (*variables)["number"] = SimpleItoa(descriptor->number());
     67   (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
     68   (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
     69 
     70   // non_null_ptr_to_name is usable only if has_$name$ is true.  It yields a
     71   // pointer that will not be NULL.  Subclasses of FieldGenerator may set
     72   // (*variables)["non_null_ptr_to_name"] differently.
     73   (*variables)["non_null_ptr_to_name"] =
     74       StrCat("&this->", FieldName(descriptor), "()");
     75 
     76   (*variables)["tag_size"] = SimpleItoa(
     77     WireFormat::TagSize(descriptor->number(), descriptor->type()));
     78   (*variables)["deprecation"] = descriptor->options().deprecated()
     79       ? " PROTOBUF_DEPRECATED" : "";
     80   (*variables)["deprecated_attr"] = descriptor->options().deprecated()
     81       ? "PROTOBUF_DEPRECATED_ATTR " : "";
     82 
     83   (*variables)["cppget"] = "Get";
     84 
     85   if (HasFieldPresence(descriptor->file())) {
     86     (*variables)["set_hasbit"] =
     87         "set_has_" + FieldName(descriptor) + "();";
     88     (*variables)["clear_hasbit"] =
     89         "clear_has_" + FieldName(descriptor) + "();";
     90   } else {
     91     (*variables)["set_hasbit"] = "";
     92     (*variables)["clear_hasbit"] = "";
     93   }
     94 
     95   // By default, empty string, so that generic code used for both oneofs and
     96   // singular fields can be written.
     97   (*variables)["oneof_prefix"] = "";
     98 }
     99 
    100 void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
    101                                   map<string, string>* variables) {
    102   const string prefix = descriptor->containing_oneof()->name() + "_.";
    103   (*variables)["oneof_prefix"] = prefix;
    104   (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
    105   (*variables)["non_null_ptr_to_name"] =
    106       StrCat(prefix, (*variables)["name"], "_");
    107 }
    108 
    109 FieldGenerator::~FieldGenerator() {}
    110 
    111 void FieldGenerator::
    112 GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
    113   // Reaching here indicates a bug. Cases are:
    114   //   - This FieldGenerator should support packing, but this method should be
    115   //     overridden.
    116   //   - This FieldGenerator doesn't support packing, and this method should
    117   //     never have been called.
    118   GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
    119              << "called on field generator that does not support packing.";
    120 
    121 }
    122 
    123 FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
    124                                      const Options& options)
    125     : descriptor_(descriptor),
    126       options_(options),
    127       field_generators_(
    128           new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
    129   // Construct all the FieldGenerators.
    130   for (int i = 0; i < descriptor->field_count(); i++) {
    131     field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
    132   }
    133 }
    134 
    135 FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
    136                                                  const Options& options) {
    137   if (field->is_repeated()) {
    138     switch (field->cpp_type()) {
    139       case FieldDescriptor::CPPTYPE_MESSAGE:
    140         if (field->is_map()) {
    141           return new MapFieldGenerator(field, options);
    142         } else {
    143           return new RepeatedMessageFieldGenerator(field, options);
    144         }
    145       case FieldDescriptor::CPPTYPE_STRING:
    146         switch (field->options().ctype()) {
    147           default:  // RepeatedStringFieldGenerator handles unknown ctypes.
    148           case FieldOptions::STRING:
    149             return new RepeatedStringFieldGenerator(field, options);
    150         }
    151       case FieldDescriptor::CPPTYPE_ENUM:
    152         return new RepeatedEnumFieldGenerator(field, options);
    153       default:
    154         return new RepeatedPrimitiveFieldGenerator(field, options);
    155     }
    156   } else if (field->containing_oneof()) {
    157     switch (field->cpp_type()) {
    158       case FieldDescriptor::CPPTYPE_MESSAGE:
    159         return new MessageOneofFieldGenerator(field, options);
    160       case FieldDescriptor::CPPTYPE_STRING:
    161         switch (field->options().ctype()) {
    162           default:  // StringOneofFieldGenerator handles unknown ctypes.
    163           case FieldOptions::STRING:
    164             return new StringOneofFieldGenerator(field, options);
    165         }
    166       case FieldDescriptor::CPPTYPE_ENUM:
    167         return new EnumOneofFieldGenerator(field, options);
    168       default:
    169         return new PrimitiveOneofFieldGenerator(field, options);
    170     }
    171   } else {
    172     switch (field->cpp_type()) {
    173       case FieldDescriptor::CPPTYPE_MESSAGE:
    174         return new MessageFieldGenerator(field, options);
    175       case FieldDescriptor::CPPTYPE_STRING:
    176         switch (field->options().ctype()) {
    177           default:  // StringFieldGenerator handles unknown ctypes.
    178           case FieldOptions::STRING:
    179             return new StringFieldGenerator(field, options);
    180         }
    181       case FieldDescriptor::CPPTYPE_ENUM:
    182         return new EnumFieldGenerator(field, options);
    183       default:
    184         return new PrimitiveFieldGenerator(field, options);
    185     }
    186   }
    187 }
    188 
    189 FieldGeneratorMap::~FieldGeneratorMap() {}
    190 
    191 const FieldGenerator& FieldGeneratorMap::get(
    192     const FieldDescriptor* field) const {
    193   GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
    194   return *field_generators_[field->index()];
    195 }
    196 
    197 
    198 }  // namespace cpp
    199 }  // namespace compiler
    200 }  // namespace protobuf
    201 }  // namespace google
    202