Reduce code bloat related to MapField:

- Move several operations from MapField/DynamicMapField into TypeDefinedMapFieldBase.
 - Change MapIterator to keep an iterator inline instead of new/delete.
 - Change RepeatedPtrField usage to always be RepeatedPtrField<Message>.

PiperOrigin-RevId: 530375616
pull/12705/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent fd33221080
commit 078644fbec
  1. 36
      src/google/protobuf/map.h
  2. 62
      src/google/protobuf/map_field.cc
  3. 153
      src/google/protobuf/map_field.h
  4. 287
      src/google/protobuf/map_field_inl.h
  5. 11
      src/google/protobuf/map_field_test.cc

@ -667,6 +667,19 @@ N MultiplyWithOverflow(N a, N b) {
#endif
}
// This struct contains the field of the iterators, but no other API.
// This allows MapIterator to allocate space for an iterator generically.
class MapIteratorPayload {
protected:
MapIteratorPayload() = default;
MapIteratorPayload(NodeBase* node, const UntypedMapBase* m,
size_t bucket_index)
: node_(node), m_(m), bucket_index_(bucket_index) {}
NodeBase* node_ = nullptr;
const UntypedMapBase* m_ = nullptr;
size_t bucket_index_ = 0;
};
// KeyMapBase is a chaining hash map with the additional feature that some
// buckets can be converted to use an ordered container. This ensures O(lg n)
// bounds on find, insert, and erase, while avoiding the overheads of ordered
@ -713,7 +726,7 @@ class KeyMapBase : public UntypedMapBase {
using Tree = internal::TreeForMap<Key>;
using TreeIterator = typename Tree::iterator;
class KeyIteratorBase {
class KeyIteratorBase : protected MapIteratorPayload {
public:
// Invariants:
// node_ is always correct. This is handy because the most common
@ -722,25 +735,26 @@ class KeyMapBase : public UntypedMapBase {
// are updated to be correct also, but those fields can become stale
// if the underlying map is modified. When those fields are needed they
// are rechecked, and updated if necessary.
KeyIteratorBase() : node_(nullptr), m_(nullptr), bucket_index_(0) {}
KeyIteratorBase() = default;
explicit KeyIteratorBase(const KeyMapBase* m) : m_(m) {
explicit KeyIteratorBase(const KeyMapBase* m) {
m_ = m;
SearchFrom(m->index_of_first_non_null_);
}
KeyIteratorBase(KeyNode* n, const KeyMapBase* m, size_type index)
: node_(n), m_(m), bucket_index_(index) {}
: MapIteratorPayload(n, m, index) {}
KeyIteratorBase(TreeIterator tree_it, const KeyMapBase* m, size_type index)
: node_(NodeFromTreeIterator(tree_it)), m_(m), bucket_index_(index) {}
: MapIteratorPayload(NodeFromTreeIterator(tree_it), m, index) {}
// Advance through buckets, looking for the first that isn't empty.
// If nothing non-empty is found then leave node_ == nullptr.
void SearchFrom(size_type start_bucket) {
ABSL_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ ||
!m_->TableEntryIsEmpty(m_->index_of_first_non_null_));
for (size_type i = start_bucket; i < m_->num_buckets_; ++i) {
TableEntryPtr entry = m_->table_[i];
ABSL_DCHECK(map().index_of_first_non_null_ == map().num_buckets_ ||
!map().TableEntryIsEmpty(map().index_of_first_non_null_));
for (size_type i = start_bucket; i < map().num_buckets_; ++i) {
TableEntryPtr entry = map().table_[i];
if (entry == TableEntryPtr{}) continue;
bucket_index_ = i;
if (PROTOBUF_PREDICT_TRUE(internal::TableEntryIsList(entry))) {
@ -773,9 +787,7 @@ class KeyMapBase : public UntypedMapBase {
}
}
KeyNode* node_;
const KeyMapBase* m_;
size_type bucket_index_;
auto& map() const { return static_cast<const KeyMapBase&>(*m_); }
};
public:

@ -201,7 +201,6 @@ DynamicMapField::DynamicMapField(const Message* default_entry)
DynamicMapField::DynamicMapField(const Message* default_entry, Arena* arena)
: TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena),
map_(arena),
default_entry_(default_entry) {}
DynamicMapField::~DynamicMapField() {
@ -214,8 +213,6 @@ DynamicMapField::~DynamicMapField() {
map_.clear();
}
int DynamicMapField::size() const { return GetMap().size(); }
void DynamicMapField::Clear() {
Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
if (arena() == nullptr) {
@ -235,12 +232,6 @@ void DynamicMapField::Clear() {
MapFieldBase::SetMapDirty();
}
bool DynamicMapField::ContainsMapKey(const MapKey& map_key) const {
const Map<MapKey, MapValueRef>& map = GetMap();
Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
return iter != map.end();
}
void DynamicMapField::AllocateMapValue(MapValueRef* map_val) {
const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value();
map_val->SetType(val_des->cpp_type());
@ -291,54 +282,6 @@ bool DynamicMapField::InsertOrLookupMapValue(const MapKey& map_key,
return false;
}
bool DynamicMapField::LookupMapValue(const MapKey& map_key,
MapValueConstRef* val) const {
const Map<MapKey, MapValueRef>& map = GetMap();
Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
if (iter == map.end()) {
return false;
}
// map_key is already in the map. Make sure (*map)[map_key] is not called.
// [] may reorder the map and iterators.
val->CopyFrom(iter->second);
return true;
}
bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
MapFieldBase::SyncMapWithRepeatedField();
Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
if (iter == map_.end()) {
return false;
}
// Set map dirty only if the delete is successful.
MapFieldBase::SetMapDirty();
if (arena() == nullptr) {
iter->second.DeleteData();
}
map_.erase(iter);
return true;
}
const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const {
MapFieldBase::SyncMapWithRepeatedField();
return map_;
}
Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() {
MapFieldBase::SyncMapWithRepeatedField();
MapFieldBase::SetMapDirty();
return &map_;
}
void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const {
Map<MapKey, MapValueRef>::const_iterator iter =
TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator(
map_iter);
if (iter == map_.end()) return;
map_iter->key_.CopyFrom(iter->first);
map_iter->value_.CopyFrom(iter->second);
}
void DynamicMapField::MergeFrom(const MapFieldBase& other) {
ABSL_DCHECK(IsMapValid() && other.IsMapValid());
Map<MapKey, MapValueRef>* map = MutableMap();
@ -405,11 +348,6 @@ void DynamicMapField::MergeFrom(const MapFieldBase& other) {
}
}
void DynamicMapField::Swap(MapFieldBase* other) {
MapFieldBase::Swap(other);
map_.swap(DownCast<DynamicMapField*>(other)->map_);
}
void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const {
const Reflection* reflection = default_entry_->GetReflection();
const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key();

@ -486,12 +486,6 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
// different types. Real helper methods are implemented in
// TypeDefinedMapFieldBase.
friend class google::protobuf::MapIterator;
// Allocate map<...>::iterator for MapIterator.
virtual void InitializeIterator(MapIterator* map_iter) const = 0;
// DeleteIterator() is called by the destructor of MapIterator only.
// It deletes map<...>::iterator for MapIterator.
virtual void DeleteIterator(MapIterator* map_iter) const = 0;
// Copy the map<...>::iterator from other_iterator to
// this_iterator.
@ -535,39 +529,81 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
template <typename Key, typename T>
class TypeDefinedMapFieldBase : public MapFieldBase {
public:
constexpr TypeDefinedMapFieldBase() {}
constexpr TypeDefinedMapFieldBase() : map_() {}
TypeDefinedMapFieldBase(const TypeDefinedMapFieldBase&) = delete;
TypeDefinedMapFieldBase& operator=(const TypeDefinedMapFieldBase&) = delete;
explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {}
explicit TypeDefinedMapFieldBase(Arena* arena)
: MapFieldBase(arena), map_(arena) {}
TypeDefinedMapFieldBase(ArenaInitialized, Arena* arena)
: TypeDefinedMapFieldBase(arena) {}
protected:
~TypeDefinedMapFieldBase() {}
~TypeDefinedMapFieldBase() { map_.~Map(); }
// Not all overrides are marked `final` here because DynamicMapField overrides
// them. DynamicMapField does extra memory management for the elements and
// needs to override the functions that create or destroy elements.
public:
void MapBegin(MapIterator* map_iter) const final;
void MapEnd(MapIterator* map_iter) const final;
bool EqualIterator(const MapIterator& a, const MapIterator& b) const final;
virtual const Map<Key, T>& GetMap() const = 0;
// This overrides the base's method to specialize the signature via
// covariance, but we do not yet provide an implementation here, so `= 0`.
Map<Key, T>* MutableMap() override = 0;
const Map<Key, T>& GetMap() const {
SyncMapWithRepeatedField();
return map_;
}
Map<Key, T>* MutableMap() override final {
SyncMapWithRepeatedField();
SetMapDirty();
return &map_;
}
void Clear() override {
if (auto* p = maybe_payload()) {
p->repeated_field.Clear();
}
MutableMap()->clear();
// Data in map and repeated field are both empty, but we can't set status
// CLEAN. Because clear is a generated API, we cannot invalidate previous
// reference to map.
SetMapDirty();
}
int size() const final { return GetMap().size(); }
void InternalSwap(TypeDefinedMapFieldBase* other);
void Swap(MapFieldBase* other) final;
void UnsafeShallowSwap(MapFieldBase* other) override;
size_t SpaceUsedExcludingSelfNoLock() const override;
void MergeFrom(const MapFieldBase& other) override;
protected:
typename Map<Key, T>::const_iterator& InternalGetIterator(
const MapIterator* map_iter) const;
using Iter = typename Map<Key, T>::const_iterator;
static const Iter& InternalGetIterator(const MapIterator* map_iter);
static Iter& InternalGetIterator(MapIterator* map_iter);
// map_ is inside an anonymous union so we can explicitly control its
// destruction
union {
Map<Key, T> map_;
};
private:
void InitializeIterator(MapIterator* map_iter) const final;
void DeleteIterator(MapIterator* map_iter) const final;
void CopyIterator(MapIterator* this_iteratorm,
const MapIterator& that_iterator) const final;
void IncreaseIterator(MapIterator* map_iter) const final;
virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
void SetMapIteratorValue(MapIterator* map_iter) const;
bool ContainsMapKey(const MapKey& map_key) const final;
bool LookupMapValue(const MapKey& map_key, MapValueConstRef* val) const final;
bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
bool DeleteMapValue(const MapKey& map_key) final;
bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override;
};
// This class provides access to map field using generated api. It is used for
@ -601,69 +637,40 @@ class MapField final : public TypeDefinedMapFieldBase<Key, T> {
static constexpr WireFormatLite::FieldType kKeyFieldType = kKeyFieldType_;
static constexpr WireFormatLite::FieldType kValueFieldType = kValueFieldType_;
constexpr MapField() : impl_() {}
constexpr MapField() {}
MapField(const MapField&) = delete;
MapField& operator=(const MapField&) = delete;
~MapField() {}
explicit MapField(Arena* arena)
: TypeDefinedMapFieldBase<Key, T>(arena), impl_(arena) {}
explicit MapField(Arena* arena) : TypeDefinedMapFieldBase<Key, T>(arena) {}
MapField(ArenaInitialized, Arena* arena) : MapField(arena) {}
// TODO(sbenza): Move these up to TypeDefinedMapFieldBase where possible.
// Implement MapFieldBase
bool ContainsMapKey(const MapKey& map_key) const final;
bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) final;
bool LookupMapValue(const MapKey& map_key, MapValueConstRef* val) const final;
bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
bool DeleteMapValue(const MapKey& map_key) final;
const Map<Key, T>& GetMap() const final {
MapFieldBase::SyncMapWithRepeatedField();
return impl_.GetMap();
}
Map<Key, T>* MutableMap() final {
MapFieldBase::SyncMapWithRepeatedField();
Map<Key, T>* result = impl_.MutableMap();
MapFieldBase::SetMapDirty();
return result;
}
int size() const final;
void Clear() final;
void MergeFrom(const MapFieldBase& other) final;
void Swap(MapFieldBase* other) final;
void UnsafeShallowSwap(MapFieldBase* other) final;
void InternalSwap(MapField* other);
// Used in the implementation of parsing. Caller should take the ownership iff
// arena_ is nullptr.
EntryType* NewEntry() const { return impl_.NewEntry(); }
EntryType* NewEntry() const {
return Arena::CreateMessage<EntryType>(this->arena());
}
const char* _InternalParse(const char* ptr, ParseContext* ctx) {
return impl_._InternalParse(ptr, ctx);
typename Derived::template Parser<MapField, Map<Key, T>> parser(this);
return parser._InternalParse(ptr, ctx);
}
template <typename UnknownType>
const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
bool (*is_valid)(int), uint32_t field_num,
InternalMetadata* metadata) {
return impl_.template ParseWithEnumValidation<UnknownType>(
typename Derived::template Parser<MapField, Map<Key, T>> parser(this);
return parser.template ParseWithEnumValidation<UnknownType>(
ptr, ctx, is_valid, field_num, metadata);
}
private:
MapFieldLiteType impl_;
typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
// Implements MapFieldBase
void SyncRepeatedFieldWithMapNoLock() const final;
void SyncMapWithRepeatedFieldNoLock() const final;
size_t SpaceUsedExcludingSelfNoLock() const final;
void SetMapIteratorValue(MapIterator* map_iter) const final;
friend class google::protobuf::Arena;
friend class MapFieldStateTest; // For testing, it needs raw access to impl_
@ -695,23 +702,13 @@ class PROTOBUF_EXPORT DynamicMapField final
virtual ~DynamicMapField();
// Implement MapFieldBase
bool ContainsMapKey(const MapKey& map_key) const final;
bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) final;
bool LookupMapValue(const MapKey& map_key, MapValueConstRef* val) const final;
bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
bool DeleteMapValue(const MapKey& map_key) final;
void MergeFrom(const MapFieldBase& other) final;
void Swap(MapFieldBase* other) final;
void UnsafeShallowSwap(MapFieldBase* other) final { Swap(other); }
const Map<MapKey, MapValueRef>& GetMap() const final;
Map<MapKey, MapValueRef>* MutableMap() final;
int size() const final;
void Clear() final;
private:
Map<MapKey, MapValueRef> map_;
const Message* default_entry_;
void AllocateMapValue(MapValueRef* map_val);
@ -720,7 +717,6 @@ class PROTOBUF_EXPORT DynamicMapField final
void SyncRepeatedFieldWithMapNoLock() const final;
void SyncMapWithRepeatedFieldNoLock() const final;
size_t SpaceUsedExcludingSelfNoLock() const final;
void SetMapIteratorValue(MapIterator* map_iter) const final;
};
} // namespace internal
@ -809,6 +805,9 @@ class PROTOBUF_EXPORT MapValueConstRef {
friend class Reflection;
friend class internal::DynamicMapField;
void SetValueOrCopy(const void* val) { SetValue(val); }
void SetValueOrCopy(const MapValueConstRef* val) { CopyFrom(*val); }
void SetType(FieldDescriptor::CppType type) { type_ = type; }
void SetValue(const void* val) { data_ = const_cast<void*>(val); }
void CopyFrom(const MapValueConstRef& other) {
@ -902,14 +901,8 @@ class PROTOBUF_EXPORT MapIterator {
map_ = reflection->MutableMapData(message, field);
key_.SetType(field->message_type()->map_key()->cpp_type());
value_.SetType(field->message_type()->map_value()->cpp_type());
map_->InitializeIterator(this);
}
MapIterator(const MapIterator& other) {
map_ = other.map_;
map_->InitializeIterator(this);
map_->CopyIterator(this, other);
}
~MapIterator() { map_->DeleteIterator(this); }
MapIterator(const MapIterator& other) { *this = other; }
MapIterator& operator=(const MapIterator& other) {
map_ = other.map_;
map_->CopyIterator(this, other);
@ -948,11 +941,11 @@ class PROTOBUF_EXPORT MapIterator {
internal::WireFormatLite::FieldType kValueFieldType>
friend class internal::MapField;
// reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns
// the iterator. It is allocated by MapField<...>::InitializeIterator() called
// in constructor and deleted by MapField<...>::DeleteIterator() called in
// destructor.
void* iter_;
// This field provides the storage for Map<...>::const_iterator. We use
// reinterpret_cast to get the right type. The real iterator is trivially
// destructible/copyable, so no need to manage that.
alignas(internal::MapIteratorPayload) char map_iter_buffer_[sizeof(
internal::MapIteratorPayload)]{};
// Point to a MapField to call helper methods implemented in MapField.
// MapIterator does not own this object.
internal::MapFieldBase* map_;

@ -32,6 +32,9 @@
#define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
#include "absl/base/casts.h"
#include "google/protobuf/map.h"
@ -53,65 +56,71 @@ namespace internal {
template <typename T>
T UnwrapMapKey(const MapKey& map_key);
template <>
inline int32_t UnwrapMapKey<int32_t>(const MapKey& map_key) {
inline int32_t UnwrapMapKey(const MapKey& map_key) {
return map_key.GetInt32Value();
}
template <>
inline uint32_t UnwrapMapKey<uint32_t>(const MapKey& map_key) {
inline uint32_t UnwrapMapKey(const MapKey& map_key) {
return map_key.GetUInt32Value();
}
template <>
inline int64_t UnwrapMapKey<int64_t>(const MapKey& map_key) {
inline int64_t UnwrapMapKey(const MapKey& map_key) {
return map_key.GetInt64Value();
}
template <>
inline uint64_t UnwrapMapKey<uint64_t>(const MapKey& map_key) {
inline uint64_t UnwrapMapKey(const MapKey& map_key) {
return map_key.GetUInt64Value();
}
template <>
inline bool UnwrapMapKey<bool>(const MapKey& map_key) {
inline bool UnwrapMapKey(const MapKey& map_key) {
return map_key.GetBoolValue();
}
template <>
inline std::string UnwrapMapKey<std::string>(const MapKey& map_key) {
inline std::string UnwrapMapKey(const MapKey& map_key) {
return map_key.GetStringValue();
}
// SetMapKey template
template <typename T>
inline void SetMapKey(MapKey* map_key, const T& value);
template <>
inline void SetMapKey<int32_t>(MapKey* map_key, const int32_t& value) {
inline MapKey UnwrapMapKey(const MapKey& map_key) {
return map_key;
}
// SetMapKey
inline void SetMapKey(MapKey* map_key, int32_t value) {
map_key->SetInt32Value(value);
}
template <>
inline void SetMapKey<uint32_t>(MapKey* map_key, const uint32_t& value) {
inline void SetMapKey(MapKey* map_key, uint32_t value) {
map_key->SetUInt32Value(value);
}
template <>
inline void SetMapKey<int64_t>(MapKey* map_key, const int64_t& value) {
inline void SetMapKey(MapKey* map_key, int64_t value) {
map_key->SetInt64Value(value);
}
template <>
inline void SetMapKey<uint64_t>(MapKey* map_key, const uint64_t& value) {
inline void SetMapKey(MapKey* map_key, uint64_t value) {
map_key->SetUInt64Value(value);
}
template <>
inline void SetMapKey<bool>(MapKey* map_key, const bool& value) {
inline void SetMapKey(MapKey* map_key, bool value) {
map_key->SetBoolValue(value);
}
template <>
inline void SetMapKey<std::string>(MapKey* map_key, const std::string& value) {
inline void SetMapKey(MapKey* map_key, const std::string& value) {
map_key->SetStringValue(value);
}
inline void SetMapKey(MapKey* map_key, const MapKey& value) {
map_key->CopyFrom(value);
}
// ------------------------TypeDefinedMapFieldBase---------------
template <typename Key, typename T>
typename Map<Key, T>::const_iterator&
TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(
const MapIterator* map_iter) const {
return *reinterpret_cast<typename Map<Key, T>::const_iterator*>(
map_iter->iter_);
auto TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(
const MapIterator* map_iter) -> const Iter& {
static_assert(sizeof(Iter) == sizeof(map_iter->map_iter_buffer_), "");
static_assert(std::is_trivially_copy_constructible<Iter>::value, "");
static_assert(std::is_trivially_destructible<Iter>::value, "");
return reinterpret_cast<const Iter&>(map_iter->map_iter_buffer_);
}
template <typename Key, typename T>
auto TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(MapIterator* map_iter)
-> Iter& {
return reinterpret_cast<Iter&>(map_iter->map_iter_buffer_);
}
template <typename Key, typename T>
@ -138,20 +147,6 @@ void TypeDefinedMapFieldBase<Key, T>::IncreaseIterator(
SetMapIteratorValue(map_iter);
}
template <typename Key, typename T>
void TypeDefinedMapFieldBase<Key, T>::InitializeIterator(
MapIterator* map_iter) const {
map_iter->iter_ = new typename Map<Key, T>::const_iterator;
ABSL_CHECK(map_iter->iter_ != nullptr);
}
template <typename Key, typename T>
void TypeDefinedMapFieldBase<Key, T>::DeleteIterator(
MapIterator* map_iter) const {
delete reinterpret_cast<typename Map<Key, T>::const_iterator*>(
map_iter->iter_);
}
template <typename Key, typename T>
void TypeDefinedMapFieldBase<Key, T>::CopyIterator(
MapIterator* this_iter, const MapIterator& that_iter) const {
@ -164,153 +159,103 @@ void TypeDefinedMapFieldBase<Key, T>::CopyIterator(
SetMapIteratorValue(this_iter);
}
// ----------------------------------------------------------------------
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
int MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::size() const {
MapFieldBase::SyncMapWithRepeatedField();
return static_cast<int>(impl_.GetMap().size());
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Clear() {
if (auto* p = this->maybe_payload()) {
reinterpret_cast<RepeatedPtrField<EntryType>&>(p->repeated_field).Clear();
}
impl_.MutableMap()->clear();
// Data in map and repeated field are both empty, but we can't set status
// CLEAN. Because clear is a generated API, we cannot invalidate previous
// reference to map.
MapFieldBase::SetMapDirty();
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
void MapField<Derived, Key, T, kKeyFieldType,
kValueFieldType>::SetMapIteratorValue(MapIterator* map_iter)
const {
const Map<Key, T>& map = impl_.GetMap();
typename Map<Key, T>::const_iterator iter =
TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(map_iter);
template <typename Key, typename T>
void TypeDefinedMapFieldBase<Key, T>::SetMapIteratorValue(
MapIterator* map_iter) const {
const auto& map = GetMap();
auto iter = InternalGetIterator(map_iter);
if (iter == map.end()) return;
SetMapKey(&map_iter->key_, iter->first);
map_iter->value_.SetValue(&iter->second);
map_iter->value_.SetValueOrCopy(&iter->second);
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::ContainsMapKey(
template <typename Key, typename T>
bool TypeDefinedMapFieldBase<Key, T>::ContainsMapKey(
const MapKey& map_key) const {
const Map<Key, T>& map = impl_.GetMap();
const Key& key = UnwrapMapKey<Key>(map_key);
typename Map<Key, T>::const_iterator iter = map.find(key);
return iter != map.end();
return GetMap().contains(UnwrapMapKey<Key>(map_key));
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
bool MapField<Derived, Key, T, kKeyFieldType,
kValueFieldType>::InsertOrLookupMapValue(const MapKey& map_key,
MapValueRef* val) {
template <typename Key, typename T>
bool TypeDefinedMapFieldBase<Key, T>::InsertOrLookupMapValue(
const MapKey& map_key, MapValueRef* val) {
// Always use mutable map because users may change the map value by
// MapValueRef.
Map<Key, T>* map = MutableMap();
const Key& key = UnwrapMapKey<Key>(map_key);
typename Map<Key, T>::iterator iter = map->find(key);
if (map->end() == iter) {
val->SetValue(&((*map)[key]));
return true;
}
// Key is already in the map. Make sure (*map)[key] is not called.
// [] may reorder the map and iterators.
val->SetValue(&(iter->second));
return false;
auto& map = *MutableMap();
auto res = map.try_emplace(UnwrapMapKey<Key>(map_key));
val->SetValue(&res.first->second);
return res.second;
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::LookupMapValue(
template <typename Key, typename T>
bool TypeDefinedMapFieldBase<Key, T>::LookupMapValue(
const MapKey& map_key, MapValueConstRef* val) const {
const Map<Key, T>& map = GetMap();
const Key& key = UnwrapMapKey<Key>(map_key);
typename Map<Key, T>::const_iterator iter = map.find(key);
const auto& map = GetMap();
auto iter = map.find(UnwrapMapKey<Key>(map_key));
if (map.end() == iter) {
return false;
}
// Key is already in the map. Make sure (*map)[key] is not called.
// [] may reorder the map and iterators.
val->SetValue(&(iter->second));
val->SetValueOrCopy(&iter->second);
return true;
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::DeleteMapValue(
const MapKey& map_key) {
const Key& key = UnwrapMapKey<Key>(map_key);
return MutableMap()->erase(key);
template <typename Key, typename T>
bool TypeDefinedMapFieldBase<Key, T>::DeleteMapValue(const MapKey& map_key) {
return MutableMap()->erase(UnwrapMapKey<Key>(map_key));
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::MergeFrom(
const MapFieldBase& other) {
MapFieldBase::SyncMapWithRepeatedField();
const MapField& other_field = static_cast<const MapField&>(other);
template <typename Key, typename T>
void TypeDefinedMapFieldBase<Key, T>::Swap(MapFieldBase* other) {
MapFieldBase::Swap(other);
auto* other_field = DownCast<TypeDefinedMapFieldBase*>(other);
map_.Swap(&other_field->map_);
}
template <typename Key, typename T>
void TypeDefinedMapFieldBase<Key, T>::MergeFrom(const MapFieldBase& other) {
SyncMapWithRepeatedField();
const auto& other_field = static_cast<const TypeDefinedMapFieldBase&>(other);
other_field.SyncMapWithRepeatedField();
impl_.MergeFrom(other_field.impl_);
MapFieldBase::SetMapDirty();
internal::MapMergeFrom(map_, other_field.map_);
SetMapDirty();
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Swap(
MapFieldBase* other) {
MapFieldBase::Swap(other);
MapField* other_field = DownCast<MapField*>(other);
impl_.Swap(&other_field->impl_);
template <typename Key, typename T>
size_t TypeDefinedMapFieldBase<Key, T>::SpaceUsedExcludingSelfNoLock() const {
size_t size = 0;
if (auto* p = maybe_payload()) {
size += p->repeated_field.SpaceUsedExcludingSelfLong();
}
// We can't compile this expression for DynamicMapField even though it is
// never used at runtime, so disable it at compile time.
std::get<std::is_same<Map<Key, T>, Map<MapKey, MapValueRef>>::value>(
std::make_tuple(
[&](const auto& map) { size += map.SpaceUsedExcludingSelfLong(); },
[](const auto&) {}))(map_);
return size;
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
void MapField<Derived, Key, T, kKeyFieldType,
kValueFieldType>::UnsafeShallowSwap(MapFieldBase* other) {
InternalSwap(DownCast<MapField*>(other));
template <typename Key, typename T>
void TypeDefinedMapFieldBase<Key, T>::UnsafeShallowSwap(MapFieldBase* other) {
InternalSwap(DownCast<TypeDefinedMapFieldBase*>(other));
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::InternalSwap(
MapField* other) {
template <typename Key, typename T>
void TypeDefinedMapFieldBase<Key, T>::InternalSwap(
TypeDefinedMapFieldBase* other) {
MapFieldBase::InternalSwap(other);
impl_.InternalSwap(&other->impl_);
map_.InternalSwap(&other->map_);
}
// ----------------------------------------------------------------------
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
void MapField<Derived, Key, T, kKeyFieldType,
kValueFieldType>::SyncRepeatedFieldWithMapNoLock() const {
const Map<Key, T>& map = impl_.GetMap();
RepeatedPtrField<EntryType>* repeated_field =
reinterpret_cast<RepeatedPtrField<EntryType>*>(
&this->payload().repeated_field);
repeated_field->Clear();
auto& repeated_field = this->payload().repeated_field;
repeated_field.Clear();
// The only way we can get at this point is through reflection and the
// only way we can get the reflection object is by having called GetReflection
@ -319,12 +264,11 @@ void MapField<Derived, Key, T, kKeyFieldType,
// So it's safe to just call internal_default_instance().
auto* arena = this->arena();
const Message* default_entry = Derived::internal_default_instance();
for (typename Map<Key, T>::const_iterator it = map.begin(); it != map.end();
++it) {
for (auto& elem : this->map_) {
EntryType* new_entry = DownCast<EntryType*>(default_entry->New(arena));
repeated_field->AddAllocated(new_entry);
(*new_entry->mutable_key()) = it->first;
(*new_entry->mutable_value()) = it->second;
repeated_field.AddAllocated(new_entry);
(*new_entry->mutable_key()) = elem.first;
(*new_entry->mutable_value()) = elem.second;
}
}
@ -333,35 +277,18 @@ template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kValueFieldType>
void MapField<Derived, Key, T, kKeyFieldType,
kValueFieldType>::SyncMapWithRepeatedFieldNoLock() const {
Map<Key, T>* map = const_cast<MapField*>(this)->impl_.MutableMap();
RepeatedPtrField<EntryType>* repeated_field =
reinterpret_cast<RepeatedPtrField<EntryType>*>(
&this->payload().repeated_field);
map->clear();
for (typename RepeatedPtrField<EntryType>::iterator it =
repeated_field->begin();
it != repeated_field->end(); ++it) {
Map<Key, T>& map = const_cast<MapField*>(this)->map_;
auto& repeated_field = this->payload().repeated_field;
map.clear();
for (const auto& generic_elem : repeated_field) {
// Cast is needed because Map's api and internal storage is different when
// value is enum. For enum, we cannot cast an int to enum. Thus, we have to
// copy value. For other types, they have same exposed api type and internal
// stored type. We should not introduce value copy for them. We achieve this
// by casting to value for enum while casting to reference for other types.
(*map)[it->key()] = static_cast<CastValueType>(it->value());
}
}
template <typename Derived, typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType>
size_t MapField<Derived, Key, T, kKeyFieldType,
kValueFieldType>::SpaceUsedExcludingSelfNoLock() const {
size_t size = 0;
if (auto* p = this->maybe_payload()) {
size += p->repeated_field.SpaceUsedExcludingSelfLong();
const EntryType& elem = DownCast<const EntryType&>(generic_elem);
map[elem.key()] = static_cast<CastValueType>(elem.value());
}
size += impl_.GetMap().SpaceUsedExcludingSelfLong();
return size;
}
} // namespace internal
} // namespace protobuf

@ -90,8 +90,6 @@ class MapFieldBaseStub : public MapFieldBase {
void MapEnd(MapIterator* map_iter) const override {}
void MergeFrom(const MapFieldBase& other) override {}
void Swap(MapFieldBase* other) override {}
void InitializeIterator(MapIterator* map_iter) const override {}
void DeleteIterator(MapIterator* map_iter) const override {}
void CopyIterator(MapIterator* this_iterator,
const MapIterator& other_iterator) const override {}
void IncreaseIterator(MapIterator* map_iter) const override {}
@ -268,17 +266,16 @@ class MapFieldStateTest
MakeMapDirty(map_field);
MapFieldBase* map_field_base = map_field;
map_field_base->MutableRepeatedField();
// We use MutableMap on impl_ because we don't want to disturb the syncing
Map<int32_t, int32_t>* map = map_field->impl_.MutableMap();
map->clear();
// We use map_ because we don't want to disturb the syncing
map_field->map_.clear();
Expect(map_field, REPEATED_DIRTY, 0, 1);
}
void Expect(MapFieldType* map_field, State state, int map_size,
int repeated_size) {
// We use MutableMap on impl_ because we don't want to disturb the syncing
Map<int32_t, int32_t>* map = map_field->impl_.MutableMap();
// We use map_ because we don't want to disturb the syncing
Map<int32_t, int32_t>* map = &map_field->map_;
switch (state) {
case MAP_DIRTY:

Loading…
Cancel
Save