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_H__
     32 #define GOOGLE_PROTOBUF_MAP_ENTRY_H__
     33 
     34 #include <google/protobuf/generated_message_reflection.h>
     35 #include <google/protobuf/map_entry_lite.h>
     36 #include <google/protobuf/map_type_handler.h>
     37 #include <google/protobuf/metadata.h>
     38 #include <google/protobuf/reflection_ops.h>
     39 #include <google/protobuf/unknown_field_set.h>
     40 #include <google/protobuf/wire_format_lite_inl.h>
     41 
     42 namespace google {
     43 namespace protobuf {
     44 class Arena;
     45 namespace internal {
     46 template <typename Key, typename Value,
     47           WireFormatLite::FieldType kKeyFieldType,
     48           WireFormatLite::FieldType kValueFieldType,
     49           int default_enum_value>
     50 class MapField;
     51 }
     52 }
     53 
     54 namespace protobuf {
     55 namespace internal {
     56 
     57 // Register all MapEntry default instances so we can delete them in
     58 // ShutdownProtobufLibrary().
     59 void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(
     60     MessageLite* default_instance);
     61 
     62 // This is the common base class for MapEntry. It is used by MapFieldBase in
     63 // reflection api, in which the static type of key and value is unknown.
     64 class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
     65  public:
     66   ::google::protobuf::Metadata GetMetadata() const {
     67     ::google::protobuf::Metadata metadata;
     68     metadata.descriptor = descriptor_;
     69     metadata.reflection = reflection_;
     70     return metadata;
     71   }
     72 
     73  protected:
     74   MapEntryBase() : descriptor_(NULL), reflection_(NULL) {  }
     75   virtual ~MapEntryBase() {}
     76 
     77   const Descriptor* descriptor_;
     78   const Reflection* reflection_;
     79 };
     80 
     81 // MapEntry is the returned google::protobuf::Message when calling AddMessage of
     82 // google::protobuf::Reflection. In order to let it work with generated message
     83 // reflection, its in-memory type is the same as generated message with the same
     84 // fields. However, in order to decide the in-memory type of key/value, we need
     85 // to know both their cpp type in generated api and proto type. In
     86 // implmentation, all in-memory types have related wire format functions to
     87 // support except ArenaStringPtr. Therefore, we need to define another type with
     88 // supporting wire format functions. Since this type is only used as return type
     89 // of MapEntry accessors, it's named MapEntry accessor type.
     90 //
     91 // cpp type:               the type visible to users in public API.
     92 // proto type:             WireFormatLite::FieldType of the field.
     93 // in-memory type:         type of the data member used to stored this field.
     94 // MapEntry accessor type: type used in MapEntry getters/mutators to access the
     95 //                         field.
     96 //
     97 // cpp type | proto type  | in-memory type | MapEntry accessor type
     98 // int32      TYPE_INT32    int32            int32
     99 // int32      TYPE_FIXED32  int32            int32
    100 // string     TYPE_STRING   ArenaStringPtr   string
    101 // FooEnum    TYPE_ENUM     int              int
    102 // FooMessage TYPE_MESSAGE  FooMessage*      FooMessage
    103 //
    104 // The in-memory types of primitive types can be inferred from its proto type,
    105 // while we need to explicitly specify the cpp type if proto type is
    106 // TYPE_MESSAGE to infer the in-memory type.  Moreover, default_enum_value is
    107 // used to initialize enum field in proto2.
    108 template <typename Key, typename Value,
    109           WireFormatLite::FieldType kKeyFieldType,
    110           WireFormatLite::FieldType kValueFieldType,
    111           int default_enum_value>
    112 class MapEntry : public MapEntryBase {
    113   // Provide utilities to parse/serialize key/value.  Provide utilities to
    114   // manipulate internal stored type.
    115   typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
    116   typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
    117 
    118   // Enum type cannot be used for MapTypeHandler::Read. Define a type
    119   // which will replace Enum with int.
    120   typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
    121   typedef typename ValueTypeHandler::MapEntryAccessorType
    122       ValueMapEntryAccessorType;
    123 
    124   // Abbreviation for MapEntry
    125   typedef typename google::protobuf::internal::MapEntry<
    126       Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> EntryType;
    127 
    128   // Abbreviation for MapEntryLite
    129   typedef typename google::protobuf::internal::MapEntryLite<
    130       Key, Value, kKeyFieldType, kValueFieldType, default_enum_value>
    131       EntryLiteType;
    132 
    133  public:
    134   ~MapEntry() {
    135     if (this == default_instance_) {
    136       delete reflection_;
    137     }
    138   }
    139 
    140   // accessors ======================================================
    141 
    142   virtual inline const KeyMapEntryAccessorType& key() const {
    143     return entry_lite_.key();
    144   }
    145   inline KeyMapEntryAccessorType* mutable_key() {
    146     return entry_lite_.mutable_key();
    147   }
    148   virtual inline const ValueMapEntryAccessorType& value() const {
    149     return entry_lite_.value();
    150   }
    151   inline ValueMapEntryAccessorType* mutable_value() {
    152     return entry_lite_.mutable_value();
    153   }
    154 
    155   // implements Message =============================================
    156 
    157   bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
    158     return entry_lite_.MergePartialFromCodedStream(input);
    159   }
    160 
    161   int ByteSize() const {
    162     return entry_lite_.ByteSize();
    163   }
    164 
    165   void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
    166     entry_lite_.SerializeWithCachedSizes(output);
    167   }
    168 
    169   ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
    170     return entry_lite_.SerializeWithCachedSizesToArray(output);
    171   }
    172 
    173   int GetCachedSize() const {
    174     return entry_lite_.GetCachedSize();
    175   }
    176 
    177   bool IsInitialized() const {
    178     return entry_lite_.IsInitialized();
    179   }
    180 
    181   Message* New() const {
    182     MapEntry* entry = new MapEntry;
    183     entry->descriptor_ = descriptor_;
    184     entry->reflection_ = reflection_;
    185     entry->set_default_instance(default_instance_);
    186     return entry;
    187   }
    188 
    189   Message* New(Arena* arena) const {
    190     MapEntry* entry = Arena::CreateMessage<MapEntry>(arena);
    191     entry->descriptor_ = descriptor_;
    192     entry->reflection_ = reflection_;
    193     entry->set_default_instance(default_instance_);
    194     return entry;
    195   }
    196 
    197   int SpaceUsed() const {
    198     int size = sizeof(MapEntry);
    199     size += entry_lite_.SpaceUsed();
    200     return size;
    201   }
    202 
    203   void CopyFrom(const ::google::protobuf::Message& from) {
    204     Clear();
    205     MergeFrom(from);
    206   }
    207 
    208   void MergeFrom(const ::google::protobuf::Message& from) {
    209     GOOGLE_CHECK_NE(&from, this);
    210     const MapEntry* source = dynamic_cast_if_available<const MapEntry*>(&from);
    211     if (source == NULL) {
    212       ReflectionOps::Merge(from, this);
    213     } else {
    214       MergeFrom(*source);
    215     }
    216   }
    217 
    218   void CopyFrom(const MapEntry& from) {
    219     Clear();
    220     MergeFrom(from);
    221   }
    222 
    223   void MergeFrom(const MapEntry& from) {
    224     entry_lite_.MergeFrom(from.entry_lite_);
    225   }
    226 
    227   void Clear() {
    228     entry_lite_.Clear();
    229   }
    230 
    231   void InitAsDefaultInstance() {
    232     entry_lite_.InitAsDefaultInstance();
    233   }
    234 
    235   Arena* GetArena() const {
    236     return entry_lite_.GetArena();
    237   }
    238 
    239   // Create default MapEntry instance for given descriptor. Descriptor has to be
    240   // given when creating default MapEntry instance because different map field
    241   // may have the same type and MapEntry class. The given descriptor is needed
    242   // to distinguish instances of the same MapEntry class.
    243   static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) {
    244     MapEntry* entry = new MapEntry;
    245     const Reflection* reflection = new GeneratedMessageReflection(
    246         descriptor, entry, offsets_,
    247         GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_),
    248         GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
    249         DescriptorPool::generated_pool(),
    250         ::google::protobuf::MessageFactory::generated_factory(),
    251         sizeof(MapEntry),
    252         GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _internal_metadata_));
    253     entry->descriptor_ = descriptor;
    254     entry->reflection_ = reflection;
    255     entry->set_default_instance(entry);
    256     entry->InitAsDefaultInstance();
    257     RegisterMapEntryDefaultInstance(entry);
    258     return entry;
    259   }
    260 
    261  private:
    262   MapEntry()
    263       : _internal_metadata_(NULL), default_instance_(NULL), entry_lite_() {}
    264 
    265   explicit MapEntry(Arena* arena)
    266       : _internal_metadata_(arena),
    267         default_instance_(NULL),
    268         entry_lite_(arena) {}
    269 
    270   inline Arena* GetArenaNoVirtual() const {
    271     return entry_lite_.GetArenaNoVirtual();
    272   }
    273 
    274   void set_default_instance(MapEntry* default_instance) {
    275     default_instance_ = default_instance;
    276     entry_lite_.set_default_instance(&default_instance->entry_lite_);
    277   }
    278 
    279   static int offsets_[2];
    280   UnknownFieldSet _unknown_fields_;
    281   InternalMetadataWithArena _internal_metadata_;
    282   MapEntry* default_instance_;
    283   EntryLiteType entry_lite_;
    284 
    285   friend class ::google::protobuf::Arena;
    286   typedef void InternalArenaConstructable_;
    287   typedef void DestructorSkippable_;
    288   template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
    289             WireFormatLite::FieldType, int default_enum>
    290   friend class internal::MapField;
    291   friend class internal::GeneratedMessageReflection;
    292 
    293   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
    294 };
    295 
    296 template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
    297           WireFormatLite::FieldType kValueFieldType, int default_enum_value>
    298 int MapEntry<Key, Value, kKeyFieldType, kValueFieldType,
    299              default_enum_value>::offsets_[2] = {
    300     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_),
    301     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_),
    302 };
    303 
    304 }  // namespace internal
    305 }  // namespace protobuf
    306 
    307 }  // namespace google
    308 #endif  // GOOGLE_PROTOBUF_MAP_ENTRY_H__
    309