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