Home | History | Annotate | Download | only in protobuf
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // http://code.google.com/p/protobuf/
      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 // Contains methods defined in extension_set.h which cannot be part of the
     36 // lite library because they use descriptors or reflection.
     37 
     38 #include <google/protobuf/extension_set.h>
     39 #include <google/protobuf/descriptor.h>
     40 #include <google/protobuf/message.h>
     41 #include <google/protobuf/repeated_field.h>
     42 #include <google/protobuf/wire_format.h>
     43 #include <google/protobuf/wire_format_lite_inl.h>
     44 
     45 namespace google {
     46 namespace protobuf {
     47 namespace internal {
     48 
     49 // Implementation of ExtensionFinder which finds extensions in a given
     50 // DescriptorPool, using the given MessageFactory to construct sub-objects.
     51 // This class is implemented in extension_set_heavy.cc.
     52 class DescriptorPoolExtensionFinder : public ExtensionFinder {
     53  public:
     54   DescriptorPoolExtensionFinder(const DescriptorPool* pool,
     55                                 MessageFactory* factory,
     56                                 const Descriptor* containing_type)
     57       : pool_(pool), factory_(factory), containing_type_(containing_type) {}
     58   virtual ~DescriptorPoolExtensionFinder() {}
     59 
     60   virtual bool Find(int number, ExtensionInfo* output);
     61 
     62  private:
     63   const DescriptorPool* pool_;
     64   MessageFactory* factory_;
     65   const Descriptor* containing_type_;
     66 };
     67 
     68 void ExtensionSet::AppendToList(const Descriptor* containing_type,
     69                                 const DescriptorPool* pool,
     70                                 vector<const FieldDescriptor*>* output) const {
     71   for (map<int, Extension>::const_iterator iter = extensions_.begin();
     72        iter != extensions_.end(); ++iter) {
     73     bool has = false;
     74     if (iter->second.is_repeated) {
     75       has = iter->second.GetSize() > 0;
     76     } else {
     77       has = !iter->second.is_cleared;
     78     }
     79 
     80     if (has) {
     81       // TODO(kenton): Looking up each field by number is somewhat unfortunate.
     82       //   Is there a better way?  The problem is that descriptors are lazily-
     83       //   initialized, so they might not even be constructed until
     84       //   AppendToList() is called.
     85 
     86       if (iter->second.descriptor == NULL) {
     87         output->push_back(pool->FindExtensionByNumber(
     88             containing_type, iter->first));
     89       } else {
     90         output->push_back(iter->second.descriptor);
     91       }
     92     }
     93   }
     94 }
     95 
     96 inline FieldDescriptor::Type real_type(FieldType type) {
     97   GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
     98   return static_cast<FieldDescriptor::Type>(type);
     99 }
    100 
    101 inline FieldDescriptor::CppType cpp_type(FieldType type) {
    102   return FieldDescriptor::TypeToCppType(
    103       static_cast<FieldDescriptor::Type>(type));
    104 }
    105 
    106 #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE)                            \
    107   GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED     \
    108                                   : FieldDescriptor::LABEL_OPTIONAL,      \
    109             FieldDescriptor::LABEL_##LABEL);                              \
    110   GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
    111 
    112 const MessageLite& ExtensionSet::GetMessage(int number,
    113                                             const Descriptor* message_type,
    114                                             MessageFactory* factory) const {
    115   map<int, Extension>::const_iterator iter = extensions_.find(number);
    116   if (iter == extensions_.end() || iter->second.is_cleared) {
    117     // Not present.  Return the default value.
    118     return *factory->GetPrototype(message_type);
    119   } else {
    120     GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
    121     return *iter->second.message_value;
    122   }
    123 }
    124 
    125 MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
    126                                           MessageFactory* factory) {
    127   Extension* extension;
    128   if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
    129     extension->type = descriptor->type();
    130     GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
    131     extension->is_repeated = false;
    132     extension->is_packed = false;
    133     const MessageLite* prototype =
    134         factory->GetPrototype(descriptor->message_type());
    135     GOOGLE_CHECK(prototype != NULL);
    136     extension->message_value = prototype->New();
    137   } else {
    138     GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
    139   }
    140   extension->is_cleared = false;
    141   return extension->message_value;
    142 }
    143 
    144 MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
    145                                       MessageFactory* factory) {
    146   Extension* extension;
    147   if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
    148     extension->type = descriptor->type();
    149     GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
    150     extension->is_repeated = true;
    151     extension->repeated_message_value =
    152       new RepeatedPtrField<MessageLite>();
    153   } else {
    154     GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
    155   }
    156 
    157   // RepeatedPtrField<Message> does not know how to Add() since it cannot
    158   // allocate an abstract object, so we have to be tricky.
    159   MessageLite* result = extension->repeated_message_value
    160       ->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
    161   if (result == NULL) {
    162     const MessageLite* prototype;
    163     if (extension->repeated_message_value->size() == 0) {
    164       prototype = factory->GetPrototype(descriptor->message_type());
    165       GOOGLE_CHECK(prototype != NULL);
    166     } else {
    167       prototype = &extension->repeated_message_value->Get(0);
    168     }
    169     result = prototype->New();
    170     extension->repeated_message_value->AddAllocated(result);
    171   }
    172   return result;
    173 }
    174 
    175 static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
    176   return reinterpret_cast<const EnumDescriptor*>(arg)
    177       ->FindValueByNumber(number) != NULL;
    178 }
    179 
    180 bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
    181   const FieldDescriptor* extension =
    182       pool_->FindExtensionByNumber(containing_type_, number);
    183   if (extension == NULL) {
    184     return false;
    185   } else {
    186     output->type = extension->type();
    187     output->is_repeated = extension->is_repeated();
    188     output->is_packed = extension->options().packed();
    189     output->descriptor = extension;
    190     if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
    191       output->message_prototype =
    192           factory_->GetPrototype(extension->message_type());
    193       GOOGLE_CHECK(output->message_prototype != NULL)
    194           << "Extension factory's GetPrototype() returned NULL for extension: "
    195           << extension->full_name();
    196     } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
    197       output->enum_validity_check.func = ValidateEnumUsingDescriptor;
    198       output->enum_validity_check.arg = extension->enum_type();
    199     }
    200 
    201     return true;
    202   }
    203 }
    204 
    205 bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
    206                               const Message* containing_type,
    207                               UnknownFieldSet* unknown_fields) {
    208   UnknownFieldSetFieldSkipper skipper(unknown_fields);
    209   if (input->GetExtensionPool() == NULL) {
    210     GeneratedExtensionFinder finder(containing_type);
    211     return ParseField(tag, input, &finder, &skipper);
    212   } else {
    213     DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
    214                                          input->GetExtensionFactory(),
    215                                          containing_type->GetDescriptor());
    216     return ParseField(tag, input, &finder, &skipper);
    217   }
    218 }
    219 
    220 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
    221                                    const Message* containing_type,
    222                                    UnknownFieldSet* unknown_fields) {
    223   UnknownFieldSetFieldSkipper skipper(unknown_fields);
    224   if (input->GetExtensionPool() == NULL) {
    225     GeneratedExtensionFinder finder(containing_type);
    226     return ParseMessageSet(input, &finder, &skipper);
    227   } else {
    228     DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
    229                                          input->GetExtensionFactory(),
    230                                          containing_type->GetDescriptor());
    231     return ParseMessageSet(input, &finder, &skipper);
    232   }
    233 }
    234 
    235 int ExtensionSet::SpaceUsedExcludingSelf() const {
    236   int total_size =
    237       extensions_.size() * sizeof(map<int, Extension>::value_type);
    238   for (map<int, Extension>::const_iterator iter = extensions_.begin(),
    239        end = extensions_.end();
    240        iter != end;
    241        ++iter) {
    242     total_size += iter->second.SpaceUsedExcludingSelf();
    243   }
    244   return total_size;
    245 }
    246 
    247 inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf(
    248     RepeatedPtrFieldBase* field) {
    249   return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
    250 }
    251 
    252 int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
    253   int total_size = 0;
    254   if (is_repeated) {
    255     switch (cpp_type(type)) {
    256 #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                          \
    257       case FieldDescriptor::CPPTYPE_##UPPERCASE:                   \
    258         total_size += sizeof(*repeated_##LOWERCASE##_value) +      \
    259             repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
    260         break
    261 
    262       HANDLE_TYPE(  INT32,   int32);
    263       HANDLE_TYPE(  INT64,   int64);
    264       HANDLE_TYPE( UINT32,  uint32);
    265       HANDLE_TYPE( UINT64,  uint64);
    266       HANDLE_TYPE(  FLOAT,   float);
    267       HANDLE_TYPE( DOUBLE,  double);
    268       HANDLE_TYPE(   BOOL,    bool);
    269       HANDLE_TYPE(   ENUM,    enum);
    270       HANDLE_TYPE( STRING,  string);
    271 #undef HANDLE_TYPE
    272 
    273       case FieldDescriptor::CPPTYPE_MESSAGE:
    274         // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
    275         // but MessageLite has no SpaceUsed(), so we must directly call
    276         // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
    277         // handler.
    278         total_size += sizeof(*repeated_message_value) +
    279             RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value);
    280         break;
    281     }
    282   } else {
    283     switch (cpp_type(type)) {
    284       case FieldDescriptor::CPPTYPE_STRING:
    285         total_size += sizeof(*string_value) +
    286                       StringSpaceUsedExcludingSelf(*string_value);
    287         break;
    288       case FieldDescriptor::CPPTYPE_MESSAGE:
    289         total_size += down_cast<Message*>(message_value)->SpaceUsed();
    290         break;
    291       default:
    292         // No extra storage costs for primitive types.
    293         break;
    294     }
    295   }
    296   return total_size;
    297 }
    298 
    299 // The Serialize*ToArray methods are only needed in the heavy library, as
    300 // the lite library only generates SerializeWithCachedSizes.
    301 uint8* ExtensionSet::SerializeWithCachedSizesToArray(
    302     int start_field_number, int end_field_number,
    303     uint8* target) const {
    304   map<int, Extension>::const_iterator iter;
    305   for (iter = extensions_.lower_bound(start_field_number);
    306        iter != extensions_.end() && iter->first < end_field_number;
    307        ++iter) {
    308     target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first,
    309                                                                target);
    310   }
    311   return target;
    312 }
    313 
    314 uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
    315     uint8* target) const {
    316   map<int, Extension>::const_iterator iter;
    317   for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
    318     target = iter->second.SerializeMessageSetItemWithCachedSizesToArray(
    319         iter->first, target);
    320   }
    321   return target;
    322 }
    323 
    324 uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray(
    325     int number, uint8* target) const {
    326   if (is_repeated) {
    327     if (is_packed) {
    328       if (cached_size == 0) return target;
    329 
    330       target = WireFormatLite::WriteTagToArray(number,
    331           WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
    332       target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
    333 
    334       switch (real_type(type)) {
    335 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
    336         case FieldDescriptor::TYPE_##UPPERCASE:                             \
    337           for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
    338             target = WireFormatLite::Write##CAMELCASE##NoTagToArray(        \
    339               repeated_##LOWERCASE##_value->Get(i), target);                \
    340           }                                                                 \
    341           break
    342 
    343         HANDLE_TYPE(   INT32,    Int32,   int32);
    344         HANDLE_TYPE(   INT64,    Int64,   int64);
    345         HANDLE_TYPE(  UINT32,   UInt32,  uint32);
    346         HANDLE_TYPE(  UINT64,   UInt64,  uint64);
    347         HANDLE_TYPE(  SINT32,   SInt32,   int32);
    348         HANDLE_TYPE(  SINT64,   SInt64,   int64);
    349         HANDLE_TYPE( FIXED32,  Fixed32,  uint32);
    350         HANDLE_TYPE( FIXED64,  Fixed64,  uint64);
    351         HANDLE_TYPE(SFIXED32, SFixed32,   int32);
    352         HANDLE_TYPE(SFIXED64, SFixed64,   int64);
    353         HANDLE_TYPE(   FLOAT,    Float,   float);
    354         HANDLE_TYPE(  DOUBLE,   Double,  double);
    355         HANDLE_TYPE(    BOOL,     Bool,    bool);
    356         HANDLE_TYPE(    ENUM,     Enum,    enum);
    357 #undef HANDLE_TYPE
    358 
    359         case WireFormatLite::TYPE_STRING:
    360         case WireFormatLite::TYPE_BYTES:
    361         case WireFormatLite::TYPE_GROUP:
    362         case WireFormatLite::TYPE_MESSAGE:
    363           GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
    364           break;
    365       }
    366     } else {
    367       switch (real_type(type)) {
    368 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE)                        \
    369         case FieldDescriptor::TYPE_##UPPERCASE:                             \
    370           for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) {  \
    371             target = WireFormatLite::Write##CAMELCASE##ToArray(number,      \
    372               repeated_##LOWERCASE##_value->Get(i), target);                \
    373           }                                                                 \
    374           break
    375 
    376         HANDLE_TYPE(   INT32,    Int32,   int32);
    377         HANDLE_TYPE(   INT64,    Int64,   int64);
    378         HANDLE_TYPE(  UINT32,   UInt32,  uint32);
    379         HANDLE_TYPE(  UINT64,   UInt64,  uint64);
    380         HANDLE_TYPE(  SINT32,   SInt32,   int32);
    381         HANDLE_TYPE(  SINT64,   SInt64,   int64);
    382         HANDLE_TYPE( FIXED32,  Fixed32,  uint32);
    383         HANDLE_TYPE( FIXED64,  Fixed64,  uint64);
    384         HANDLE_TYPE(SFIXED32, SFixed32,   int32);
    385         HANDLE_TYPE(SFIXED64, SFixed64,   int64);
    386         HANDLE_TYPE(   FLOAT,    Float,   float);
    387         HANDLE_TYPE(  DOUBLE,   Double,  double);
    388         HANDLE_TYPE(    BOOL,     Bool,    bool);
    389         HANDLE_TYPE(  STRING,   String,  string);
    390         HANDLE_TYPE(   BYTES,    Bytes,  string);
    391         HANDLE_TYPE(    ENUM,     Enum,    enum);
    392         HANDLE_TYPE(   GROUP,    Group, message);
    393         HANDLE_TYPE( MESSAGE,  Message, message);
    394 #undef HANDLE_TYPE
    395       }
    396     }
    397   } else if (!is_cleared) {
    398     switch (real_type(type)) {
    399 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE)                 \
    400       case FieldDescriptor::TYPE_##UPPERCASE:                    \
    401         target = WireFormatLite::Write##CAMELCASE##ToArray(      \
    402             number, VALUE, target); \
    403         break
    404 
    405       HANDLE_TYPE(   INT32,    Int32,    int32_value);
    406       HANDLE_TYPE(   INT64,    Int64,    int64_value);
    407       HANDLE_TYPE(  UINT32,   UInt32,   uint32_value);
    408       HANDLE_TYPE(  UINT64,   UInt64,   uint64_value);
    409       HANDLE_TYPE(  SINT32,   SInt32,    int32_value);
    410       HANDLE_TYPE(  SINT64,   SInt64,    int64_value);
    411       HANDLE_TYPE( FIXED32,  Fixed32,   uint32_value);
    412       HANDLE_TYPE( FIXED64,  Fixed64,   uint64_value);
    413       HANDLE_TYPE(SFIXED32, SFixed32,    int32_value);
    414       HANDLE_TYPE(SFIXED64, SFixed64,    int64_value);
    415       HANDLE_TYPE(   FLOAT,    Float,    float_value);
    416       HANDLE_TYPE(  DOUBLE,   Double,   double_value);
    417       HANDLE_TYPE(    BOOL,     Bool,     bool_value);
    418       HANDLE_TYPE(  STRING,   String,  *string_value);
    419       HANDLE_TYPE(   BYTES,    Bytes,  *string_value);
    420       HANDLE_TYPE(    ENUM,     Enum,     enum_value);
    421       HANDLE_TYPE(   GROUP,    Group, *message_value);
    422       HANDLE_TYPE( MESSAGE,  Message, *message_value);
    423 #undef HANDLE_TYPE
    424     }
    425   }
    426   return target;
    427 }
    428 
    429 uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray(
    430     int number,
    431     uint8* target) const {
    432   if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
    433     // Not a valid MessageSet extension, but serialize it the normal way.
    434     GOOGLE_LOG(WARNING) << "Invalid message set extension.";
    435     return SerializeFieldWithCachedSizesToArray(number, target);
    436   }
    437 
    438   if (is_cleared) return target;
    439 
    440   // Start group.
    441   target = io::CodedOutputStream::WriteTagToArray(
    442       WireFormatLite::kMessageSetItemStartTag, target);
    443   // Write type ID.
    444   target = WireFormatLite::WriteUInt32ToArray(
    445       WireFormatLite::kMessageSetTypeIdNumber, number, target);
    446   // Write message.
    447   target = WireFormatLite::WriteMessageToArray(
    448       WireFormatLite::kMessageSetMessageNumber, *message_value, target);
    449   // End group.
    450   target = io::CodedOutputStream::WriteTagToArray(
    451       WireFormatLite::kMessageSetItemEndTag, target);
    452   return target;
    453 }
    454 
    455 }  // namespace internal
    456 }  // namespace protobuf
    457 }  // namespace google
    458