1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 #ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__ 9 #define GOOGLE_PROTOBUF_MAP_FIELD_H__ 10 11 #include <atomic> 12 #include <cstddef> 13 #include <cstdint> 14 #include <functional> 15 #include <string> 16 #include <type_traits> 17 #include <utility> 18 19 #include "absl/log/absl_check.h" 20 #include "absl/log/absl_log.h" 21 #include "absl/strings/string_view.h" 22 #include "absl/synchronization/mutex.h" 23 #include "google/protobuf/arena.h" 24 #include "google/protobuf/descriptor.h" 25 #include "google/protobuf/explicitly_constructed.h" 26 #include "google/protobuf/generated_message_reflection.h" 27 #include "google/protobuf/generated_message_util.h" 28 #include "google/protobuf/internal_visibility.h" 29 #include "google/protobuf/map.h" 30 #include "google/protobuf/map_field_lite.h" 31 #include "google/protobuf/map_type_handler.h" 32 #include "google/protobuf/message.h" 33 #include "google/protobuf/message_lite.h" 34 #include "google/protobuf/port.h" 35 #include "google/protobuf/repeated_field.h" 36 #include "google/protobuf/unknown_field_set.h" 37 38 39 // Must be included last. 40 #include "google/protobuf/port_def.inc" 41 42 #ifdef SWIG 43 #error "You cannot SWIG proto headers" 44 #endif 45 46 namespace google { 47 namespace protobuf { 48 class DynamicMessage; 49 class MapIterator; 50 51 // Microsoft compiler complains about non-virtual destructor, 52 // even when the destructor is private. 53 #ifdef _MSC_VER 54 #pragma warning(push) 55 #pragma warning(disable : 4265) 56 #endif // _MSC_VER 57 58 #define TYPE_CHECK(EXPECTEDTYPE, METHOD) \ 59 if (type() != EXPECTEDTYPE) { \ 60 ABSL_LOG(FATAL) << "Protocol Buffer map usage error:\n" \ 61 << METHOD << " type does not match\n" \ 62 << " Expected : " \ 63 << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \ 64 << " Actual : " \ 65 << FieldDescriptor::CppTypeName(type()); \ 66 } 67 68 // MapKey is an union type for representing any possible 69 // map key. 70 class PROTOBUF_EXPORT MapKey { 71 public: MapKey()72 MapKey() : type_() {} MapKey(const MapKey & other)73 MapKey(const MapKey& other) : type_() { CopyFrom(other); } 74 75 MapKey& operator=(const MapKey& other) { 76 CopyFrom(other); 77 return *this; 78 } 79 ~MapKey()80 ~MapKey() { 81 if (type_ == FieldDescriptor::CPPTYPE_STRING) { 82 val_.string_value.Destruct(); 83 } 84 } 85 type()86 FieldDescriptor::CppType type() const { 87 if (type_ == FieldDescriptor::CppType()) { 88 ABSL_LOG(FATAL) << "Protocol Buffer map usage error:\n" 89 << "MapKey::type MapKey is not initialized. " 90 << "Call set methods to initialize MapKey."; 91 } 92 return type_; 93 } 94 SetInt64Value(int64_t value)95 void SetInt64Value(int64_t value) { 96 SetType(FieldDescriptor::CPPTYPE_INT64); 97 val_.int64_value = value; 98 } SetUInt64Value(uint64_t value)99 void SetUInt64Value(uint64_t value) { 100 SetType(FieldDescriptor::CPPTYPE_UINT64); 101 val_.uint64_value = value; 102 } SetInt32Value(int32_t value)103 void SetInt32Value(int32_t value) { 104 SetType(FieldDescriptor::CPPTYPE_INT32); 105 val_.int32_value = value; 106 } SetUInt32Value(uint32_t value)107 void SetUInt32Value(uint32_t value) { 108 SetType(FieldDescriptor::CPPTYPE_UINT32); 109 val_.uint32_value = value; 110 } SetBoolValue(bool value)111 void SetBoolValue(bool value) { 112 SetType(FieldDescriptor::CPPTYPE_BOOL); 113 val_.bool_value = value; 114 } SetStringValue(absl::string_view val)115 void SetStringValue(absl::string_view val) { 116 SetType(FieldDescriptor::CPPTYPE_STRING); 117 val_.string_value.get_mutable()->assign(val.data(), val.size()); 118 } 119 GetInt64Value()120 int64_t GetInt64Value() const { 121 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value"); 122 return val_.int64_value; 123 } GetUInt64Value()124 uint64_t GetUInt64Value() const { 125 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value"); 126 return val_.uint64_value; 127 } GetInt32Value()128 int32_t GetInt32Value() const { 129 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value"); 130 return val_.int32_value; 131 } GetUInt32Value()132 uint32_t GetUInt32Value() const { 133 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value"); 134 return val_.uint32_value; 135 } GetBoolValue()136 bool GetBoolValue() const { 137 TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue"); 138 return val_.bool_value; 139 } GetStringValue()140 absl::string_view GetStringValue() const { 141 TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue"); 142 return val_.string_value.get(); 143 } 144 145 bool operator<(const MapKey& other) const { 146 if (type_ != other.type_) { 147 // We could define a total order that handles this case, but 148 // there currently no need. So, for now, fail. 149 ABSL_LOG(FATAL) << "Unsupported: type mismatch"; 150 } 151 switch (type()) { 152 case FieldDescriptor::CPPTYPE_DOUBLE: 153 case FieldDescriptor::CPPTYPE_FLOAT: 154 case FieldDescriptor::CPPTYPE_ENUM: 155 case FieldDescriptor::CPPTYPE_MESSAGE: 156 ABSL_LOG(FATAL) << "Unsupported"; 157 return false; 158 case FieldDescriptor::CPPTYPE_STRING: 159 return val_.string_value.get() < other.val_.string_value.get(); 160 case FieldDescriptor::CPPTYPE_INT64: 161 return val_.int64_value < other.val_.int64_value; 162 case FieldDescriptor::CPPTYPE_INT32: 163 return val_.int32_value < other.val_.int32_value; 164 case FieldDescriptor::CPPTYPE_UINT64: 165 return val_.uint64_value < other.val_.uint64_value; 166 case FieldDescriptor::CPPTYPE_UINT32: 167 return val_.uint32_value < other.val_.uint32_value; 168 case FieldDescriptor::CPPTYPE_BOOL: 169 return val_.bool_value < other.val_.bool_value; 170 } 171 return false; 172 } 173 174 bool operator==(const MapKey& other) const { 175 if (type_ != other.type_) { 176 // To be consistent with operator<, we don't allow this either. 177 ABSL_LOG(FATAL) << "Unsupported: type mismatch"; 178 } 179 switch (type()) { 180 case FieldDescriptor::CPPTYPE_DOUBLE: 181 case FieldDescriptor::CPPTYPE_FLOAT: 182 case FieldDescriptor::CPPTYPE_ENUM: 183 case FieldDescriptor::CPPTYPE_MESSAGE: 184 ABSL_LOG(FATAL) << "Unsupported"; 185 break; 186 case FieldDescriptor::CPPTYPE_STRING: 187 return val_.string_value.get() == other.val_.string_value.get(); 188 case FieldDescriptor::CPPTYPE_INT64: 189 return val_.int64_value == other.val_.int64_value; 190 case FieldDescriptor::CPPTYPE_INT32: 191 return val_.int32_value == other.val_.int32_value; 192 case FieldDescriptor::CPPTYPE_UINT64: 193 return val_.uint64_value == other.val_.uint64_value; 194 case FieldDescriptor::CPPTYPE_UINT32: 195 return val_.uint32_value == other.val_.uint32_value; 196 case FieldDescriptor::CPPTYPE_BOOL: 197 return val_.bool_value == other.val_.bool_value; 198 } 199 ABSL_LOG(FATAL) << "Can't get here."; 200 return false; 201 } 202 CopyFrom(const MapKey & other)203 void CopyFrom(const MapKey& other) { 204 SetType(other.type()); 205 switch (type_) { 206 case FieldDescriptor::CPPTYPE_DOUBLE: 207 case FieldDescriptor::CPPTYPE_FLOAT: 208 case FieldDescriptor::CPPTYPE_ENUM: 209 case FieldDescriptor::CPPTYPE_MESSAGE: 210 ABSL_LOG(FATAL) << "Unsupported"; 211 break; 212 case FieldDescriptor::CPPTYPE_STRING: 213 *val_.string_value.get_mutable() = other.val_.string_value.get(); 214 break; 215 case FieldDescriptor::CPPTYPE_INT64: 216 val_.int64_value = other.val_.int64_value; 217 break; 218 case FieldDescriptor::CPPTYPE_INT32: 219 val_.int32_value = other.val_.int32_value; 220 break; 221 case FieldDescriptor::CPPTYPE_UINT64: 222 val_.uint64_value = other.val_.uint64_value; 223 break; 224 case FieldDescriptor::CPPTYPE_UINT32: 225 val_.uint32_value = other.val_.uint32_value; 226 break; 227 case FieldDescriptor::CPPTYPE_BOOL: 228 val_.bool_value = other.val_.bool_value; 229 break; 230 } 231 } 232 233 private: 234 template <typename K, typename V> 235 friend class internal::TypeDefinedMapFieldBase; 236 friend class internal::MapFieldBase; 237 friend class MapIterator; 238 friend class internal::DynamicMapField; 239 240 union KeyValue { KeyValue()241 KeyValue() {} 242 internal::ExplicitlyConstructed<std::string> string_value; 243 int64_t int64_value; 244 int32_t int32_value; 245 uint64_t uint64_value; 246 uint32_t uint32_value; 247 bool bool_value; 248 } val_; 249 SetType(FieldDescriptor::CppType type)250 void SetType(FieldDescriptor::CppType type) { 251 if (type_ == type) return; 252 if (type_ == FieldDescriptor::CPPTYPE_STRING) { 253 val_.string_value.Destruct(); 254 } 255 type_ = type; 256 if (type_ == FieldDescriptor::CPPTYPE_STRING) { 257 val_.string_value.DefaultConstruct(); 258 } 259 } 260 261 // type_ is 0 or a valid FieldDescriptor::CppType. 262 // Use "CppType()" to indicate zero. 263 FieldDescriptor::CppType type_; 264 }; 265 266 namespace internal { 267 268 template <> 269 struct is_internal_map_key_type<MapKey> : std::true_type {}; 270 271 template <> 272 struct RealKeyToVariantKey<MapKey> { 273 VariantKey operator()(const MapKey& value) const; 274 }; 275 276 template <> 277 struct RealKeyToVariantKeyAlternative<MapKey> { 278 VariantKey operator()(const MapKey& value) const { 279 return RealKeyToVariantKey<MapKey>{}(value); 280 } 281 }; 282 283 } // namespace internal 284 285 namespace internal { 286 287 class ContendedMapCleanTest; 288 class GeneratedMessageReflection; 289 class MapFieldAccessor; 290 291 template <typename MessageT> 292 struct MapDynamicFieldInfo; 293 struct MapFieldTestPeer; 294 295 // This class provides access to map field using reflection, which is the same 296 // as those provided for RepeatedPtrField<Message>. It is used for internal 297 // reflection implementation only. Users should never use this directly. 298 class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse { 299 public: 300 explicit constexpr MapFieldBase(const VTable* vtable) 301 : MapFieldBaseForParse(vtable) {} 302 explicit MapFieldBase(const VTable* vtable, Arena* arena) 303 : MapFieldBaseForParse(vtable), payload_{ToTaggedPtr(arena)} {} 304 MapFieldBase(const MapFieldBase&) = delete; 305 MapFieldBase& operator=(const MapFieldBase&) = delete; 306 307 protected: 308 // "protected" stops users from deleting a `MapFieldBase *` 309 ~MapFieldBase(); 310 311 struct VTable : MapFieldBaseForParse::VTable { 312 bool (*lookup_map_value)(const MapFieldBase& map, const MapKey& map_key, 313 MapValueConstRef* val); 314 bool (*delete_map_value)(MapFieldBase& map, const MapKey& map_key); 315 void (*set_map_iterator_value)(MapIterator* map_iter); 316 bool (*insert_or_lookup_no_sync)(MapFieldBase& map, const MapKey& map_key, 317 MapValueRef* val); 318 319 void (*clear_map_no_sync)(MapFieldBase& map); 320 void (*merge_from)(MapFieldBase& map, const MapFieldBase& other); 321 void (*swap)(MapFieldBase& lhs, MapFieldBase& rhs); 322 void (*unsafe_shallow_swap)(MapFieldBase& lhs, MapFieldBase& rhs); 323 size_t (*space_used_excluding_self_nolock)(const MapFieldBase& map); 324 325 const Message* (*get_prototype)(const MapFieldBase& map); 326 }; 327 template <typename T> 328 static constexpr VTable MakeVTable() { 329 VTable out{}; 330 out.get_map = &T::GetMapImpl; 331 out.lookup_map_value = &T::LookupMapValueImpl; 332 out.delete_map_value = &T::DeleteMapValueImpl; 333 out.set_map_iterator_value = &T::SetMapIteratorValueImpl; 334 out.insert_or_lookup_no_sync = &T::InsertOrLookupMapValueNoSyncImpl; 335 out.clear_map_no_sync = &T::ClearMapNoSyncImpl; 336 out.merge_from = &T::MergeFromImpl; 337 out.swap = &T::SwapImpl; 338 out.unsafe_shallow_swap = &T::UnsafeShallowSwapImpl; 339 out.space_used_excluding_self_nolock = &T::SpaceUsedExcludingSelfNoLockImpl; 340 out.get_prototype = &T::GetPrototypeImpl; 341 return out; 342 } 343 344 public: 345 // Returns reference to internal repeated field. Data written using 346 // Map's api prior to calling this function is guarantted to be 347 // included in repeated field. 348 const RepeatedPtrFieldBase& GetRepeatedField() const; 349 350 // Like above. Returns mutable pointer to the internal repeated field. 351 RepeatedPtrFieldBase* MutableRepeatedField(); 352 353 const VTable* vtable() const { return static_cast<const VTable*>(vtable_); } 354 355 bool ContainsMapKey(const MapKey& map_key) const { 356 return LookupMapValue(map_key, static_cast<MapValueConstRef*>(nullptr)); 357 } 358 bool LookupMapValue(const MapKey& map_key, MapValueConstRef* val) const { 359 return vtable()->lookup_map_value(*this, map_key, val); 360 } 361 bool LookupMapValue(const MapKey&, MapValueRef*) const = delete; 362 363 bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val); 364 365 // Returns whether changes to the map are reflected in the repeated field. 366 bool IsRepeatedFieldValid() const; 367 // Insures operations after won't get executed before calling this. 368 bool IsMapValid() const; 369 bool DeleteMapValue(const MapKey& map_key) { 370 return vtable()->delete_map_value(*this, map_key); 371 } 372 void MergeFrom(const MapFieldBase& other) { 373 vtable()->merge_from(*this, other); 374 } 375 void Swap(MapFieldBase* other) { vtable()->swap(*this, *other); } 376 void UnsafeShallowSwap(MapFieldBase* other) { 377 vtable()->unsafe_shallow_swap(*this, *other); 378 } 379 // Sync Map with repeated field and returns the size of map. 380 int size() const; 381 void Clear(); 382 void SetMapIteratorValue(MapIterator* map_iter) const { 383 return vtable()->set_map_iterator_value(map_iter); 384 } 385 386 void MapBegin(MapIterator* map_iter) const; 387 void MapEnd(MapIterator* map_iter) const; 388 bool EqualIterator(const MapIterator& a, const MapIterator& b) const; 389 390 // Returns the number of bytes used by the repeated field, excluding 391 // sizeof(*this) 392 size_t SpaceUsedExcludingSelfLong() const; 393 394 int SpaceUsedExcludingSelf() const { 395 return internal::ToIntSize(SpaceUsedExcludingSelfLong()); 396 } 397 398 static constexpr size_t InternalGetArenaOffset(internal::InternalVisibility) { 399 return PROTOBUF_FIELD_OFFSET(MapFieldBase, payload_); 400 } 401 402 protected: 403 // Gets the size of space used by map field. 404 size_t SpaceUsedExcludingSelfNoLock() const { 405 return vtable()->space_used_excluding_self_nolock(*this); 406 } 407 408 const Message* GetPrototype() const { return vtable()->get_prototype(*this); } 409 void ClearMapNoSync() { return vtable()->clear_map_no_sync(*this); } 410 411 // Synchronizes the content in Map to RepeatedPtrField if there is any change 412 // to Map after last synchronization. 413 const RepeatedPtrFieldBase& SyncRepeatedFieldWithMap(bool for_mutation) const; 414 void SyncRepeatedFieldWithMapNoLock(); 415 416 // Synchronizes the content in RepeatedPtrField to Map if there is any change 417 // to RepeatedPtrField after last synchronization. 418 void SyncMapWithRepeatedField() const; 419 void SyncMapWithRepeatedFieldNoLock(); 420 421 static void SwapImpl(MapFieldBase& lhs, MapFieldBase& rhs); 422 static void UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs); 423 424 // Tells MapFieldBase that there is new change to Map. 425 void SetMapDirty(); 426 427 // Tells MapFieldBase that there is new change to RepeatedPtrField. 428 void SetRepeatedDirty(); 429 430 // Provides derived class the access to repeated field. 431 void* MutableRepeatedPtrField() const; 432 433 bool InsertOrLookupMapValueNoSync(const MapKey& map_key, MapValueRef* val) { 434 return vtable()->insert_or_lookup_no_sync(*this, map_key, val); 435 } 436 437 void InternalSwap(MapFieldBase* other); 438 439 // Support thread sanitizer (tsan) by making const / mutable races 440 // more apparent. If one thread calls MutableAccess() while another 441 // thread calls either ConstAccess() or MutableAccess(), on the same 442 // MapFieldBase-derived object, and there is no synchronization going 443 // on between them, tsan will alert. 444 #if defined(PROTOBUF_TSAN) 445 void ConstAccess() const { ABSL_CHECK_EQ(seq1_, seq2_); } 446 void MutableAccess() { 447 if (seq1_ & 1) { 448 seq2_ = ++seq1_; 449 } else { 450 seq1_ = ++seq2_; 451 } 452 } 453 unsigned int seq1_ = 0, seq2_ = 0; 454 #else 455 void ConstAccess() const {} 456 void MutableAccess() {} 457 #endif 458 enum State { 459 STATE_MODIFIED_MAP = 0, // map has newly added data that has not been 460 // synchronized to repeated field 461 STATE_MODIFIED_REPEATED = 1, // repeated field has newly added data that 462 // has not been synchronized to map 463 CLEAN = 2, // data in map and repeated field are same 464 }; 465 466 struct ReflectionPayload { 467 explicit ReflectionPayload(Arena* arena) : repeated_field(arena) {} 468 RepeatedPtrField<Message> repeated_field; 469 470 absl::Mutex mutex; // The thread to synchronize map and repeated 471 // field needs to get lock first; 472 std::atomic<State> state{STATE_MODIFIED_MAP}; 473 }; 474 475 Arena* arena() const { 476 auto p = payload_.load(std::memory_order_acquire); 477 if (IsPayload(p)) return ToPayload(p)->repeated_field.GetArena(); 478 return ToArena(p); 479 } 480 481 // Returns the reflection payload. Returns null if it does not exist yet. 482 ReflectionPayload* maybe_payload() const { 483 auto p = payload_.load(std::memory_order_acquire); 484 return IsPayload(p) ? ToPayload(p) : nullptr; 485 } 486 // Returns the reflection payload, and constructs one if does not exist yet. 487 ReflectionPayload& payload() const { 488 auto* p = maybe_payload(); 489 return p != nullptr ? *p : PayloadSlow(); 490 } 491 ReflectionPayload& PayloadSlow() const; 492 493 State state() const { 494 auto* p = maybe_payload(); 495 return p != nullptr ? p->state.load(std::memory_order_acquire) 496 // The default 497 : STATE_MODIFIED_MAP; 498 } 499 500 static const UntypedMapBase& GetMapImpl(const MapFieldBaseForParse& map, 501 bool is_mutable); 502 503 private: 504 friend class ContendedMapCleanTest; 505 friend class GeneratedMessageReflection; 506 friend class MapFieldAccessor; 507 friend class google::protobuf::Reflection; 508 friend class google::protobuf::DynamicMessage; 509 510 // See assertion in TypeDefinedMapFieldBase::TypeDefinedMapFieldBase() 511 const UntypedMapBase& GetMapRaw() const { 512 return *reinterpret_cast<const UntypedMapBase*>(this + 1); 513 } 514 UntypedMapBase& GetMapRaw() { 515 return *reinterpret_cast<UntypedMapBase*>(this + 1); 516 } 517 518 // Virtual helper methods for MapIterator. MapIterator doesn't have the 519 // type helper for key and value. Call these help methods to deal with 520 // different types. Real helper methods are implemented in 521 // TypeDefinedMapFieldBase. 522 friend class google::protobuf::MapIterator; 523 524 // Copy the map<...>::iterator from other_iterator to 525 // this_iterator. 526 void CopyIterator(MapIterator* this_iter, const MapIterator& that_iter) const; 527 528 // IncreaseIterator() is called by operator++() of MapIterator only. 529 // It implements the ++ operator of MapIterator. 530 void IncreaseIterator(MapIterator* map_iter) const; 531 532 enum class TaggedPtr : uintptr_t {}; 533 static constexpr uintptr_t kHasPayloadBit = 1; 534 535 static ReflectionPayload* ToPayload(TaggedPtr p) { 536 ABSL_DCHECK(IsPayload(p)); 537 auto* res = reinterpret_cast<ReflectionPayload*>(static_cast<uintptr_t>(p) - 538 kHasPayloadBit); 539 PROTOBUF_ASSUME(res != nullptr); 540 return res; 541 } 542 static Arena* ToArena(TaggedPtr p) { 543 ABSL_DCHECK(!IsPayload(p)); 544 return reinterpret_cast<Arena*>(p); 545 } 546 static TaggedPtr ToTaggedPtr(ReflectionPayload* p) { 547 return static_cast<TaggedPtr>(reinterpret_cast<uintptr_t>(p) + 548 kHasPayloadBit); 549 } 550 static TaggedPtr ToTaggedPtr(Arena* p) { 551 return static_cast<TaggedPtr>(reinterpret_cast<uintptr_t>(p)); 552 } 553 static bool IsPayload(TaggedPtr p) { 554 return static_cast<uintptr_t>(p) & kHasPayloadBit; 555 } 556 557 mutable std::atomic<TaggedPtr> payload_{}; 558 }; 559 560 // This class provides common Map Reflection implementations for generated 561 // message and dynamic message. 562 template <typename Key, typename T> 563 class TypeDefinedMapFieldBase : public MapFieldBase { 564 public: 565 explicit constexpr TypeDefinedMapFieldBase(const VTable* vtable) 566 : MapFieldBase(vtable), map_() { 567 // This invariant is required by MapFieldBase to easily access the map 568 // member without paying for dynamic dispatch. It reduces code size. 569 static_assert(PROTOBUF_FIELD_OFFSET(TypeDefinedMapFieldBase, map_) == 570 sizeof(MapFieldBase), 571 ""); 572 } 573 TypeDefinedMapFieldBase(const TypeDefinedMapFieldBase&) = delete; 574 TypeDefinedMapFieldBase& operator=(const TypeDefinedMapFieldBase&) = delete; 575 576 TypeDefinedMapFieldBase(const VTable* vtable, Arena* arena) 577 : MapFieldBase(vtable, arena), map_(arena) {} 578 579 protected: 580 ~TypeDefinedMapFieldBase() { map_.~Map(); } 581 582 // Not all overrides are marked `final` here because DynamicMapField overrides 583 // them. DynamicMapField does extra memory management for the elements and 584 // needs to override the functions that create or destroy elements. 585 586 public: 587 const Map<Key, T>& GetMap() const { 588 SyncMapWithRepeatedField(); 589 return map_; 590 } 591 592 Map<Key, T>* MutableMap() { 593 SyncMapWithRepeatedField(); 594 SetMapDirty(); 595 return &map_; 596 } 597 598 static void ClearMapNoSyncImpl(MapFieldBase& map) { 599 static_cast<TypeDefinedMapFieldBase&>(map).map_.clear(); 600 } 601 602 void InternalSwap(TypeDefinedMapFieldBase* other); 603 604 static constexpr size_t InternalGetArenaOffsetAlt( 605 internal::InternalVisibility access) { 606 return PROTOBUF_FIELD_OFFSET(TypeDefinedMapFieldBase, map_) + 607 decltype(map_)::InternalGetArenaOffset(access); 608 } 609 610 protected: 611 friend struct MapFieldTestPeer; 612 613 using Iter = typename Map<Key, T>::const_iterator; 614 615 static bool DeleteMapValueImpl(MapFieldBase& map, const MapKey& map_key); 616 static bool LookupMapValueImpl(const MapFieldBase& self, 617 const MapKey& map_key, MapValueConstRef* val); 618 static void SetMapIteratorValueImpl(MapIterator* map_iter); 619 static bool InsertOrLookupMapValueNoSyncImpl(MapFieldBase& map, 620 const MapKey& map_key, 621 MapValueRef* val); 622 623 static void MergeFromImpl(MapFieldBase& base, const MapFieldBase& other); 624 static void SwapImpl(MapFieldBase& lhs, MapFieldBase& rhs); 625 static void UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs); 626 627 static size_t SpaceUsedExcludingSelfNoLockImpl(const MapFieldBase& map); 628 629 // map_ is inside an anonymous union so we can explicitly control its 630 // destruction 631 union { 632 Map<Key, T> map_; 633 }; 634 }; 635 636 // This class provides access to map field using generated api. It is used for 637 // internal generated message implementation only. Users should never use this 638 // directly. 639 template <typename Derived, typename Key, typename T, 640 WireFormatLite::FieldType kKeyFieldType_, 641 WireFormatLite::FieldType kValueFieldType_> 642 class MapField final : public TypeDefinedMapFieldBase<Key, T> { 643 // Provide utilities to parse/serialize key/value. Provide utilities to 644 // manipulate internal stored type. 645 typedef MapTypeHandler<kKeyFieldType_, Key> KeyTypeHandler; 646 typedef MapTypeHandler<kValueFieldType_, T> ValueTypeHandler; 647 648 public: 649 typedef Map<Key, T> MapType; 650 static constexpr WireFormatLite::FieldType kKeyFieldType = kKeyFieldType_; 651 static constexpr WireFormatLite::FieldType kValueFieldType = kValueFieldType_; 652 653 constexpr MapField() : MapField::TypeDefinedMapFieldBase(&kVTable) {} 654 MapField(const MapField&) = delete; 655 MapField& operator=(const MapField&) = delete; 656 ~MapField() = default; 657 658 explicit MapField(Arena* arena) 659 : TypeDefinedMapFieldBase<Key, T>(&kVTable, arena) {} 660 MapField(ArenaInitialized, Arena* arena) : MapField(arena) {} 661 MapField(InternalVisibility, Arena* arena) : MapField(arena) {} 662 MapField(InternalVisibility, Arena* arena, const MapField& from) 663 : MapField(arena) { 664 this->MergeFromImpl(*this, from); 665 } 666 667 private: 668 typedef void InternalArenaConstructable_; 669 typedef void DestructorSkippable_; 670 671 static const Message* GetPrototypeImpl(const MapFieldBase& map); 672 673 static const MapFieldBase::VTable kVTable; 674 675 friend class google::protobuf::Arena; 676 friend class MapFieldBase; 677 friend class MapFieldStateTest; // For testing, it needs raw access to impl_ 678 }; 679 680 template <typename Derived, typename Key, typename T, 681 WireFormatLite::FieldType kKeyFieldType_, 682 WireFormatLite::FieldType kValueFieldType_> 683 PROTOBUF_CONSTINIT const MapFieldBase::VTable 684 MapField<Derived, Key, T, kKeyFieldType_, kValueFieldType_>::kVTable = 685 MapField::template MakeVTable<MapField>(); 686 687 template <typename Key, typename T> 688 bool AllAreInitialized(const TypeDefinedMapFieldBase<Key, T>& field) { 689 for (const auto& p : field.GetMap()) { 690 if (!p.second.IsInitialized()) return false; 691 } 692 return true; 693 } 694 695 class PROTOBUF_EXPORT DynamicMapField final 696 : public TypeDefinedMapFieldBase<MapKey, MapValueRef> { 697 public: 698 explicit DynamicMapField(const Message* default_entry); 699 DynamicMapField(const Message* default_entry, Arena* arena); 700 DynamicMapField(const DynamicMapField&) = delete; 701 DynamicMapField& operator=(const DynamicMapField&) = delete; 702 ~DynamicMapField(); 703 704 private: 705 friend class MapFieldBase; 706 707 const Message* default_entry_; 708 709 static const VTable kVTable; 710 711 void AllocateMapValue(MapValueRef* map_val); 712 713 static void MergeFromImpl(MapFieldBase& base, const MapFieldBase& other); 714 static bool InsertOrLookupMapValueNoSyncImpl(MapFieldBase& base, 715 const MapKey& map_key, 716 MapValueRef* val); 717 static void ClearMapNoSyncImpl(MapFieldBase& base); 718 719 static void UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs) { 720 static_cast<DynamicMapField&>(lhs).Swap( 721 static_cast<DynamicMapField*>(&rhs)); 722 } 723 724 static size_t SpaceUsedExcludingSelfNoLockImpl(const MapFieldBase& map); 725 726 static const Message* GetPrototypeImpl(const MapFieldBase& map); 727 }; 728 729 } // namespace internal 730 731 // MapValueConstRef points to a map value. Users can NOT modify 732 // the map value. 733 class PROTOBUF_EXPORT MapValueConstRef { 734 public: 735 MapValueConstRef() : data_(nullptr), type_() {} 736 737 int64_t GetInt64Value() const { 738 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, 739 "MapValueConstRef::GetInt64Value"); 740 return *reinterpret_cast<int64_t*>(data_); 741 } 742 uint64_t GetUInt64Value() const { 743 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, 744 "MapValueConstRef::GetUInt64Value"); 745 return *reinterpret_cast<uint64_t*>(data_); 746 } 747 int32_t GetInt32Value() const { 748 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, 749 "MapValueConstRef::GetInt32Value"); 750 return *reinterpret_cast<int32_t*>(data_); 751 } 752 uint32_t GetUInt32Value() const { 753 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, 754 "MapValueConstRef::GetUInt32Value"); 755 return *reinterpret_cast<uint32_t*>(data_); 756 } 757 bool GetBoolValue() const { 758 TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueConstRef::GetBoolValue"); 759 return *reinterpret_cast<bool*>(data_); 760 } 761 int GetEnumValue() const { 762 TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueConstRef::GetEnumValue"); 763 return *reinterpret_cast<int*>(data_); 764 } 765 const std::string& GetStringValue() const { 766 TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, 767 "MapValueConstRef::GetStringValue"); 768 return *reinterpret_cast<std::string*>(data_); 769 } 770 float GetFloatValue() const { 771 TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, 772 "MapValueConstRef::GetFloatValue"); 773 return *reinterpret_cast<float*>(data_); 774 } 775 double GetDoubleValue() const { 776 TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, 777 "MapValueConstRef::GetDoubleValue"); 778 return *reinterpret_cast<double*>(data_); 779 } 780 781 const Message& GetMessageValue() const { 782 TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, 783 "MapValueConstRef::GetMessageValue"); 784 return *reinterpret_cast<Message*>(data_); 785 } 786 787 FieldDescriptor::CppType type() const { 788 if (type_ == FieldDescriptor::CppType() || data_ == nullptr) { 789 ABSL_LOG(FATAL) 790 << "Protocol Buffer map usage error:\n" 791 << "MapValueConstRef::type MapValueConstRef is not initialized."; 792 } 793 return type_; 794 } 795 796 protected: 797 // data_ point to a map value. MapValueConstRef does not 798 // own this value. 799 void* data_; 800 // type_ is 0 or a valid FieldDescriptor::CppType. 801 // Use "CppType()" to indicate zero. 802 FieldDescriptor::CppType type_; 803 804 private: 805 template <typename Derived, typename K, typename V, 806 internal::WireFormatLite::FieldType key_wire_type, 807 internal::WireFormatLite::FieldType value_wire_type> 808 friend class internal::MapField; 809 template <typename K, typename V> 810 friend class internal::TypeDefinedMapFieldBase; 811 friend class google::protobuf::MapIterator; 812 friend class Reflection; 813 friend class internal::DynamicMapField; 814 friend class internal::MapFieldBase; 815 816 void SetValueOrCopy(const void* val) { SetValue(val); } 817 void SetValueOrCopy(const MapValueConstRef* val) { CopyFrom(*val); } 818 819 void SetType(FieldDescriptor::CppType type) { type_ = type; } 820 void SetValue(const void* val) { data_ = const_cast<void*>(val); } 821 void CopyFrom(const MapValueConstRef& other) { 822 type_ = other.type_; 823 data_ = other.data_; 824 } 825 }; 826 827 // MapValueRef points to a map value. Users are able to modify 828 // the map value. 829 class PROTOBUF_EXPORT MapValueRef final : public MapValueConstRef { 830 public: 831 MapValueRef() = default; 832 833 void SetInt64Value(int64_t value) { 834 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapValueRef::SetInt64Value"); 835 *reinterpret_cast<int64_t*>(data_) = value; 836 } 837 void SetUInt64Value(uint64_t value) { 838 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapValueRef::SetUInt64Value"); 839 *reinterpret_cast<uint64_t*>(data_) = value; 840 } 841 void SetInt32Value(int32_t value) { 842 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapValueRef::SetInt32Value"); 843 *reinterpret_cast<int32_t*>(data_) = value; 844 } 845 void SetUInt32Value(uint32_t value) { 846 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapValueRef::SetUInt32Value"); 847 *reinterpret_cast<uint32_t*>(data_) = value; 848 } 849 void SetBoolValue(bool value) { 850 TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueRef::SetBoolValue"); 851 *reinterpret_cast<bool*>(data_) = value; 852 } 853 // TODO - Checks that enum is member. 854 void SetEnumValue(int value) { 855 TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueRef::SetEnumValue"); 856 *reinterpret_cast<int*>(data_) = value; 857 } 858 void SetStringValue(const std::string& value) { 859 TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapValueRef::SetStringValue"); 860 *reinterpret_cast<std::string*>(data_) = value; 861 } 862 void SetFloatValue(float value) { 863 TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, "MapValueRef::SetFloatValue"); 864 *reinterpret_cast<float*>(data_) = value; 865 } 866 void SetDoubleValue(double value) { 867 TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, "MapValueRef::SetDoubleValue"); 868 *reinterpret_cast<double*>(data_) = value; 869 } 870 871 Message* MutableMessageValue() { 872 TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, 873 "MapValueRef::MutableMessageValue"); 874 return reinterpret_cast<Message*>(data_); 875 } 876 877 private: 878 friend class internal::DynamicMapField; 879 880 // Only used in DynamicMapField 881 void DeleteData() { 882 switch (type_) { 883 #define HANDLE_TYPE(CPPTYPE, TYPE) \ 884 case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ 885 delete reinterpret_cast<TYPE*>(data_); \ 886 break; \ 887 } 888 HANDLE_TYPE(INT32, int32_t); 889 HANDLE_TYPE(INT64, int64_t); 890 HANDLE_TYPE(UINT32, uint32_t); 891 HANDLE_TYPE(UINT64, uint64_t); 892 HANDLE_TYPE(DOUBLE, double); 893 HANDLE_TYPE(FLOAT, float); 894 HANDLE_TYPE(BOOL, bool); 895 HANDLE_TYPE(STRING, std::string); 896 HANDLE_TYPE(ENUM, int32_t); 897 HANDLE_TYPE(MESSAGE, Message); 898 #undef HANDLE_TYPE 899 } 900 } 901 }; 902 903 #undef TYPE_CHECK 904 905 class PROTOBUF_EXPORT MapIterator { 906 public: 907 MapIterator(Message* message, const FieldDescriptor* field) { 908 const Reflection* reflection = message->GetReflection(); 909 map_ = reflection->MutableMapData(message, field); 910 key_.SetType(field->message_type()->map_key()->cpp_type()); 911 value_.SetType(field->message_type()->map_value()->cpp_type()); 912 } 913 MapIterator(const MapIterator& other) { *this = other; } 914 MapIterator& operator=(const MapIterator& other) { 915 map_ = other.map_; 916 map_->CopyIterator(this, other); 917 return *this; 918 } 919 friend bool operator==(const MapIterator& a, const MapIterator& b) { 920 return a.map_->EqualIterator(a, b); 921 } 922 friend bool operator!=(const MapIterator& a, const MapIterator& b) { 923 return !a.map_->EqualIterator(a, b); 924 } 925 MapIterator& operator++() { 926 map_->IncreaseIterator(this); 927 return *this; 928 } 929 MapIterator operator++(int) { 930 // iter_ is copied from Map<...>::iterator, no need to 931 // copy from its self again. Use the same implementation 932 // with operator++() 933 map_->IncreaseIterator(this); 934 return *this; 935 } 936 const MapKey& GetKey() { return key_; } 937 const MapValueRef& GetValueRef() { return value_; } 938 MapValueRef* MutableValueRef() { 939 map_->SetMapDirty(); 940 return &value_; 941 } 942 943 private: 944 template <typename Key, typename T> 945 friend class internal::TypeDefinedMapFieldBase; 946 friend class internal::DynamicMapField; 947 template <typename Derived, typename Key, typename T, 948 internal::WireFormatLite::FieldType kKeyFieldType, 949 internal::WireFormatLite::FieldType kValueFieldType> 950 friend class internal::MapField; 951 friend class internal::MapFieldBase; 952 template <typename MessageT> 953 friend struct internal::MapDynamicFieldInfo; 954 955 MapIterator(internal::MapFieldBase* map, const Descriptor* descriptor) { 956 map_ = map; 957 key_.SetType(descriptor->map_key()->cpp_type()); 958 value_.SetType(descriptor->map_value()->cpp_type()); 959 } 960 961 internal::UntypedMapIterator iter_; 962 // Point to a MapField to call helper methods implemented in MapField. 963 // MapIterator does not own this object. 964 internal::MapFieldBase* map_; 965 MapKey key_; 966 MapValueRef value_; 967 }; 968 969 namespace internal { 970 template <> 971 struct is_internal_map_value_type<class MapValueConstRef> : std::true_type {}; 972 template <> 973 struct is_internal_map_value_type<class MapValueRef> : std::true_type {}; 974 } // namespace internal 975 976 } // namespace protobuf 977 } // namespace google 978 979 #ifdef _MSC_VER 980 #pragma warning(pop) // restore warning C4265 981 #endif // _MSC_VER 982 983 #include "google/protobuf/port_undef.inc" 984 985 #endif // GOOGLE_PROTOBUF_MAP_FIELD_H__ 986