Home | History | Annotate | Download | only in protobuf
      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 #ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
     32 #define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
     33 
     34 #include <google/protobuf/map_type_handler.h>
     35 #include <google/protobuf/wire_format_lite_inl.h>
     36 
     37 namespace google {
     38 namespace protobuf {
     39 class Arena;
     40 namespace internal {
     41 template <typename Key, typename Value,
     42           WireFormatLite::FieldType kKeyFieldType,
     43           WireFormatLite::FieldType kValueFieldType,
     44           int default_enum_value>
     45 class MapEntry;
     46 template <typename Key, typename Value,
     47           WireFormatLite::FieldType kKeyFieldType,
     48           WireFormatLite::FieldType kValueFieldType,
     49           int default_enum_value>
     50 class MapFieldLite;
     51 }  // namespace internal
     52 }  // namespace protobuf
     53 
     54 namespace protobuf {
     55 namespace internal {
     56 
     57 // MapEntryLite is used to implement parsing and serialization of map for lite
     58 // runtime.
     59 template <typename Key, typename Value,
     60           WireFormatLite::FieldType kKeyFieldType,
     61           WireFormatLite::FieldType kValueFieldType,
     62           int default_enum_value>
     63 class MapEntryLite : public MessageLite {
     64   // Provide utilities to parse/serialize key/value.  Provide utilities to
     65   // manipulate internal stored type.
     66   typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
     67   typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
     68 
     69   // Define internal memory layout. Strings and messages are stored as
     70   // pointers, while other types are stored as values.
     71   typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
     72   typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
     73 
     74   // Enum type cannot be used for MapTypeHandler::Read. Define a type
     75   // which will replace Enum with int.
     76   typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
     77   typedef typename ValueTypeHandler::MapEntryAccessorType
     78       ValueMapEntryAccessorType;
     79 
     80   // Constants for field number.
     81   static const int kKeyFieldNumber = 1;
     82   static const int kValueFieldNumber = 2;
     83 
     84   // Constants for field tag.
     85   static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
     86       kKeyFieldNumber, KeyTypeHandler::kWireType);
     87   static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
     88       kValueFieldNumber, ValueTypeHandler::kWireType);
     89   static const int kTagSize = 1;
     90 
     91  public:
     92   ~MapEntryLite() {
     93     if (this != default_instance_) {
     94       if (GetArenaNoVirtual() != NULL) return;
     95       KeyTypeHandler::DeleteNoArena(key_);
     96       ValueTypeHandler::DeleteNoArena(value_);
     97     }
     98   }
     99 
    100   // accessors ======================================================
    101 
    102   virtual inline const KeyMapEntryAccessorType& key() const {
    103     return KeyTypeHandler::GetExternalReference(key_);
    104   }
    105   virtual inline const ValueMapEntryAccessorType& value() const {
    106     GOOGLE_CHECK(default_instance_ != NULL);
    107     return ValueTypeHandler::DefaultIfNotInitialized(value_,
    108                                                     default_instance_->value_);
    109   }
    110   inline KeyMapEntryAccessorType* mutable_key() {
    111     set_has_key();
    112     return KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
    113   }
    114   inline ValueMapEntryAccessorType* mutable_value() {
    115     set_has_value();
    116     return ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
    117   }
    118 
    119   // implements MessageLite =========================================
    120 
    121   // MapEntryLite is for implementation only and this function isn't called
    122   // anywhere. Just provide a fake implementation here for MessageLite.
    123   string GetTypeName() const { return ""; }
    124 
    125   void CheckTypeAndMergeFrom(const MessageLite& other) {
    126     MergeFrom(*::google::protobuf::down_cast<const MapEntryLite*>(&other));
    127   }
    128 
    129   bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
    130     uint32 tag;
    131 
    132     for (;;) {
    133       // 1) corrupted data: return false;
    134       // 2) unknown field: skip without putting into unknown field set;
    135       // 3) unknown enum value: keep it in parsing. In proto2, caller should
    136       // check the value and put this entry into containing message's unknown
    137       // field set if the value is an unknown enum. In proto3, caller doesn't
    138       // need to care whether the value is unknown enum;
    139       // 4) missing key/value: missed key/value will have default value. caller
    140       // should take this entry as if key/value is set to default value.
    141       tag = input->ReadTag();
    142       switch (tag) {
    143         case kKeyTag:
    144           if (!KeyTypeHandler::Read(input, mutable_key())) {
    145             return false;
    146           }
    147           set_has_key();
    148           if (!input->ExpectTag(kValueTag)) break;
    149           GOOGLE_FALLTHROUGH_INTENDED;
    150 
    151         case kValueTag:
    152           if (!ValueTypeHandler::Read(input, mutable_value())) {
    153             return false;
    154           }
    155           set_has_value();
    156           if (input->ExpectAtEnd()) return true;
    157           break;
    158 
    159         default:
    160           if (tag == 0 ||
    161               WireFormatLite::GetTagWireType(tag) ==
    162               WireFormatLite::WIRETYPE_END_GROUP) {
    163             return true;
    164           }
    165           if (!WireFormatLite::SkipField(input, tag)) return false;
    166           break;
    167       }
    168     }
    169   }
    170 
    171   int ByteSize() const {
    172     int size = 0;
    173     size += has_key() ? kTagSize + KeyTypeHandler::ByteSize(key()) : 0;
    174     size += has_value() ? kTagSize + ValueTypeHandler::ByteSize(value()) : 0;
    175     return size;
    176   }
    177 
    178   void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
    179     KeyTypeHandler::Write(kKeyFieldNumber, key(), output);
    180     ValueTypeHandler::Write(kValueFieldNumber, value(), output);
    181   }
    182 
    183   ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
    184     output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key(), output);
    185     output = ValueTypeHandler::WriteToArray(kValueFieldNumber, value(), output);
    186     return output;
    187   }
    188 
    189   int GetCachedSize() const {
    190     int size = 0;
    191     size += has_key()
    192         ? kTagSize + KeyTypeHandler::GetCachedSize(key())
    193         : 0;
    194     size += has_value()
    195         ? kTagSize + ValueTypeHandler::GetCachedSize(
    196             value())
    197         : 0;
    198     return size;
    199   }
    200 
    201   bool IsInitialized() const { return ValueTypeHandler::IsInitialized(value_); }
    202 
    203   MessageLite* New() const {
    204     MapEntryLite* entry = new MapEntryLite;
    205     entry->default_instance_ = default_instance_;
    206     return entry;
    207   }
    208 
    209   MessageLite* New(Arena* arena) const {
    210     MapEntryLite* entry = Arena::CreateMessage<MapEntryLite>(arena);
    211     entry->default_instance_ = default_instance_;
    212     return entry;
    213   }
    214 
    215   int SpaceUsed() const {
    216     int size = sizeof(MapEntryLite);
    217     size += KeyTypeHandler::SpaceUsedInMapEntry(key_);
    218     size += ValueTypeHandler::SpaceUsedInMapEntry(value_);
    219     return size;
    220   }
    221 
    222   void MergeFrom(const MapEntryLite& from) {
    223     if (from._has_bits_[0]) {
    224       if (from.has_key()) {
    225         KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
    226         KeyTypeHandler::Merge(from.key(), &key_, GetArenaNoVirtual());
    227         set_has_key();
    228       }
    229       if (from.has_value()) {
    230         ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
    231         ValueTypeHandler::Merge(from.value(), &value_, GetArenaNoVirtual());
    232         set_has_value();
    233       }
    234     }
    235   }
    236 
    237   void Clear() {
    238     KeyTypeHandler::Clear(&key_, GetArenaNoVirtual());
    239     ValueTypeHandler::ClearMaybeByDefaultEnum(
    240         &value_, GetArenaNoVirtual(), default_enum_value);
    241     clear_has_key();
    242     clear_has_value();
    243   }
    244 
    245   void InitAsDefaultInstance() {
    246     KeyTypeHandler::AssignDefaultValue(&key_);
    247     ValueTypeHandler::AssignDefaultValue(&value_);
    248   }
    249 
    250   Arena* GetArena() const {
    251     return GetArenaNoVirtual();
    252   }
    253 
    254   // Create a MapEntryLite for given key and value from google::protobuf::Map in
    255   // serialization. This function is only called when value is enum. Enum is
    256   // treated differently because its type in MapEntry is int and its type in
    257   // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
    258   static MapEntryLite* EnumWrap(const Key& key, const Value value,
    259                                 Arena* arena) {
    260     return Arena::CreateMessage<MapEnumEntryWrapper<
    261         Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> >(
    262         arena, key, value);
    263   }
    264 
    265   // Like above, but for all the other types. This avoids value copy to create
    266   // MapEntryLite from google::protobuf::Map in serialization.
    267   static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) {
    268     return Arena::CreateMessage<MapEntryWrapper<Key, Value, kKeyFieldType,
    269                                                 kValueFieldType,
    270                                                 default_enum_value> >(
    271         arena, key, value);
    272   }
    273 
    274  protected:
    275   void set_has_key() { _has_bits_[0] |= 0x00000001u; }
    276   bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
    277   void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
    278   void set_has_value() { _has_bits_[0] |= 0x00000002u; }
    279   bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
    280   void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
    281 
    282  private:
    283   // Serializing a generated message containing map field involves serializing
    284   // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
    285   // after serialization should be the same as that of a MapEntry message
    286   // containing the same key and value inside it.  However, google::protobuf::Map doesn't
    287   // store key and value as MapEntry message, which disables us to use existing
    288   // code to serialize message. In order to use existing code to serialize
    289   // message, we need to construct a MapEntry from key-value pair. But it
    290   // involves copy of key and value to construct a MapEntry. In order to avoid
    291   // this copy in constructing a MapEntry, we need the following class which
    292   // only takes references of given key and value.
    293   template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
    294             WireFormatLite::FieldType v_wire_type, int default_enum>
    295   class MapEntryWrapper
    296       : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
    297     typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
    298     typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
    299     typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
    300 
    301    public:
    302     MapEntryWrapper(Arena* arena, const K& key, const V& value)
    303         : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
    304           key_(key),
    305           value_(value) {
    306       Base::set_has_key();
    307       Base::set_has_value();
    308     }
    309     inline const KeyMapEntryAccessorType& key() const { return key_; }
    310     inline const ValueMapEntryAccessorType& value() const { return value_; }
    311 
    312    private:
    313     const Key& key_;
    314     const Value& value_;
    315 
    316     friend class ::google::protobuf::Arena;
    317     typedef void InternalArenaConstructable_;
    318     typedef void DestructorSkippable_;
    319   };
    320 
    321   // Like above, but for enum value only, which stores value instead of
    322   // reference of value field inside. This is needed because the type of value
    323   // field in constructor is an enum, while we need to store it as an int. If we
    324   // initialize a reference to int with a reference to enum, compiler will
    325   // generate a temporary int from enum and initialize the reference to int with
    326   // the temporary.
    327   template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
    328             WireFormatLite::FieldType v_wire_type, int default_enum>
    329   class MapEnumEntryWrapper
    330       : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
    331     typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
    332     typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
    333     typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
    334 
    335    public:
    336     MapEnumEntryWrapper(Arena* arena, const K& key, const V& value)
    337         : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
    338           key_(key),
    339           value_(value) {
    340       Base::set_has_key();
    341       Base::set_has_value();
    342     }
    343     inline const KeyMapEntryAccessorType& key() const { return key_; }
    344     inline const ValueMapEntryAccessorType& value() const { return value_; }
    345 
    346    private:
    347     const KeyMapEntryAccessorType& key_;
    348     const ValueMapEntryAccessorType value_;
    349 
    350     friend class google::protobuf::Arena;
    351     typedef void DestructorSkippable_;
    352   };
    353 
    354   MapEntryLite() : default_instance_(NULL), arena_(NULL) {
    355     KeyTypeHandler::Initialize(&key_, NULL);
    356     ValueTypeHandler::InitializeMaybeByDefaultEnum(
    357         &value_, default_enum_value, NULL);
    358     _has_bits_[0] = 0;
    359   }
    360 
    361   explicit MapEntryLite(Arena* arena)
    362       : default_instance_(NULL), arena_(arena) {
    363     KeyTypeHandler::Initialize(&key_, arena);
    364     ValueTypeHandler::InitializeMaybeByDefaultEnum(
    365         &value_, default_enum_value, arena);
    366     _has_bits_[0] = 0;
    367   }
    368 
    369   inline Arena* GetArenaNoVirtual() const {
    370     return arena_;
    371   }
    372 
    373   void set_default_instance(MapEntryLite* default_instance) {
    374     default_instance_ = default_instance;
    375   }
    376 
    377   MapEntryLite* default_instance_;
    378 
    379   KeyOnMemory key_;
    380   ValueOnMemory value_;
    381   Arena* arena_;
    382   uint32 _has_bits_[1];
    383 
    384   friend class ::google::protobuf::Arena;
    385   typedef void InternalArenaConstructable_;
    386   typedef void DestructorSkippable_;
    387   template <typename K, typename V, WireFormatLite::FieldType,
    388             WireFormatLite::FieldType, int>
    389   friend class internal::MapEntry;
    390   template <typename K, typename V, WireFormatLite::FieldType,
    391             WireFormatLite::FieldType, int>
    392   friend class internal::MapFieldLite;
    393 
    394   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
    395 };
    396 
    397 }  // namespace internal
    398 }  // namespace protobuf
    399 
    400 }  // namespace google
    401 #endif  // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
    402