// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd #ifndef GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ #define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ #include #include #include #include #include #include #include "absl/base/casts.h" #include "absl/strings/string_view.h" #include "google/protobuf/map.h" #include "google/protobuf/map_field.h" #include "google/protobuf/map_type_handler.h" #include "google/protobuf/message.h" #include "google/protobuf/port.h" // must be last #include "google/protobuf/port_def.inc" #ifdef SWIG #error "You cannot SWIG proto headers" #endif namespace google { namespace protobuf { namespace internal { // UnwrapMapKey template. We're using overloading rather than template // specialization so that we can return a value or reference type depending on // `T`. inline int32_t UnwrapMapKeyImpl(const MapKey& map_key, const int32_t*) { return map_key.GetInt32Value(); } inline uint32_t UnwrapMapKeyImpl(const MapKey& map_key, const uint32_t*) { return map_key.GetUInt32Value(); } inline int64_t UnwrapMapKeyImpl(const MapKey& map_key, const int64_t*) { return map_key.GetInt64Value(); } inline uint64_t UnwrapMapKeyImpl(const MapKey& map_key, const uint64_t*) { return map_key.GetUInt64Value(); } inline bool UnwrapMapKeyImpl(const MapKey& map_key, const bool*) { return map_key.GetBoolValue(); } inline absl::string_view UnwrapMapKeyImpl(const MapKey& map_key, const std::string*) { return map_key.GetStringValue(); } inline const MapKey& UnwrapMapKeyImpl(const MapKey& map_key, const MapKey*) { return map_key; } template decltype(auto) UnwrapMapKey(const MapKey& map_key) { return UnwrapMapKeyImpl(map_key, static_cast(nullptr)); } // SetMapKey inline void SetMapKey(MapKey* map_key, int32_t value) { map_key->SetInt32Value(value); } inline void SetMapKey(MapKey* map_key, uint32_t value) { map_key->SetUInt32Value(value); } inline void SetMapKey(MapKey* map_key, int64_t value) { map_key->SetInt64Value(value); } inline void SetMapKey(MapKey* map_key, uint64_t value) { map_key->SetUInt64Value(value); } inline void SetMapKey(MapKey* map_key, bool value) { map_key->SetBoolValue(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 void TypeDefinedMapFieldBase::SetMapIteratorValueImpl( MapIterator* map_iter) { if (map_iter->iter_.Equals(UntypedMapBase::EndIterator())) return; auto iter = typename Map::const_iterator(map_iter->iter_); SetMapKey(&map_iter->key_, iter->first); map_iter->value_.SetValueOrCopy(&iter->second); } template bool TypeDefinedMapFieldBase::InsertOrLookupMapValueNoSyncImpl( MapFieldBase& map, const MapKey& map_key, MapValueRef* val) { auto res = static_cast(map).map_.try_emplace( UnwrapMapKey(map_key)); val->SetValue(&res.first->second); return res.second; } template bool TypeDefinedMapFieldBase::LookupMapValueImpl( const MapFieldBase& self, const MapKey& map_key, MapValueConstRef* val) { const auto& map = static_cast(self).GetMap(); auto iter = map.find(UnwrapMapKey(map_key)); if (map.end() == iter) { return false; } if (val != nullptr) { val->SetValueOrCopy(&iter->second); } return true; } template bool TypeDefinedMapFieldBase::DeleteMapValueImpl( MapFieldBase& map, const MapKey& map_key) { return static_cast(map).MutableMap()->erase( UnwrapMapKey(map_key)); } template void TypeDefinedMapFieldBase::SwapImpl(MapFieldBase& lhs, MapFieldBase& rhs) { MapFieldBase::SwapImpl(lhs, rhs); static_cast(lhs).map_.swap( static_cast(rhs).map_); } template void TypeDefinedMapFieldBase::MergeFromImpl(MapFieldBase& base, const MapFieldBase& other) { auto& self = static_cast(base); self.SyncMapWithRepeatedField(); const auto& other_field = static_cast(other); other_field.SyncMapWithRepeatedField(); internal::MapMergeFrom(self.map_, other_field.map_); self.SetMapDirty(); } template size_t TypeDefinedMapFieldBase::SpaceUsedExcludingSelfNoLockImpl( const MapFieldBase& map) { auto& self = static_cast(map); size_t size = 0; if (auto* p = self.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, Map>::value>( std::make_tuple( [&](const auto& map) { size += map.SpaceUsedExcludingSelfLong(); }, [](const auto&) {}))(self.map_); return size; } template void TypeDefinedMapFieldBase::UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs) { static_cast(lhs).InternalSwap( static_cast(&rhs)); } template void TypeDefinedMapFieldBase::InternalSwap( TypeDefinedMapFieldBase* other) { MapFieldBase::InternalSwap(other); map_.InternalSwap(&other->map_); } // ---------------------------------------------------------------------- template const Message* MapField::GetPrototypeImpl( const MapFieldBase&) { return Derived::internal_default_instance(); } } // namespace internal } // namespace protobuf } // namespace google #include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__