|
|
|
@ -108,8 +108,7 @@ class GenericTypeHandler; |
|
|
|
|
// using Type = MyType;
|
|
|
|
|
// using Movable = ...;
|
|
|
|
|
//
|
|
|
|
|
// static ElementFactory GetNewFunc();
|
|
|
|
|
// static ElementFactory GetNewFromPrototypeFunc(const Type* prototype);
|
|
|
|
|
// static Type*(*)(Arena*) GetNewFunc();
|
|
|
|
|
// static void GetArena(Type* value);
|
|
|
|
|
//
|
|
|
|
|
// static Type* New(Arena* arena);
|
|
|
|
@ -128,6 +127,8 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
|
|
|
|
|
static constexpr int kSSOCapacity = 1; |
|
|
|
|
|
|
|
|
|
using ElementFactory = void* (*)(Arena*); |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
// We use the same TypeHandler for all Message types to deduplicate generated
|
|
|
|
|
// code.
|
|
|
|
@ -191,18 +192,15 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
|
|
|
|
|
template <typename TypeHandler> |
|
|
|
|
Value<TypeHandler>* Add() { |
|
|
|
|
return cast<TypeHandler>(AddInternal(TypeHandler::GetNewFunc())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename Type> |
|
|
|
|
Type* AddFromPrototype(const Type* prototype) { |
|
|
|
|
using TypeHandler = GenericTypeHandler<Type>; |
|
|
|
|
using H = CommonHandler<TypeHandler>; |
|
|
|
|
return cast<TypeHandler>( |
|
|
|
|
AddInternal(H::GetNewFromPrototypeFunc(prototype))); |
|
|
|
|
if (std::is_same<Value<TypeHandler>, std::string>{}) { |
|
|
|
|
return cast<TypeHandler>(AddString()); |
|
|
|
|
} |
|
|
|
|
return cast<TypeHandler>(AddMessageLite(TypeHandler::GetNewFunc())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename TypeHandler> |
|
|
|
|
template < |
|
|
|
|
typename TypeHandler, |
|
|
|
|
typename std::enable_if<TypeHandler::Movable::value>::type* = nullptr> |
|
|
|
|
inline void Add(Value<TypeHandler>&& value) { |
|
|
|
|
if (current_size_ < allocated_size()) { |
|
|
|
|
*cast<TypeHandler>(element_at(ExchangeCurrentSize(current_size_ + 1))) = |
|
|
|
@ -257,6 +255,12 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
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> |
|
|
|
|
void Clear() { |
|
|
|
|
const int n = current_size_; |
|
|
|
@ -721,6 +725,10 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
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
|
|
|
|
|
// used to construct a new element unless there are spare cleared elements
|
|
|
|
|
// ready for reuse. Returns pointer to the new element.
|
|
|
|
@ -805,32 +813,13 @@ void* RepeatedPtrFieldBase::AddInternal(Factory factory) { |
|
|
|
|
|
|
|
|
|
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> |
|
|
|
|
class GenericTypeHandler { |
|
|
|
|
public: |
|
|
|
|
using Type = GenericType; |
|
|
|
|
using Movable = IsMovable<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 constexpr auto GetNewFunc() { return Arena::DefaultConstruct<Type>; } |
|
|
|
|
static inline Arena* GetArena(Type* value) { |
|
|
|
|
return Arena::InternalGetArena(value); |
|
|
|
|
} |
|
|
|
@ -841,42 +830,76 @@ class GenericTypeHandler { |
|
|
|
|
static inline Type* New(Arena* arena, Type&& 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) { |
|
|
|
|
static_assert(std::is_base_of<MessageLite, Type>::value, ""); |
|
|
|
|
ABSL_DCHECK(prototype != nullptr); |
|
|
|
|
return prototype->New(arena); |
|
|
|
|
return New(arena); |
|
|
|
|
} |
|
|
|
|
static inline void Delete(Type* value, Arena* arena) { |
|
|
|
|
if (arena != nullptr) return; |
|
|
|
|
// Using virtual destructor to reduce generated code size that would have
|
|
|
|
|
// happened otherwise due to inlined `~Type()`.
|
|
|
|
|
InternalOutOfLineDeleteMessageLite(value); |
|
|
|
|
} |
|
|
|
|
static inline void Clear(Type* value) { |
|
|
|
|
static_assert(std::is_base_of<MessageLite, Type>::value, ""); |
|
|
|
|
value->Clear(); |
|
|
|
|
} |
|
|
|
|
static inline void Merge(const Type& from, Type* to) { |
|
|
|
|
static_assert(std::is_base_of<MessageLite, Type>::value, ""); |
|
|
|
|
to->CheckTypeAndMergeFrom(from); |
|
|
|
|
#ifdef __cpp_if_constexpr |
|
|
|
|
if constexpr (std::is_base_of<MessageLite, Type>::value) { |
|
|
|
|
// Using virtual destructor to reduce generated code size that would have
|
|
|
|
|
// happened otherwise due to inlined `~Type()`.
|
|
|
|
|
InternalOutOfLineDeleteMessageLite(value); |
|
|
|
|
} else { |
|
|
|
|
delete value; |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
delete value; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
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_assert(std::is_base_of<MessageLite, Type>::value, ""); |
|
|
|
|
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 <> |
|
|
|
|
class GenericTypeHandler<std::string> { |
|
|
|
|
public: |
|
|
|
|
using Type = std::string; |
|
|
|
|
using Movable = IsMovable<Type>; |
|
|
|
|
|
|
|
|
|
static constexpr auto* GetNewFunc() { return Arena::Create<Type>; } |
|
|
|
|
static constexpr auto* GetNewFromPrototypeFunc(const Type* prototype) { |
|
|
|
|
return GetNewFunc(); |
|
|
|
|
} |
|
|
|
|
static constexpr auto GetNewFunc() { return NewStringElement; } |
|
|
|
|
static inline Arena* GetArena(Type*) { return nullptr; } |
|
|
|
|
|
|
|
|
|
static PROTOBUF_NOINLINE Type* New(Arena* arena) { |
|
|
|
|
return Arena::Create<Type>(arena); |
|
|
|
|
} |
|
|
|
@ -891,15 +914,13 @@ class GenericTypeHandler<std::string> { |
|
|
|
|
delete value; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
static inline Arena* GetArena(Type*) { return nullptr; } |
|
|
|
|
static inline void Clear(Type* value) { value->clear(); } |
|
|
|
|
static inline void Merge(const Type& from, Type* to) { *to = from; } |
|
|
|
|
static inline size_t SpaceUsedLong(const Type& value) { |
|
|
|
|
static size_t SpaceUsedLong(const Type& value) { |
|
|
|
|
return sizeof(value) + StringSpaceUsedExcludingSelfLong(value); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
|
|
|
|
|
|
// RepeatedPtrField is like RepeatedField, but used for repeated strings or
|
|
|
|
@ -1225,7 +1246,7 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void AddAllocatedForParse(Element* p) { |
|
|
|
|
RepeatedPtrFieldBase::AddAllocatedForParse(p); |
|
|
|
|
return RepeatedPtrFieldBase::AddAllocatedForParse(p); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|