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: GetMetadata()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: MapEntryBase()74 MapEntryBase() : descriptor_(NULL), reflection_(NULL) { } ~MapEntryBase()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: ~MapEntry()134 ~MapEntry() { 135 if (this == default_instance_) { 136 delete reflection_; 137 } 138 } 139 140 // accessors ====================================================== 141 key()142 virtual inline const KeyMapEntryAccessorType& key() const { 143 return entry_lite_.key(); 144 } mutable_key()145 inline KeyMapEntryAccessorType* mutable_key() { 146 return entry_lite_.mutable_key(); 147 } value()148 virtual inline const ValueMapEntryAccessorType& value() const { 149 return entry_lite_.value(); 150 } mutable_value()151 inline ValueMapEntryAccessorType* mutable_value() { 152 return entry_lite_.mutable_value(); 153 } 154 155 // implements Message ============================================= 156 MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream * input)157 bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) { 158 return entry_lite_.MergePartialFromCodedStream(input); 159 } 160 ByteSize()161 int ByteSize() const { 162 return entry_lite_.ByteSize(); 163 } 164 SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream * output)165 void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const { 166 entry_lite_.SerializeWithCachedSizes(output); 167 } 168 SerializeWithCachedSizesToArray(::google::protobuf::uint8 * output)169 ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { 170 return entry_lite_.SerializeWithCachedSizesToArray(output); 171 } 172 GetCachedSize()173 int GetCachedSize() const { 174 return entry_lite_.GetCachedSize(); 175 } 176 IsInitialized()177 bool IsInitialized() const { 178 return entry_lite_.IsInitialized(); 179 } 180 New()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 New(Arena * arena)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 SpaceUsed()197 int SpaceUsed() const { 198 int size = sizeof(MapEntry); 199 size += entry_lite_.SpaceUsed(); 200 return size; 201 } 202 CopyFrom(const::google::protobuf::Message & from)203 void CopyFrom(const ::google::protobuf::Message& from) { 204 Clear(); 205 MergeFrom(from); 206 } 207 MergeFrom(const::google::protobuf::Message & from)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 CopyFrom(const MapEntry & from)218 void CopyFrom(const MapEntry& from) { 219 Clear(); 220 MergeFrom(from); 221 } 222 MergeFrom(const MapEntry & from)223 void MergeFrom(const MapEntry& from) { 224 entry_lite_.MergeFrom(from.entry_lite_); 225 } 226 Clear()227 void Clear() { 228 entry_lite_.Clear(); 229 } 230 InitAsDefaultInstance()231 void InitAsDefaultInstance() { 232 entry_lite_.InitAsDefaultInstance(); 233 } 234 GetArena()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. CreateDefaultInstance(const Descriptor * descriptor)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: MapEntry()262 MapEntry() 263 : _internal_metadata_(NULL), default_instance_(NULL), entry_lite_() {} 264 MapEntry(Arena * arena)265 explicit MapEntry(Arena* arena) 266 : _internal_metadata_(arena), 267 default_instance_(NULL), 268 entry_lite_(arena) {} 269 GetArenaNoVirtual()270 inline Arena* GetArenaNoVirtual() const { 271 return entry_lite_.GetArenaNoVirtual(); 272 } 273 set_default_instance(MapEntry * default_instance)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