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 42namespace google { 43namespace protobuf { 44class Arena; 45namespace internal { 46template <typename Key, typename Value, 47 WireFormatLite::FieldType kKeyFieldType, 48 WireFormatLite::FieldType kValueFieldType, 49 int default_enum_value> 50class MapField; 51} 52} 53 54namespace protobuf { 55namespace internal { 56 57// Register all MapEntry default instances so we can delete them in 58// ShutdownProtobufLibrary(). 59void 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. 64class 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. 108template <typename Key, typename Value, 109 WireFormatLite::FieldType kKeyFieldType, 110 WireFormatLite::FieldType kValueFieldType, 111 int default_enum_value> 112class 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 296template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType, 297 WireFormatLite::FieldType kValueFieldType, int default_enum_value> 298int 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