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 // implementation, 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 InternalSerializeWithCachedSizesToArray(bool deterministic,::google::protobuf::uint8 * output)169 ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(bool deterministic, 170 ::google::protobuf::uint8* output) const { 171 return entry_lite_.InternalSerializeWithCachedSizesToArray(deterministic, 172 output); 173 } 174 GetCachedSize()175 int GetCachedSize() const { 176 return entry_lite_.GetCachedSize(); 177 } 178 IsInitialized()179 bool IsInitialized() const { 180 return entry_lite_.IsInitialized(); 181 } 182 New()183 Message* New() const { 184 MapEntry* entry = new MapEntry; 185 entry->descriptor_ = descriptor_; 186 entry->reflection_ = reflection_; 187 entry->set_default_instance(default_instance_); 188 return entry; 189 } 190 New(Arena * arena)191 Message* New(Arena* arena) const { 192 MapEntry* entry = Arena::CreateMessage<MapEntry>(arena); 193 entry->descriptor_ = descriptor_; 194 entry->reflection_ = reflection_; 195 entry->set_default_instance(default_instance_); 196 return entry; 197 } 198 SpaceUsed()199 int SpaceUsed() const { 200 int size = sizeof(MapEntry); 201 size += entry_lite_.SpaceUsed(); 202 return size; 203 } 204 CopyFrom(const::google::protobuf::Message & from)205 void CopyFrom(const ::google::protobuf::Message& from) { 206 Clear(); 207 MergeFrom(from); 208 } 209 MergeFrom(const::google::protobuf::Message & from)210 void MergeFrom(const ::google::protobuf::Message& from) { 211 GOOGLE_CHECK_NE(&from, this); 212 const MapEntry* source = dynamic_cast_if_available<const MapEntry*>(&from); 213 if (source == NULL) { 214 ReflectionOps::Merge(from, this); 215 } else { 216 MergeFrom(*source); 217 } 218 } 219 CopyFrom(const MapEntry & from)220 void CopyFrom(const MapEntry& from) { 221 Clear(); 222 MergeFrom(from); 223 } 224 MergeFrom(const MapEntry & from)225 void MergeFrom(const MapEntry& from) { 226 entry_lite_.MergeFrom(from.entry_lite_); 227 } 228 Clear()229 void Clear() { 230 entry_lite_.Clear(); 231 } 232 InitAsDefaultInstance()233 void InitAsDefaultInstance() { 234 entry_lite_.InitAsDefaultInstance(); 235 } 236 GetArena()237 Arena* GetArena() const { 238 return entry_lite_.GetArena(); 239 } 240 241 // Create default MapEntry instance for given descriptor. Descriptor has to be 242 // given when creating default MapEntry instance because different map field 243 // may have the same type and MapEntry class. The given descriptor is needed 244 // to distinguish instances of the same MapEntry class. CreateDefaultInstance(const Descriptor * descriptor)245 static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) { 246 MapEntry* entry = new MapEntry; 247 const Reflection* reflection = new GeneratedMessageReflection( 248 descriptor, entry, offsets_, 249 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_), 250 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1, 251 DescriptorPool::generated_pool(), 252 ::google::protobuf::MessageFactory::generated_factory(), 253 sizeof(MapEntry), 254 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _internal_metadata_)); 255 entry->descriptor_ = descriptor; 256 entry->reflection_ = reflection; 257 entry->set_default_instance(entry); 258 entry->InitAsDefaultInstance(); 259 RegisterMapEntryDefaultInstance(entry); 260 return entry; 261 } 262 263 private: MapEntry()264 MapEntry() 265 : _internal_metadata_(NULL), default_instance_(NULL), entry_lite_() {} 266 MapEntry(Arena * arena)267 explicit MapEntry(Arena* arena) 268 : _internal_metadata_(arena), 269 default_instance_(NULL), 270 entry_lite_(arena) {} 271 GetArenaNoVirtual()272 inline Arena* GetArenaNoVirtual() const { 273 return entry_lite_.GetArenaNoVirtual(); 274 } 275 set_default_instance(MapEntry * default_instance)276 void set_default_instance(MapEntry* default_instance) { 277 default_instance_ = default_instance; 278 entry_lite_.set_default_instance(&default_instance->entry_lite_); 279 } 280 281 static int offsets_[2]; 282 UnknownFieldSet _unknown_fields_; 283 InternalMetadataWithArena _internal_metadata_; 284 MapEntry* default_instance_; 285 EntryLiteType entry_lite_; 286 287 friend class ::google::protobuf::Arena; 288 typedef void InternalArenaConstructable_; 289 typedef void DestructorSkippable_; 290 template <typename K, typename V, WireFormatLite::FieldType k_wire_type, 291 WireFormatLite::FieldType, int default_enum> 292 friend class internal::MapField; 293 friend class internal::GeneratedMessageReflection; 294 295 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry); 296 }; 297 298 template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType, 299 WireFormatLite::FieldType kValueFieldType, int default_enum_value> 300 int MapEntry<Key, Value, kKeyFieldType, kValueFieldType, 301 default_enum_value>::offsets_[2] = { 302 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_), 303 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_), 304 }; 305 306 } // namespace internal 307 } // namespace protobuf 308 309 } // namespace google 310 #endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__ 311