@ -18,6 +18,7 @@
# include "google/protobuf/generated_message_reflection.h"
# include "google/protobuf/generated_message_util.h"
# include "google/protobuf/internal_visibility.h"
# include "google/protobuf/map.h"
# include "google/protobuf/map_entry.h"
# include "google/protobuf/map_field_lite.h"
# include "google/protobuf/map_type_handler.h"
@ -295,8 +296,10 @@ class MapFieldAccessor;
// reflection implementation only. Users should never use this directly.
class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
public :
constexpr MapFieldBase ( ) { }
explicit MapFieldBase ( Arena * arena ) : payload_ { ToTaggedPtr ( arena ) } { }
explicit constexpr MapFieldBase ( const VTable * vtable )
: MapFieldBaseForParse ( vtable ) { }
explicit MapFieldBase ( const VTable * vtable , Arena * arena )
: MapFieldBaseForParse ( vtable ) , payload_ { ToTaggedPtr ( arena ) } { }
MapFieldBase ( const MapFieldBase & ) = delete ;
MapFieldBase & operator = ( const MapFieldBase & ) = delete ;
@ -304,6 +307,39 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
// "protected" stops users from deleting a `MapFieldBase *`
~ MapFieldBase ( ) ;
struct VTable : MapFieldBaseForParse : : VTable {
bool ( * lookup_map_value ) ( const MapFieldBase & map , const MapKey & map_key ,
MapValueConstRef * val ) ;
bool ( * delete_map_value ) ( MapFieldBase & map , const MapKey & map_key ) ;
void ( * set_map_iterator_value ) ( MapIterator * map_iter ) ;
bool ( * insert_or_lookup_no_sync ) ( MapFieldBase & map , const MapKey & map_key ,
MapValueRef * val ) ;
void ( * clear_map_no_sync ) ( MapFieldBase & map ) ;
void ( * merge_from ) ( MapFieldBase & map , const MapFieldBase & other ) ;
void ( * swap ) ( MapFieldBase & lhs , MapFieldBase & rhs ) ;
void ( * unsafe_shallow_swap ) ( MapFieldBase & lhs , MapFieldBase & rhs ) ;
size_t ( * space_used_excluding_self_nolock ) ( const MapFieldBase & map ) ;
const Message * ( * get_prototype ) ( const MapFieldBase & map ) ;
} ;
template < typename T >
static constexpr VTable MakeVTable ( ) {
VTable out { } ;
out . get_map = & T : : GetMapImpl ;
out . lookup_map_value = & T : : LookupMapValueImpl ;
out . delete_map_value = & T : : DeleteMapValueImpl ;
out . set_map_iterator_value = & T : : SetMapIteratorValueImpl ;
out . insert_or_lookup_no_sync = & T : : InsertOrLookupMapValueNoSyncImpl ;
out . clear_map_no_sync = & T : : ClearMapNoSyncImpl ;
out . merge_from = & T : : MergeFromImpl ;
out . swap = & T : : SwapImpl ;
out . unsafe_shallow_swap = & T : : UnsafeShallowSwapImpl ;
out . space_used_excluding_self_nolock = & T : : SpaceUsedExcludingSelfNoLockImpl ;
out . get_prototype = & T : : GetPrototypeImpl ;
return out ;
}
public :
// Returns reference to internal repeated field. Data written using
// Map's api prior to calling this function is guarantted to be
@ -313,10 +349,14 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
// Like above. Returns mutable pointer to the internal repeated field.
RepeatedPtrFieldBase * MutableRepeatedField ( ) ;
// Pure virtual map APIs for Map Reflection.
virtual bool ContainsMapKey ( const MapKey & map_key ) const = 0 ;
virtual bool LookupMapValue ( const MapKey & map_key ,
MapValueConstRef * val ) const = 0 ;
const VTable * vtable ( ) const { return static_cast < const VTable * > ( vtable_ ) ; }
bool ContainsMapKey ( const MapKey & map_key ) const {
return LookupMapValue ( map_key , static_cast < MapValueConstRef * > ( nullptr ) ) ;
}
bool LookupMapValue ( const MapKey & map_key , MapValueConstRef * val ) const {
return vtable ( ) - > lookup_map_value ( * this , map_key , val ) ;
}
bool LookupMapValue ( const MapKey & , MapValueRef * ) const = delete ;
bool InsertOrLookupMapValue ( const MapKey & map_key , MapValueRef * val ) ;
@ -325,19 +365,26 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
bool IsRepeatedFieldValid ( ) const ;
// Insures operations after won't get executed before calling this.
bool IsMapValid ( ) const ;
virtual bool DeleteMapValue ( const MapKey & map_key ) = 0 ;
virtual void MergeFrom ( const MapFieldBase & other ) = 0 ;
virtual void Swap ( MapFieldBase * other ) ;
virtual void UnsafeShallowSwap ( MapFieldBase * other ) ;
bool DeleteMapValue ( const MapKey & map_key ) {
return vtable ( ) - > delete_map_value ( * this , map_key ) ;
}
void MergeFrom ( const MapFieldBase & other ) {
vtable ( ) - > merge_from ( * this , other ) ;
}
void Swap ( MapFieldBase * other ) { vtable ( ) - > swap ( * this , * other ) ; }
void UnsafeShallowSwap ( MapFieldBase * other ) {
vtable ( ) - > unsafe_shallow_swap ( * this , * other ) ;
}
// Sync Map with repeated field and returns the size of map.
int size ( ) const ;
void Clear ( ) ;
virtual void SetMapIteratorValue ( MapIterator * map_iter ) const = 0 ;
void SetMapIteratorValue ( MapIterator * map_iter ) const {
return vtable ( ) - > set_map_iterator_value ( map_iter ) ;
}
void MapBegin ( MapIterator * map_iter ) const ;
void MapEnd ( MapIterator * map_iter ) const ;
bool EqualIterator ( const MapIterator & a , const MapIterator & b ) const ;
const UntypedMapBase & GetMapImpl ( bool is_mutable ) const final ;
// Returns the number of bytes used by the repeated field, excluding
// sizeof(*this)
@ -349,10 +396,12 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
protected :
// Gets the size of space used by map field.
virtual size_t SpaceUsedExcludingSelfNoLock ( ) const ;
size_t SpaceUsedExcludingSelfNoLock ( ) const {
return vtable ( ) - > space_used_excluding_self_nolock ( * this ) ;
}
virtual const Message * GetPrototype ( ) const = 0 ;
virtual void ClearMapNoSync ( ) = 0 ;
const Message * GetPrototype ( ) const { return vtable ( ) - > get_prototype ( * this ) ; }
void ClearMapNoSync ( ) { return vtable ( ) - > clear_map_no_sync ( * this ) ; }
// Synchronizes the content in Map to RepeatedPtrField if there is any change
// to Map after last synchronization.
@ -364,6 +413,9 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
void SyncMapWithRepeatedField ( ) const ;
void SyncMapWithRepeatedFieldNoLock ( ) ;
static void SwapImpl ( MapFieldBase & lhs , MapFieldBase & rhs ) ;
static void UnsafeShallowSwapImpl ( MapFieldBase & lhs , MapFieldBase & rhs ) ;
// Tells MapFieldBase that there is new change to Map.
void SetMapDirty ( ) ;
@ -373,8 +425,9 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
// Provides derived class the access to repeated field.
void * MutableRepeatedPtrField ( ) const ;
virtual bool InsertOrLookupMapValueNoSync ( const MapKey & map_key ,
MapValueRef * val ) = 0 ;
bool InsertOrLookupMapValueNoSync ( const MapKey & map_key , MapValueRef * val ) {
return vtable ( ) - > insert_or_lookup_no_sync ( * this , map_key , val ) ;
}
void InternalSwap ( MapFieldBase * other ) ;
@ -439,6 +492,9 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
: STATE_MODIFIED_MAP ;
}
static const UntypedMapBase & GetMapImpl ( const MapFieldBaseForParse & map ,
bool is_mutable ) ;
private :
friend class ContendedMapCleanTest ;
friend class GeneratedMessageReflection ;
@ -501,7 +557,8 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
template < typename Key , typename T >
class TypeDefinedMapFieldBase : public MapFieldBase {
public :
constexpr TypeDefinedMapFieldBase ( ) : map_ ( ) {
explicit constexpr TypeDefinedMapFieldBase ( const VTable * vtable )
: MapFieldBase ( vtable ) , map_ ( ) {
// This invariant is required by MapFieldBase to easily access the map
// member without paying for dynamic dispatch. It reduces code size.
static_assert ( PROTOBUF_FIELD_OFFSET ( TypeDefinedMapFieldBase , map_ ) = =
@ -511,10 +568,8 @@ class TypeDefinedMapFieldBase : public MapFieldBase {
TypeDefinedMapFieldBase ( const TypeDefinedMapFieldBase & ) = delete ;
TypeDefinedMapFieldBase & operator = ( const TypeDefinedMapFieldBase & ) = delete ;
explicit TypeDefinedMapFieldBase ( Arena * arena )
: MapFieldBase ( arena ) , map_ ( arena ) { }
TypeDefinedMapFieldBase ( ArenaInitialized , Arena * arena )
: TypeDefinedMapFieldBase ( arena ) { }
TypeDefinedMapFieldBase ( const VTable * vtable , Arena * arena )
: MapFieldBase ( vtable , arena ) , map_ ( arena ) { }
protected :
~ TypeDefinedMapFieldBase ( ) { map_ . ~ Map ( ) ; }
@ -535,33 +590,36 @@ class TypeDefinedMapFieldBase : public MapFieldBase {
return & map_ ;
}
void ClearMapNoSync ( ) override { map_ . clear ( ) ; }
static void ClearMapNoSyncImpl ( MapFieldBase & map ) {
static_cast < TypeDefinedMapFieldBase & > ( map ) . map_ . clear ( ) ;
}
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 :
friend struct MapFieldTestPeer ;
using Iter = typename Map < Key , T > : : const_iterator ;
static bool DeleteMapValueImpl ( MapFieldBase & map , const MapKey & map_key ) ;
static bool LookupMapValueImpl ( const MapFieldBase & self ,
const MapKey & map_key , MapValueConstRef * val ) ;
static void SetMapIteratorValueImpl ( MapIterator * map_iter ) ;
static bool InsertOrLookupMapValueNoSyncImpl ( MapFieldBase & map ,
const MapKey & map_key ,
MapValueRef * val ) ;
static void MergeFromImpl ( MapFieldBase & base , const MapFieldBase & other ) ;
static void SwapImpl ( MapFieldBase & lhs , MapFieldBase & rhs ) ;
static void UnsafeShallowSwapImpl ( MapFieldBase & lhs , MapFieldBase & rhs ) ;
static size_t SpaceUsedExcludingSelfNoLockImpl ( const MapFieldBase & map ) ;
// map_ is inside an anonymous union so we can explicitly control its
// destruction
union {
Map < Key , T > map_ ;
} ;
private :
void SetMapIteratorValue ( MapIterator * map_iter ) const final ;
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 InsertOrLookupMapValueNoSync ( const MapKey & map_key ,
MapValueRef * val ) override ;
} ;
// This class provides access to map field using generated api. It is used for
@ -584,19 +642,18 @@ class MapField final : public TypeDefinedMapFieldBase<Key, T> {
static constexpr WireFormatLite : : FieldType kKeyFieldType = kKeyFieldType_ ;
static constexpr WireFormatLite : : FieldType kValueFieldType = kValueFieldType_ ;
constexpr MapField ( ) { }
constexpr MapField ( ) : MapField : : TypeDefinedMapFieldBase ( & kVTable ) { }
MapField ( const MapField & ) = delete ;
MapField & operator = ( const MapField & ) = delete ;
~ MapField ( ) { }
explicit MapField ( Arena * arena ) : TypeDefinedMapFieldBase < Key , T > ( arena ) { }
explicit MapField ( Arena * arena )
: TypeDefinedMapFieldBase < Key , T > ( & kVTable , arena ) { }
MapField ( ArenaInitialized , Arena * arena ) : MapField ( arena ) { }
MapField ( InternalVisibility , Arena * arena )
: TypeDefinedMapFieldBase < Key , T > ( arena ) { }
MapField ( InternalVisibility , Arena * arena ) : MapField ( arena ) { }
MapField ( InternalVisibility , Arena * arena , const MapField & from )
: TypeDefined MapFieldBase < Key , T > ( arena ) {
TypeDefinedMapFieldBase < Key , T > : : MergeFrom ( from ) ;
: MapField ( arena ) {
this - > MergeFromImpl ( * this , from ) ;
}
// Used in the implementation of parsing. Caller should take the ownership iff
@ -609,13 +666,22 @@ class MapField final : public TypeDefinedMapFieldBase<Key, T> {
typedef void InternalArenaConstructable_ ;
typedef void DestructorSkippable_ ;
// Implements MapFieldBase
const Message * GetPrototype ( ) const final ;
static const Message * GetPrototypeImpl ( const MapFieldBase & map ) ;
static const MapFieldBase : : VTable kVTable ;
friend class google : : protobuf : : Arena ;
friend class MapFieldBase ;
friend class MapFieldStateTest ; // For testing, it needs raw access to impl_
} ;
template < typename Derived , typename Key , typename T ,
WireFormatLite : : FieldType kKeyFieldType_ ,
WireFormatLite : : FieldType kValueFieldType_ >
constexpr MapFieldBase : : VTable
MapField < Derived , Key , T , kKeyFieldType_ , kValueFieldType_ > : : kVTable =
MapField : : template MakeVTable < MapField > ( ) ;
template < typename Key , typename T >
bool AllAreInitialized ( const TypeDefinedMapFieldBase < Key , T > & field ) {
for ( const auto & p : field . GetMap ( ) ) {
@ -639,24 +705,31 @@ class PROTOBUF_EXPORT DynamicMapField final
DynamicMapField ( const Message * default_entry , Arena * arena ) ;
DynamicMapField ( const DynamicMapField & ) = delete ;
DynamicMapField & operator = ( const DynamicMapField & ) = delete ;
virtual ~ DynamicMapField ( ) ;
// Implement MapFieldBase
bool InsertOrLookupMapValueNoSync ( const MapKey & map_key ,
MapValueRef * val ) final ;
void MergeFrom ( const MapFieldBase & other ) final ;
void UnsafeShallowSwap ( MapFieldBase * other ) final { Swap ( other ) ; }
void ClearMapNoSync ( ) final ;
~ DynamicMapField ( ) ;
private :
friend class MapFieldBase ;
const Message * default_entry_ ;
static const VTable kVTable ;
void AllocateMapValue ( MapValueRef * map_val ) ;
// Implements MapFieldBase
const Message * GetPrototype ( ) const final ;
size_t SpaceUsedExcludingSelfNoLock ( ) const final ;
static void MergeFromImpl ( MapFieldBase & base , const MapFieldBase & other ) ;
static bool InsertOrLookupMapValueNoSyncImpl ( MapFieldBase & base ,
const MapKey & map_key ,
MapValueRef * val ) ;
static void ClearMapNoSyncImpl ( MapFieldBase & base ) ;
static void UnsafeShallowSwapImpl ( MapFieldBase & lhs , MapFieldBase & rhs ) {
static_cast < DynamicMapField & > ( lhs ) . Swap (
static_cast < DynamicMapField * > ( & rhs ) ) ;
}
static size_t SpaceUsedExcludingSelfNoLockImpl ( const MapFieldBase & map ) ;
static const Message * GetPrototypeImpl ( const MapFieldBase & map ) ;
} ;
} // namespace internal