@ -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 : : Map MergeFrom ( map_ , other_field . ma p_ ) ;
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 ) ;
i mpl _. InternalSwap ( & other - > i mpl _) ;
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