diff options
Diffstat (limited to 'src/google/protobuf/repeated_field.h')
-rw-r--r-- | src/google/protobuf/repeated_field.h | 343 |
1 files changed, 158 insertions, 185 deletions
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 8eb6c795..fbfbf942 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -57,10 +57,11 @@ #include <google/protobuf/stubs/casts.h> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/type_traits.h> #include <google/protobuf/arena.h> +#include <google/protobuf/implicit_weak_message.h> #include <google/protobuf/message_lite.h> #include <google/protobuf/stubs/port.h> +#include <type_traits> // Forward-declare these so that we can make them friends. @@ -86,7 +87,7 @@ void LogIndexOutOfBounds(int index, int size); template <typename Iter> inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) { - return std::distance(begin, end); + return static_cast<int>(std::distance(begin, end)); } template <typename Iter> @@ -108,7 +109,7 @@ inline int CalculateReserve(Iter begin, Iter end) { // not ever use a RepeatedField directly; they will use the get-by-index, // set-by-index, and add accessors that are generated for all repeated fields. template <typename Element> -class RepeatedField PROTOBUF_FINAL { +class RepeatedField final { public: RepeatedField(); explicit RepeatedField(Arena* arena); @@ -119,10 +120,8 @@ class RepeatedField PROTOBUF_FINAL { RepeatedField& operator=(const RepeatedField& other); -#if LANG_CXX11 RepeatedField(RepeatedField&& other) noexcept; RepeatedField& operator=(RepeatedField&& other) noexcept; -#endif bool empty() const; int size() const; @@ -279,9 +278,19 @@ class RepeatedField PROTOBUF_FINAL { // a "gap" after the field arena and before the field elements (e.g., when // Element is double and pointer is 32bit). static const size_t kRepHeaderSize; - // Contains arena ptr and the elements array. We also keep the invariant that - // if rep_ is NULL, then arena is NULL. - Rep* rep_; + + // We reuse the Rep* for an Arena* when total_size == 0, to avoid having to do + // an allocation in the constructor when we have an Arena. + union Pointer { + Pointer(Arena* a) : arena(a) {} + Arena* arena; // When total_size_ == 0. + Rep* rep; // When total_size_ != 0. + } ptr_; + + Rep* rep() const { + GOOGLE_DCHECK_GT(total_size_, 0); + return ptr_.rep; + } friend class Arena; typedef void InternalArenaConstructable_; @@ -297,7 +306,7 @@ class RepeatedField PROTOBUF_FINAL { // Internal helper expected by Arena methods. inline Arena* GetArenaNoVirtual() const { - return (rep_ == NULL) ? NULL : rep_->arena; + return (total_size_ == 0) ? ptr_.arena : ptr_.rep->arena; } // Internal helper to delete all elements and deallocate the storage. @@ -342,7 +351,7 @@ namespace internal { // effectively. template <typename Element, bool HasTrivialCopy = - has_trivial_copy<Element>::value> + std::is_pod<Element>::value> struct ElementCopier { void operator()(Element* to, const Element* from, int array_size); }; @@ -376,8 +385,8 @@ struct TypeImplementsMergeBehaviorProbeForMergeFrom { CheckType<U, bool, &U::MergeFrom>*); template<typename U> static HasNoMerge Check(...); - // Resolves to either google::protobuf::internal::true_type or google::protobuf::internal::false_type. - typedef google::protobuf::internal::integral_constant<bool, + // Resolves to either std::true_type or std::false_type. + typedef std::integral_constant<bool, (sizeof(Check<T>(0)) == sizeof(HasMerge))> type; }; @@ -388,7 +397,7 @@ struct TypeImplementsMergeBehavior : template <> struct TypeImplementsMergeBehavior< ::std::string> { - typedef google::protobuf::internal::true_type type; + typedef std::true_type type; }; // This is the common base class for RepeatedPtrFields. It deals only in void* @@ -399,7 +408,12 @@ struct TypeImplementsMergeBehavior< ::std::string> { // class TypeHandler { // public: // typedef MyType Type; +// // WeakType is almost always the same as MyType, but we use it in +// // ImplicitWeakTypeHandler. +// typedef MyType WeakType; // static Type* New(); +// static WeakType* NewFromPrototype(const WeakType* prototype, +// ::google::protobuf::Arena* arena); // static void Delete(Type*); // static void Clear(Type*); // static void Merge(const Type& from, Type* to); @@ -409,31 +423,6 @@ struct TypeImplementsMergeBehavior< ::std::string> { // }; class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { protected: - // The reflection implementation needs to call protected methods directly, - // reinterpreting pointers as being to Message instead of a specific Message - // subclass. - friend class GeneratedMessageReflection; - - // ExtensionSet stores repeated message extensions as - // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to implement - // SpaceUsedLong(), and thus need to call SpaceUsedExcludingSelfLong() - // reinterpreting MessageLite as Message. ExtensionSet also needs to make use - // of AddFromCleared(), which is not part of the public interface. - friend class ExtensionSet; - - // The MapFieldBase implementation needs to call protected methods directly, - // reinterpreting pointers as being to Message instead of a specific Message - // subclass. - friend class MapFieldBase; - - // The table-driven MergePartialFromCodedStream implementation needs to - // operate on RepeatedPtrField<MessageLite>. - friend class MergePartialFromCodedStreamHelper; - - // To parse directly into a proto2 generated class, the upb class GMR_Handlers - // needs to be able to modify a RepeatedPtrFieldBase directly. - friend class upb::google_opensource::GMR_Handlers; - RepeatedPtrFieldBase(); explicit RepeatedPtrFieldBase(::google::protobuf::Arena* arena); ~RepeatedPtrFieldBase() {} @@ -446,25 +435,41 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { int size() const; template <typename TypeHandler> - const typename TypeHandler::Type& Get(int index) const; - template <typename TypeHandler> typename TypeHandler::Type* Mutable(int index); template <typename TypeHandler> void Delete(int index); template <typename TypeHandler> typename TypeHandler::Type* Add(typename TypeHandler::Type* prototype = NULL); -#if LANG_CXX11 - template <typename TypeHandler> - void Add(typename TypeHandler::Type&& value, - internal::enable_if<TypeHandler::Moveable>* dummy = NULL); -#endif + + public: + // The next few methods are public so that they can be called from generated + // code when implicit weak fields are used, but they should never be called by + // application code. template <typename TypeHandler> - void RemoveLast(); + const typename TypeHandler::WeakType& Get(int index) const; + + // Creates and adds an element using the given prototype, without introducing + // a link-time dependency on the concrete message type. This method is used to + // implement implicit weak fields. The prototype may be NULL, in which case an + // ImplicitWeakMessage will be used as a placeholder. + google::protobuf::MessageLite* AddWeak(const google::protobuf::MessageLite* prototype); + template <typename TypeHandler> void Clear(); + template <typename TypeHandler> void MergeFrom(const RepeatedPtrFieldBase& other); + + inline void InternalSwap(RepeatedPtrFieldBase* other); + + protected: + template <typename TypeHandler> + void Add(typename TypeHandler::Type&& value, + std::enable_if<TypeHandler::Moveable>* dummy = NULL); + + template <typename TypeHandler> + void RemoveLast(); template <typename TypeHandler> void CopyFrom(const RepeatedPtrFieldBase& other); @@ -491,7 +496,6 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { template <typename TypeHandler> size_t SpaceUsedExcludingSelfLong() const; - // Advanced memory management -------------------------------------- // Like Add(), but if there are no cleared objects to use, returns NULL. @@ -524,13 +528,10 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { template <typename TypeHandler> typename TypeHandler::Type* ReleaseCleared(); - protected: - inline void InternalSwap(RepeatedPtrFieldBase* other); - template <typename TypeHandler> - void AddAllocatedInternal(typename TypeHandler::Type* value, google::protobuf::internal::true_type); + void AddAllocatedInternal(typename TypeHandler::Type* value, std::true_type); template <typename TypeHandler> - void AddAllocatedInternal(typename TypeHandler::Type* value, google::protobuf::internal::false_type); + void AddAllocatedInternal(typename TypeHandler::Type* value, std::false_type); template <typename TypeHandler> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value, @@ -540,9 +541,9 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value); template <typename TypeHandler> - typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::true_type); + typename TypeHandler::Type* ReleaseLastInternal(std::true_type); template <typename TypeHandler> - typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::false_type); + typename TypeHandler::Type* ReleaseLastInternal(std::false_type); template<typename TypeHandler> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void SwapFallback(RepeatedPtrFieldBase* other); @@ -601,7 +602,33 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { // Reserve() and MergeFrom() to reduce code size. |extend_amount| must be > 0. void** InternalExtend(int extend_amount); + // The reflection implementation needs to call protected methods directly, + // reinterpreting pointers as being to Message instead of a specific Message + // subclass. + friend class GeneratedMessageReflection; + + // ExtensionSet stores repeated message extensions as + // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to implement + // SpaceUsedLong(), and thus need to call SpaceUsedExcludingSelfLong() + // reinterpreting MessageLite as Message. ExtensionSet also needs to make use + // of AddFromCleared(), which is not part of the public interface. + friend class ExtensionSet; + + // The MapFieldBase implementation needs to call protected methods directly, + // reinterpreting pointers as being to Message instead of a specific Message + // subclass. + friend class MapFieldBase; + + // The table-driven MergePartialFromCodedStream implementation needs to + // operate on RepeatedPtrField<MessageLite>. + friend class MergePartialFromCodedStreamHelper; + + // To parse directly into a proto2 generated class, the upb class GMR_Handlers + // needs to be able to modify a RepeatedPtrFieldBase directly. + friend class upb::google_opensource::GMR_Handlers; + friend class AccessorHelper; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); }; @@ -609,9 +636,8 @@ template <typename GenericType> class GenericTypeHandler { public: typedef GenericType Type; -#if LANG_CXX11 + typedef GenericType WeakType; static const bool Moveable = false; -#endif static inline GenericType* New(Arena* arena) { return ::google::protobuf::Arena::CreateMaybeMessage<Type>(arena); @@ -636,9 +662,6 @@ class GenericTypeHandler { static inline size_t SpaceUsedLong(const GenericType& value) { return value.SpaceUsedLong(); } - static inline const Type& default_instance() { - return Type::default_instance(); - } }; template <typename GenericType> @@ -682,13 +705,13 @@ void GenericTypeHandler<string>::Merge(const string& from, // Declarations of the specialization as we cannot define them here, as the // header that defines ProtocolMessage depends on types defined in this header. #define DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(TypeName) \ - template<> \ + template<> LIBPROTOBUF_EXPORT \ TypeName* GenericTypeHandler<TypeName>::NewFromPrototype( \ const TypeName* prototype, google::protobuf::Arena* arena); \ - template<> \ + template<> LIBPROTOBUF_EXPORT \ google::protobuf::Arena* GenericTypeHandler<TypeName>::GetArena( \ TypeName* value); \ - template<> \ + template<> LIBPROTOBUF_EXPORT \ void* GenericTypeHandler<TypeName>::GetMaybeArenaPointer( \ TypeName* value); @@ -700,42 +723,19 @@ DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message) #undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES -template <> -inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() { - // Yes, the behavior of the code is undefined, but this function is only - // called when we're already deep into the world of undefined, because the - // caller called Get(index) out of bounds. - MessageLite* null = NULL; - return *null; -} - -template <> -inline const Message& GenericTypeHandler<Message>::default_instance() { - // Yes, the behavior of the code is undefined, but this function is only - // called when we're already deep into the world of undefined, because the - // caller called Get(index) out of bounds. - Message* null = NULL; - return *null; -} - - class StringTypeHandler { public: typedef string Type; -#if LANG_CXX11 - static const bool Moveable = - std::is_move_constructible<Type>::value && - std::is_move_assignable<Type>::value; -#endif + typedef string WeakType; + static const bool Moveable = std::is_move_constructible<Type>::value && + std::is_move_assignable<Type>::value; static inline string* New(Arena* arena) { return Arena::Create<string>(arena); } -#if LANG_CXX11 static inline string* New(Arena* arena, string&& value) { return Arena::Create<string>(arena, std::move(value)); } -#endif static inline string* NewFromPrototype(const string*, ::google::protobuf::Arena* arena) { return New(arena); @@ -753,9 +753,6 @@ class StringTypeHandler { } static inline void Clear(string* value) { value->clear(); } static inline void Merge(const string& from, string* to) { *to = from; } - static inline const Type& default_instance() { - return ::google::protobuf::internal::GetEmptyString(); - } static size_t SpaceUsedLong(const string& value) { return sizeof(value) + StringSpaceUsedExcludingSelfLong(value); } @@ -766,7 +763,7 @@ class StringTypeHandler { // RepeatedPtrField is like RepeatedField, but used for repeated strings or // Messages. template <typename Element> -class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { +class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { public: RepeatedPtrField(); explicit RepeatedPtrField(::google::protobuf::Arena* arena); @@ -778,10 +775,8 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { RepeatedPtrField& operator=(const RepeatedPtrField& other); -#if LANG_CXX11 RepeatedPtrField(RepeatedPtrField&& other) noexcept; RepeatedPtrField& operator=(RepeatedPtrField&& other) noexcept; -#endif bool empty() const; int size() const; @@ -789,9 +784,7 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { const Element& Get(int index) const; Element* Mutable(int index); Element* Add(); -#if LANG_CXX11 void Add(Element&& value); -#endif const Element& operator[](int index) const { return Get(index); } Element& operator[](int index) { return *Mutable(index); } @@ -921,7 +914,7 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { // RepeatedPtrField<T> temp_field; // temp_field.AddAllocated(new T); // ... // Do something with temp_field - // temp_field.ExtractSubrange(0, temp_field.size(), NULL); + // temp_field.ExtractSubrange(0, temp_field.size(), nullptr); // If you put temp_field on the arena this fails, because the ownership // transfers to the arena at the "AddAllocated" call and is not released // anymore causing a double delete. UnsafeArenaAddAllocated prevents this. @@ -1020,11 +1013,13 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { // MergeFrom()), so we must resolve this at compile time. ExtractSubrange() // uses SFINAE to choose one of the below implementations. void ExtractSubrangeInternal(int start, int num, Element** elements, - google::protobuf::internal::true_type); + std::true_type); void ExtractSubrangeInternal(int start, int num, Element** elements, - google::protobuf::internal::false_type); + std::false_type); friend class Arena; + friend class MessageLite; + typedef void InternalArenaConstructable_; }; @@ -1035,33 +1030,25 @@ template <typename Element> inline RepeatedField<Element>::RepeatedField() : current_size_(0), total_size_(0), - rep_(NULL) { + ptr_(NULL) { } template <typename Element> inline RepeatedField<Element>::RepeatedField(Arena* arena) : current_size_(0), total_size_(0), - rep_(NULL) { - // In case arena is NULL, then we do not create rep_, as code has an invariant - // `rep_ == NULL then arena == NULL`. - if (arena != NULL) { - rep_ = reinterpret_cast<Rep*>( - ::google::protobuf::Arena::CreateArray<char>(arena, kRepHeaderSize)); - rep_->arena = arena; - } + ptr_(arena) { } template <typename Element> inline RepeatedField<Element>::RepeatedField(const RepeatedField& other) : current_size_(0), total_size_(0), - rep_(NULL) { + ptr_(NULL) { if (other.current_size_ != 0) { - Reserve(other.current_size_); - CopyArray(rep_->elements, - other.rep_->elements, other.current_size_); - current_size_ = other.current_size_; + Reserve(other.size()); + AddNAlreadyReserved(other.size()); + CopyArray(Mutable(0), &other.Get(0), other.size()); } } @@ -1070,7 +1057,7 @@ template <typename Iter> RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end) : current_size_(0), total_size_(0), - rep_(NULL) { + ptr_(NULL) { int reserve = internal::CalculateReserve(begin, end); if (reserve != -1) { Reserve(reserve); @@ -1086,9 +1073,9 @@ RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end) template <typename Element> RepeatedField<Element>::~RepeatedField() { - // See explanation in Reserve(): we need to invoke destructors here for the - // case that Element has a non-trivial destructor. - InternalDeallocate(rep_, total_size_); + if (total_size_ > 0) { + InternalDeallocate(rep(), total_size_); + } } template <typename Element> @@ -1099,8 +1086,6 @@ RepeatedField<Element>::operator=(const RepeatedField& other) { return *this; } -#if LANG_CXX11 - template <typename Element> inline RepeatedField<Element>::RepeatedField(RepeatedField&& other) noexcept : RepeatedField() { @@ -1128,8 +1113,6 @@ inline RepeatedField<Element>& RepeatedField<Element>::operator=( return *this; } -#endif // LANG_CXX11 - template <typename Element> inline bool RepeatedField<Element>::empty() const { return current_size_ == 0; @@ -1148,19 +1131,21 @@ inline int RepeatedField<Element>::Capacity() const { template<typename Element> inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) { GOOGLE_DCHECK_LT(current_size_, total_size_); - rep_->elements[current_size_++] = value; + rep()->elements[current_size_++] = value; } template<typename Element> inline Element* RepeatedField<Element>::AddAlreadyReserved() { GOOGLE_DCHECK_LT(current_size_, total_size_); - return &rep_->elements[current_size_++]; + return &rep()->elements[current_size_++]; } template<typename Element> inline Element* RepeatedField<Element>::AddNAlreadyReserved(int elements) { GOOGLE_DCHECK_LE(current_size_ + elements, total_size_); - Element* ret = &rep_->elements[current_size_]; + // Warning: total_size_ can be NULL if elements == 0 && current_size_ == 0. + // Existing callers depend on this behavior. :( + Element* ret = &ptr_.rep->elements[current_size_]; current_size_ += elements; return ret; } @@ -1170,8 +1155,8 @@ inline void RepeatedField<Element>::Resize(int new_size, const Element& value) { GOOGLE_DCHECK_GE(new_size, 0); if (new_size > current_size_) { Reserve(new_size); - std::fill(&rep_->elements[current_size_], - &rep_->elements[new_size], value); + std::fill(&rep()->elements[current_size_], + &rep()->elements[new_size], value); } current_size_ = new_size; } @@ -1180,33 +1165,33 @@ template <typename Element> inline const Element& RepeatedField<Element>::Get(int index) const { GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, current_size_); - return rep_->elements[index]; + return rep()->elements[index]; } template <typename Element> inline Element* RepeatedField<Element>::Mutable(int index) { GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, current_size_); - return &rep_->elements[index]; + return &rep()->elements[index]; } template <typename Element> inline void RepeatedField<Element>::Set(int index, const Element& value) { GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, current_size_); - rep_->elements[index] = value; + rep()->elements[index] = value; } template <typename Element> inline void RepeatedField<Element>::Add(const Element& value) { if (current_size_ == total_size_) Reserve(total_size_ + 1); - rep_->elements[current_size_++] = value; + rep()->elements[current_size_++] = value; } template <typename Element> inline Element* RepeatedField<Element>::Add() { if (current_size_ == total_size_) Reserve(total_size_ + 1); - return &rep_->elements[current_size_++]; + return &rep()->elements[current_size_++]; } template <typename Element> @@ -1245,10 +1230,10 @@ template <typename Element> inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) { GOOGLE_DCHECK_NE(&other, this); if (other.current_size_ != 0) { - Reserve(current_size_ + other.current_size_); - CopyArray(rep_->elements + current_size_, - other.rep_->elements, other.current_size_); - current_size_ += other.current_size_; + int existing_size = size(); + Reserve(existing_size + other.size()); + AddNAlreadyReserved(other.size()); + CopyArray(Mutable(existing_size), &other.Get(0), other.size()); } } @@ -1277,18 +1262,17 @@ inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase( template <typename Element> inline Element* RepeatedField<Element>::mutable_data() { - return rep_ ? rep_->elements : NULL; + return total_size_ > 0 ? rep()->elements : NULL; } template <typename Element> inline const Element* RepeatedField<Element>::data() const { - return rep_ ? rep_->elements : NULL; + return total_size_ > 0 ? rep()->elements : NULL; } template <typename Element> inline const Element* RepeatedField<Element>::unsafe_data() const { - GOOGLE_DCHECK(rep_); - return rep_->elements; + return rep()->elements; } template <typename Element> @@ -1296,7 +1280,7 @@ inline void RepeatedField<Element>::InternalSwap(RepeatedField* other) { GOOGLE_DCHECK(this != other); GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); - std::swap(rep_, other->rep_); + std::swap(ptr_, other->ptr_); std::swap(current_size_, other->current_size_); std::swap(total_size_, other->total_size_); } @@ -1323,43 +1307,43 @@ void RepeatedField<Element>::UnsafeArenaSwap(RepeatedField* other) { template <typename Element> void RepeatedField<Element>::SwapElements(int index1, int index2) { using std::swap; // enable ADL with fallback - swap(rep_->elements[index1], rep_->elements[index2]); + swap(rep()->elements[index1], rep()->elements[index2]); } template <typename Element> inline typename RepeatedField<Element>::iterator RepeatedField<Element>::begin() { - return rep_ ? rep_->elements : NULL; + return total_size_ > 0 ? rep()->elements : NULL; } template <typename Element> inline typename RepeatedField<Element>::const_iterator RepeatedField<Element>::begin() const { - return rep_ ? rep_->elements : NULL; + return total_size_ > 0 ? rep()->elements : NULL; } template <typename Element> inline typename RepeatedField<Element>::const_iterator RepeatedField<Element>::cbegin() const { - return rep_ ? rep_->elements : NULL; + return total_size_ > 0 ? rep()->elements : NULL; } template <typename Element> inline typename RepeatedField<Element>::iterator RepeatedField<Element>::end() { - return rep_ ? rep_->elements + current_size_ : NULL; + return total_size_ > 0 ? rep()->elements + current_size_ : NULL; } template <typename Element> inline typename RepeatedField<Element>::const_iterator RepeatedField<Element>::end() const { - return rep_ ? rep_->elements + current_size_ : NULL; + return total_size_ > 0 ? rep()->elements + current_size_ : NULL; } template <typename Element> inline typename RepeatedField<Element>::const_iterator RepeatedField<Element>::cend() const { - return rep_ ? rep_->elements + current_size_ : NULL; + return total_size_ > 0 ? rep()->elements + current_size_ : NULL; } template <typename Element> inline size_t RepeatedField<Element>::SpaceUsedExcludingSelfLong() const { - return rep_ ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; + return total_size_ > 0 ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; } // Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant @@ -1367,7 +1351,7 @@ inline size_t RepeatedField<Element>::SpaceUsedExcludingSelfLong() const { template <typename Element> void RepeatedField<Element>::Reserve(int new_size) { if (total_size_ >= new_size) return; - Rep* old_rep = rep_; + Rep* old_rep = total_size_ > 0 ? rep() : NULL; Arena* arena = GetArenaNoVirtual(); new_size = std::max(google::protobuf::internal::kMinRepeatedFieldAllocationSize, std::max(total_size_ * 2, new_size)); @@ -1377,12 +1361,12 @@ void RepeatedField<Element>::Reserve(int new_size) { << "Requested size is too large to fit into size_t."; size_t bytes = kRepHeaderSize + sizeof(Element) * static_cast<size_t>(new_size); if (arena == NULL) { - rep_ = static_cast<Rep*>(::operator new(bytes)); + ptr_.rep = static_cast<Rep*>(::operator new(bytes)); } else { - rep_ = reinterpret_cast<Rep*>( + ptr_.rep = reinterpret_cast<Rep*>( ::google::protobuf::Arena::CreateArray<char>(arena, bytes)); } - rep_->arena = arena; + ptr_.rep->arena = arena; int old_total_size = total_size_; total_size_ = new_size; // Invoke placement-new on newly allocated elements. We shouldn't have to do @@ -1394,13 +1378,13 @@ void RepeatedField<Element>::Reserve(int new_size) { // effect unless its side-effects are required for correctness. // Note that we do this before MoveArray() below because Element's copy // assignment implementation will want an initialized instance first. - Element* e = &rep_->elements[0]; - Element* limit = &rep_->elements[total_size_]; + Element* e = &rep()->elements[0]; + Element* limit = e + total_size_; for (; e < limit; e++) { new (e) Element; } if (current_size_ > 0) { - MoveArray(rep_->elements, old_rep->elements, current_size_); + MoveArray(&rep()->elements[0], old_rep->elements, current_size_); } // Likewise, we need to invoke destructors on the old array. @@ -1516,14 +1500,13 @@ inline int RepeatedPtrFieldBase::size() const { } template <typename TypeHandler> -inline const typename TypeHandler::Type& +inline const typename TypeHandler::WeakType& RepeatedPtrFieldBase::Get(int index) const { GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, current_size_); return *cast<TypeHandler>(rep_->elements[index]); } - template <typename TypeHandler> inline typename TypeHandler::Type* RepeatedPtrFieldBase::Mutable(int index) { @@ -1555,11 +1538,10 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add( return result; } -#if LANG_CXX11 template <typename TypeHandler> inline void RepeatedPtrFieldBase::Add( typename TypeHandler::Type&& value, - internal::enable_if<TypeHandler::Moveable>*) { + std::enable_if<TypeHandler::Moveable>*) { if (rep_ != NULL && current_size_ < rep_->allocated_size) { *cast<TypeHandler>(rep_->elements[current_size_++]) = std::move(value); return; @@ -1572,7 +1554,6 @@ inline void RepeatedPtrFieldBase::Add( TypeHandler::New(arena_, std::move(value)); rep_->elements[current_size_++] = result; } -#endif template <typename TypeHandler> inline void RepeatedPtrFieldBase::RemoveLast() { @@ -1632,18 +1613,18 @@ void RepeatedPtrFieldBase::MergeFromInnerLoop( // to avoid a branch within the loop. for (int i = 0; i < already_allocated && i < length; i++) { // Already allocated: use existing element. - typename TypeHandler::Type* other_elem = - reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]); - typename TypeHandler::Type* new_elem = - reinterpret_cast<typename TypeHandler::Type*>(our_elems[i]); + typename TypeHandler::WeakType* other_elem = + reinterpret_cast<typename TypeHandler::WeakType*>(other_elems[i]); + typename TypeHandler::WeakType* new_elem = + reinterpret_cast<typename TypeHandler::WeakType*>(our_elems[i]); TypeHandler::Merge(*other_elem, new_elem); } Arena* arena = GetArenaNoVirtual(); for (int i = already_allocated; i < length; i++) { // Not allocated: alloc a new element first, then merge it. - typename TypeHandler::Type* other_elem = - reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]); - typename TypeHandler::Type* new_elem = + typename TypeHandler::WeakType* other_elem = + reinterpret_cast<typename TypeHandler::WeakType*>(other_elems[i]); + typename TypeHandler::WeakType* new_elem = TypeHandler::NewFromPrototype(other_elem, arena); TypeHandler::Merge(*other_elem, new_elem); our_elems[i] = new_elem; @@ -1715,7 +1696,7 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() { template <typename TypeHandler> void RepeatedPtrFieldBase::AddAllocatedInternal( typename TypeHandler::Type* value, - google::protobuf::internal::true_type) { + std::true_type) { Arena* element_arena = reinterpret_cast<Arena*>( TypeHandler::GetMaybeArenaPointer(value)); Arena* arena = GetArenaNoVirtual(); @@ -1765,7 +1746,7 @@ void RepeatedPtrFieldBase::AddAllocatedSlowWithCopy( template <typename TypeHandler> void RepeatedPtrFieldBase::AddAllocatedInternal( typename TypeHandler::Type* value, - google::protobuf::internal::false_type) { + std::false_type) { if (rep_ && rep_->allocated_size < total_size_) { // Fast path: underlying arena representation (tagged pointer) is equal to // our arena pointer, and we can add to array without resizing it (at least @@ -1815,7 +1796,7 @@ void RepeatedPtrFieldBase::UnsafeArenaAddAllocated( // ReleaseLast() for types that implement merge/copy behavior. template <typename TypeHandler> inline typename TypeHandler::Type* -RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::true_type) { +RepeatedPtrFieldBase::ReleaseLastInternal(std::true_type) { // First, release an element. typename TypeHandler::Type* result = UnsafeArenaReleaseLast<TypeHandler>(); // Now perform a copy if we're on an arena. @@ -1836,7 +1817,7 @@ RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::true_type) // case. template <typename TypeHandler> inline typename TypeHandler::Type* -RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::false_type) { +RepeatedPtrFieldBase::ReleaseLastInternal(std::false_type) { GOOGLE_DCHECK(GetArenaNoVirtual() == NULL) << "ReleaseLast() called on a RepeatedPtrField that is on an arena, " << "with a type that does not implement MergeFrom. This is unsafe; " @@ -1942,8 +1923,6 @@ inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=( return *this; } -#if LANG_CXX11 - template <typename Element> inline RepeatedPtrField<Element>::RepeatedPtrField( RepeatedPtrField&& other) noexcept @@ -1972,8 +1951,6 @@ inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=( return *this; } -#endif // LANG_CXX11 - template <typename Element> inline bool RepeatedPtrField<Element>::empty() const { return RepeatedPtrFieldBase::empty(); @@ -2000,12 +1977,10 @@ inline Element* RepeatedPtrField<Element>::Add() { return RepeatedPtrFieldBase::Add<TypeHandler>(); } -#if LANG_CXX11 template <typename Element> inline void RepeatedPtrField<Element>::Add(Element&& value) { RepeatedPtrFieldBase::Add<TypeHandler>(std::move(value)); } -#endif template <typename Element> inline void RepeatedPtrField<Element>::RemoveLast() { @@ -2035,7 +2010,7 @@ inline void RepeatedPtrField<Element>::ExtractSubrange( // behavior. template <typename Element> inline void RepeatedPtrField<Element>::ExtractSubrangeInternal( - int start, int num, Element** elements, google::protobuf::internal::true_type) { + int start, int num, Element** elements, std::true_type) { GOOGLE_DCHECK_GE(start, 0); GOOGLE_DCHECK_GE(num, 0); GOOGLE_DCHECK_LE(start + num, size()); @@ -2068,7 +2043,7 @@ inline void RepeatedPtrField<Element>::ExtractSubrangeInternal( // behavior. template<typename Element> inline void RepeatedPtrField<Element>::ExtractSubrangeInternal( - int start, int num, Element** elements, google::protobuf::internal::false_type) { + int start, int num, Element** elements, std::false_type) { // This case is identical to UnsafeArenaExtractSubrange(). However, since // ExtractSubrange() must return heap-allocated objects by contract, and we // cannot fulfill this contract if we are an on arena, we must GOOGLE_DCHECK() that @@ -2240,7 +2215,7 @@ class RepeatedPtrIterator // Shadow the value_type in std::iterator<> because const_iterator::value_type // needs to be T, not const T. - typedef typename remove_const<Element>::type value_type; + typedef typename std::remove_const<Element>::type value_type; // Let the compiler know that these are type names, so we don't have to // write "typename" in front of them everywhere. @@ -2258,7 +2233,7 @@ class RepeatedPtrIterator : it_(other.it_) { // Force a compiler error if the other type is not convertible to ours. if (false) { - implicit_cast<Element*>(static_cast<OtherElement*>(NULL)); + implicit_cast<Element*>(static_cast<OtherElement*>(nullptr)); } } @@ -2334,7 +2309,7 @@ class RepeatedPtrOverPtrsIterator // Shadow the value_type in std::iterator<> because const_iterator::value_type // needs to be T, not const T. - typedef typename remove_const<Element>::type value_type; + typedef typename std::remove_const<Element>::type value_type; // Let the compiler know that these are type names, so we don't have to // write "typename" in front of them everywhere. @@ -2519,12 +2494,10 @@ template<typename T> class RepeatedPtrFieldBackInsertIterator *field_->Add() = *ptr_to_value; return *this; } -#if LANG_CXX11 RepeatedPtrFieldBackInsertIterator<T>& operator=(T&& value) { *field_->Add() = std::move(value); return *this; } -#endif RepeatedPtrFieldBackInsertIterator<T>& operator*() { return *this; } @@ -2639,7 +2612,7 @@ AllocatedRepeatedPtrFieldBackInserter( // RepeatedPtrField<T> temp_field; // temp_field.AddAllocated(new T); // ... // Do something with temp_field -// temp_field.ExtractSubrange(0, temp_field.size(), NULL); +// temp_field.ExtractSubrange(0, temp_field.size(), nullptr); // If you put temp_field on the arena this fails, because the ownership // transfers to the arena at the "AddAllocated" call and is not released anymore // causing a double delete. Using UnsafeArenaAddAllocated prevents this. |