@ -108,7 +108,8 @@ class GenericTypeHandler;
// using Type = MyType;
// using Type = MyType;
// using Movable = ...;
// using Movable = ...;
//
//
// static Type*(*)(Arena*) GetNewFunc();
// static ElementFactory GetNewFunc();
// static ElementFactory GetNewFromPrototypeFunc(const Type* prototype);
// static void GetArena(Type* value);
// static void GetArena(Type* value);
//
//
// static Type* New(Arena* arena);
// static Type* New(Arena* arena);
@ -127,8 +128,6 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
static constexpr int kSSOCapacity = 1 ;
static constexpr int kSSOCapacity = 1 ;
using ElementFactory = void * ( * ) ( Arena * ) ;
protected :
protected :
// We use the same TypeHandler for all Message types to deduplicate generated
// We use the same TypeHandler for all Message types to deduplicate generated
// code.
// code.
@ -192,15 +191,18 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
template < typename TypeHandler >
template < typename TypeHandler >
Value < TypeHandler > * Add ( ) {
Value < TypeHandler > * Add ( ) {
if ( std : : is_same < Value < TypeHandler > , std : : string > { } ) {
return cast < TypeHandler > ( AddInternal ( TypeHandler : : GetNewFunc ( ) ) ) ;
return cast < TypeHandler > ( AddString ( ) ) ;
}
return cast < TypeHandler > ( AddMessageLite ( TypeHandler : : GetNewFunc ( ) ) ) ;
}
}
template <
template < typename Type >
typename TypeHandler ,
Type * AddFromPrototype ( const Type * prototype ) {
typename std : : enable_if < TypeHandler : : Movable : : value > : : type * = nullptr >
using TypeHandler = GenericTypeHandler < Type > ;
using H = CommonHandler < TypeHandler > ;
return cast < TypeHandler > (
AddInternal ( H : : GetNewFromPrototypeFunc ( prototype ) ) ) ;
}
template < typename TypeHandler >
inline void Add ( Value < TypeHandler > & & value ) {
inline void Add ( Value < TypeHandler > & & value ) {
if ( current_size_ < allocated_size ( ) ) {
if ( current_size_ < allocated_size ( ) ) {
* cast < TypeHandler > ( element_at ( ExchangeCurrentSize ( current_size_ + 1 ) ) ) =
* cast < TypeHandler > ( element_at ( ExchangeCurrentSize ( current_size_ + 1 ) ) ) =
@ -255,12 +257,6 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
return * cast < TypeHandler > ( element_at ( index ) ) ;
return * cast < TypeHandler > ( element_at ( index ) ) ;
}
}
// Creates and adds an element using the given prototype, without introducing
// a link-time dependency on the concrete message type.
//
// Pre-condition: prototype must not be nullptr.
MessageLite * AddMessage ( const MessageLite * prototype ) ;
template < typename TypeHandler >
template < typename TypeHandler >
void Clear ( ) {
void Clear ( ) {
const int n = current_size_ ;
const int n = current_size_ ;
@ -725,10 +721,6 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
return InternalExtend ( n - Capacity ( ) ) ;
return InternalExtend ( n - Capacity ( ) ) ;
}
}
// Internal helpers for Add that keep definition out-of-line.
void * AddMessageLite ( ElementFactory factory ) ;
void * AddString ( ) ;
// Common implementation used by various Add* methods. `factory` is an object
// Common implementation used by various Add* methods. `factory` is an object
// used to construct a new element unless there are spare cleared elements
// used to construct a new element unless there are spare cleared elements
// ready for reuse. Returns pointer to the new element.
// ready for reuse. Returns pointer to the new element.
@ -813,13 +805,32 @@ void* RepeatedPtrFieldBase::AddInternal(Factory factory) {
PROTOBUF_EXPORT void InternalOutOfLineDeleteMessageLite ( MessageLite * message ) ;
PROTOBUF_EXPORT void InternalOutOfLineDeleteMessageLite ( MessageLite * message ) ;
// Encapsulates the minimally required subset of T's properties in a
// `RepeatedPtrField<T>` specialization so the type-agnostic
// `RepeatedPtrFieldBase` could do its job without knowing T.
//
// This generic definition is for types derived from `MessageLite`. That is
// statically asserted, but only where a non-conforming type would emit a
// compile-time diagnostic that lacks proper guidance for fixing. Asserting
// at the top level isn't possible, because some template argument types are not
// yet fully defined at the instantiation point.
//
// Explicit specializations are provided for `std::string` and
// `StringPieceField` further below.
template < typename GenericType >
template < typename GenericType >
class GenericTypeHandler {
class GenericTypeHandler {
public :
public :
using Type = GenericType ;
using Type = GenericType ;
using Movable = IsMovable < Type > ;
using Movable = IsMovable < Type > ;
static constexpr auto GetNewFunc ( ) { return Arena : : DefaultConstruct < Type > ; }
static constexpr auto * GetNewFunc ( ) { return Arena : : DefaultConstruct < Type > ; }
static constexpr auto GetNewFromPrototypeFunc ( const Type * prototype ) {
static_assert ( std : : is_base_of < MessageLite , Type > : : value , " " ) ;
return [ prototype ] ( Arena * arena ) {
ABSL_DCHECK ( prototype ! = nullptr ) ;
return prototype - > New ( arena ) ;
} ;
}
static inline Arena * GetArena ( Type * value ) {
static inline Arena * GetArena ( Type * value ) {
return Arena : : InternalGetArena ( value ) ;
return Arena : : InternalGetArena ( value ) ;
}
}
@ -830,76 +841,42 @@ class GenericTypeHandler {
static inline Type * New ( Arena * arena , Type & & value ) {
static inline Type * New ( Arena * arena , Type & & value ) {
return Arena : : Create < Type > ( arena , std : : move ( value ) ) ;
return Arena : : Create < Type > ( arena , std : : move ( value ) ) ;
}
}
static inline Type * NewFromPrototype ( const Type * /*prototype*/ ,
static inline Type * NewFromPrototype ( const Type * prototype ,
Arena * arena = nullptr ) {
Arena * arena = nullptr ) {
return New ( arena ) ;
static_assert ( std : : is_base_of < MessageLite , Type > : : value , " " ) ;
ABSL_DCHECK ( prototype ! = nullptr ) ;
return prototype - > New ( arena ) ;
}
}
static inline void Delete ( Type * value , Arena * arena ) {
static inline void Delete ( Type * value , Arena * arena ) {
if ( arena ! = nullptr ) return ;
if ( arena ! = nullptr ) return ;
# ifdef __cpp_if_constexpr
// Using virtual destructor to reduce generated code size that would have
if constexpr ( std : : is_base_of < MessageLite , Type > : : value ) {
// happened otherwise due to inlined `~Type()`.
// Using virtual destructor to reduce generated code size that would have
InternalOutOfLineDeleteMessageLite ( value ) ;
// happened otherwise due to inlined `~Type()`.
}
InternalOutOfLineDeleteMessageLite ( value ) ;
static inline void Clear ( Type * value ) {
} else {
static_assert ( std : : is_base_of < MessageLite , Type > : : value , " " ) ;
delete value ;
value - > Clear ( ) ;
}
}
# else
static inline void Merge ( const Type & from , Type * to ) {
del ete value ;
static_assert ( st d: : is_bas e_of < M essageLi te, Type > : : value , " " ) ;
# endif
to - > CheckTypeAndMergeFrom ( from ) ;
}
}
static inline void Clear ( Type * value ) { value - > Clear ( ) ; }
static void Merge ( const Type & from , Type * to ) ;
static inline size_t SpaceUsedLong ( const Type & value ) {
static inline size_t SpaceUsedLong ( const Type & value ) {
static_assert ( std : : is_base_of < MessageLite , Type > : : value , " " ) ;
return value . SpaceUsedLong ( ) ;
return value . SpaceUsedLong ( ) ;
}
}
} ;
} ;
// NewFromPrototypeHelper() is not defined inline here, as we will need to do a
// virtual function dispatch anyways to go from Message* to call New/Merge. (The
// additional helper is needed as a workaround for MSVC.)
PROTOBUF_EXPORT MessageLite * NewFromPrototypeHelper (
const MessageLite * prototype , Arena * arena ) ;
template < >
inline MessageLite * GenericTypeHandler < MessageLite > : : NewFromPrototype (
const MessageLite * prototype , Arena * arena ) {
return NewFromPrototypeHelper ( prototype , arena ) ;
}
template < >
inline Arena * GenericTypeHandler < MessageLite > : : GetArena ( MessageLite * value ) {
return value - > GetArena ( ) ;
}
template < typename GenericType >
PROTOBUF_NOINLINE inline void GenericTypeHandler < GenericType > : : Merge (
const GenericType & from , GenericType * to ) {
to - > MergeFrom ( from ) ;
}
template < >
PROTOBUF_EXPORT void GenericTypeHandler < MessageLite > : : Merge (
const MessageLite & from , MessageLite * to ) ;
// Message specialization bodies defined in message.cc. This split is necessary
// to allow proto2-lite (which includes this header) to be independent of
// Message.
template < >
PROTOBUF_EXPORT Message * GenericTypeHandler < Message > : : NewFromPrototype (
const Message * prototype , Arena * arena ) ;
template < >
PROTOBUF_EXPORT Arena * GenericTypeHandler < Message > : : GetArena ( Message * value ) ;
PROTOBUF_EXPORT void * NewStringElement ( Arena * arena ) ;
template < >
template < >
class GenericTypeHandler < std : : string > {
class GenericTypeHandler < std : : string > {
public :
public :
using Type = std : : string ;
using Type = std : : string ;
using Movable = IsMovable < Type > ;
using Movable = IsMovable < Type > ;
static constexpr auto GetNewFunc ( ) { return NewStringElement ; }
static constexpr auto * GetNewFunc ( ) { return Arena : : Create < Type > ; }
static inline Arena * GetArena ( Type * ) { return nullptr ; }
static constexpr auto * GetNewFromPrototypeFunc ( const Type * prototype ) {
return GetNewFunc ( ) ;
}
static PROTOBUF_NOINLINE Type * New ( Arena * arena ) {
static PROTOBUF_NOINLINE Type * New ( Arena * arena ) {
return Arena : : Create < Type > ( arena ) ;
return Arena : : Create < Type > ( arena ) ;
}
}
@ -914,13 +891,15 @@ class GenericTypeHandler<std::string> {
delete value ;
delete value ;
}
}
}
}
static inline Arena * GetArena ( Type * ) { return nullptr ; }
static inline void Clear ( Type * value ) { value - > clear ( ) ; }
static inline void Clear ( Type * value ) { value - > clear ( ) ; }
static inline void Merge ( const Type & from , Type * to ) { * to = from ; }
static inline void Merge ( const Type & from , Type * to ) { * to = from ; }
static size_t SpaceUsedLong ( const Type & value ) {
static inline size_t SpaceUsedLong ( const Type & value ) {
return sizeof ( value ) + StringSpaceUsedExcludingSelfLong ( value ) ;
return sizeof ( value ) + StringSpaceUsedExcludingSelfLong ( value ) ;
}
}
} ;
} ;
} // namespace internal
} // namespace internal
// RepeatedPtrField is like RepeatedField, but used for repeated strings or
// RepeatedPtrField is like RepeatedField, but used for repeated strings or
@ -1246,7 +1225,7 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
void AddAllocatedForParse ( Element * p ) {
void AddAllocatedForParse ( Element * p ) {
return RepeatedPtrFieldBase : : AddAllocatedForParse ( p ) ;
RepeatedPtrFieldBase : : AddAllocatedForParse ( p ) ;
}
}
} ;
} ;