From d36c0c538a545fac5d9db6ba65c525246d4efa95 Mon Sep 17 00:00:00 2001 From: Feng Xiao Date: Wed, 29 Mar 2017 14:32:48 -0700 Subject: Down-integrate from google3. --- src/google/protobuf/repeated_field.h | 168 ++++++++++++++++++++++------------- 1 file changed, 106 insertions(+), 62 deletions(-) (limited to 'src/google/protobuf/repeated_field.h') diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index db5893b5..074319e8 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -51,8 +51,9 @@ #include #endif -#include #include +#include +#include #include #include #include @@ -76,6 +77,8 @@ class Message; namespace internal { +class MergePartialFromCodedStreamHelper; + static const int kMinRepeatedFieldAllocationSize = 4; // A utility function for logging that doesn't need any template types. @@ -155,6 +158,7 @@ class RepeatedField PROTOBUF_FINAL { // The new element is uninitialized if |Element| is a POD type. // Should be called only if Capacity() > Size(). Element* AddAlreadyReserved(); + Element* AddNAlreadyReserved(int elements); int Capacity() const; // Like STL resize. Uses value to fill appended elements. @@ -216,7 +220,11 @@ class RepeatedField PROTOBUF_FINAL { // Returns the number of bytes used by the repeated field, excluding // sizeof(*this) - int SpaceUsedExcludingSelf() const; + size_t SpaceUsedExcludingSelfLong() const; + + int SpaceUsedExcludingSelf() const { + return internal::ToIntSize(SpaceUsedExcludingSelfLong()); + } // Removes the element referenced by position. // @@ -238,6 +246,11 @@ class RepeatedField PROTOBUF_FINAL { return GetArenaNoVirtual(); } + // For internal use only. + // + // This is public due to it being called by generated code. + inline void InternalSwap(RepeatedField* other); + private: static const int kInitialSize = 0; // A note on the representation here (see also comment below for @@ -276,8 +289,6 @@ class RepeatedField PROTOBUF_FINAL { // Copy the elements of |from| into |to|. void CopyArray(Element* to, const Element* from, int size); - inline void InternalSwap(RepeatedField* other); - // Internal helper expected by Arena methods. inline Arena* GetArenaNoVirtual() const { return (rep_ == NULL) ? NULL : rep_->arena; @@ -303,6 +314,9 @@ class RepeatedField PROTOBUF_FINAL { } } } + + friend class internal::WireFormatLite; + const Element* unsafe_data() const; }; template @@ -321,7 +335,8 @@ namespace internal { // shouldn't be necessary, but our compiler doesn't optimize std::copy very // effectively. template ::value> + bool HasTrivialCopy = + has_trivial_copy::value> struct ElementCopier { void operator()(Element* to, const Element* from, int array_size); }; @@ -335,8 +350,8 @@ namespace internal { // exist on the contained type. In particular, we rely on MergeFrom() existing // as a general proxy for the fact that a copy will work, and we also provide a // specific override for string*. -template -struct TypeImplementsMergeBehavior { +template +struct TypeImplementsMergeBehaviorProbeForMergeFrom { typedef char HasMerge; typedef long HasNoMerge; @@ -360,8 +375,13 @@ struct TypeImplementsMergeBehavior { (sizeof(Check(0)) == sizeof(HasMerge))> type; }; -template<> -struct TypeImplementsMergeBehavior< ::std::string > { +template +struct TypeImplementsMergeBehavior : + TypeImplementsMergeBehaviorProbeForMergeFrom {}; + + +template <> +struct TypeImplementsMergeBehavior< ::std::string> { typedef google::protobuf::internal::true_type type; }; @@ -379,7 +399,7 @@ struct TypeImplementsMergeBehavior< ::std::string > { // static void Merge(const Type& from, Type* to); // // // Only needs to be implemented if SpaceUsedExcludingSelf() is called. -// static int SpaceUsed(const Type&); +// static int SpaceUsedLong(const Type&); // }; class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { protected: @@ -389,10 +409,10 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { friend class GeneratedMessageReflection; // ExtensionSet stores repeated message extensions as - // RepeatedPtrField, but non-lite ExtensionSets need to - // implement SpaceUsed(), and thus need to call SpaceUsedExcludingSelf() - // reinterpreting MessageLite as Message. ExtensionSet also needs to make - // use of AddFromCleared(), which is not part of the public interface. + // RepeatedPtrField, 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, @@ -400,6 +420,10 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { // subclass. friend class MapFieldBase; + // The table-driven MergePartialFromCodedStream implementation needs to + // operate on RepeatedPtrField. + 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; @@ -426,7 +450,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { #if LANG_CXX11 template void Add(typename TypeHandler::Type&& value, - std::enable_if* dummy = NULL); + internal::enable_if* dummy = NULL); #endif template @@ -459,7 +483,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { void SwapElements(int index1, int index2); template - int SpaceUsedExcludingSelf() const; + size_t SpaceUsedExcludingSelfLong() const; // Advanced memory management -------------------------------------- @@ -583,14 +607,12 @@ class GenericTypeHandler { #if LANG_CXX11 static const bool Moveable = false; #endif + static inline GenericType* New(Arena* arena) { return ::google::protobuf::Arena::CreateMaybeMessage( arena, static_cast(0)); } - // We force NewFromPrototype() to be non-inline to reduce code size: - // else, several other methods get inlined copies of message types' - // constructors. - GOOGLE_ATTRIBUTE_NOINLINE static GenericType* NewFromPrototype( + static inline GenericType* NewFromPrototype( const GenericType* prototype, ::google::protobuf::Arena* arena = NULL); static inline void Delete(GenericType* value, Arena* arena) { if (arena == NULL) { @@ -607,8 +629,8 @@ class GenericTypeHandler { static inline void Clear(GenericType* value) { value->Clear(); } GOOGLE_ATTRIBUTE_NOINLINE static void Merge(const GenericType& from, GenericType* to); - static inline int SpaceUsed(const GenericType& value) { - return value.SpaceUsed(); + static inline size_t SpaceUsedLong(const GenericType& value) { + return value.SpaceUsedLong(); } static inline const Type& default_instance() { return Type::default_instance(); @@ -626,11 +648,9 @@ void GenericTypeHandler::Merge(const GenericType& from, to->MergeFrom(from); } -// NewFromPrototype() and Merge() cannot be defined here; if they're declared -// inline the compiler will complain about not matching GOOGLE_ATTRIBUTE_NOINLINE -// above, and if not, compilation will result in multiple definitions. These -// are therefore declared as specializations here and defined in -// message_lite.cc. +// NewFromPrototype() and Merge() are not defined inline here, as we will need +// to do a virtual function dispatch anyways to go from Message* to call +// New/Merge. template<> MessageLite* GenericTypeHandler::NewFromPrototype( const MessageLite* prototype, google::protobuf::Arena* arena); @@ -708,7 +728,7 @@ class StringTypeHandler { return Arena::Create(arena); } #if LANG_CXX11 - static inline string* New(Arena* arena, std::string&& value) { + static inline string* New(Arena* arena, string&& value) { return Arena::Create(arena, std::move(value)); } #endif @@ -732,12 +752,11 @@ class StringTypeHandler { static inline const Type& default_instance() { return ::google::protobuf::internal::GetEmptyString(); } - static int SpaceUsed(const string& value) { - return static_cast(sizeof(value)) + StringSpaceUsedExcludingSelf(value); + static size_t SpaceUsedLong(const string& value) { + return sizeof(value) + StringSpaceUsedExcludingSelfLong(value); } }; - } // namespace internal // RepeatedPtrField is like RepeatedField, but used for repeated strings or @@ -842,10 +861,11 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { // Custom STL-like iterator that iterates over and returns the underlying // pointers to Element rather than Element itself. - typedef internal::RepeatedPtrOverPtrsIterator - pointer_iterator; - typedef internal::RepeatedPtrOverPtrsIterator - const_pointer_iterator; + typedef internal::RepeatedPtrOverPtrsIterator + pointer_iterator; + typedef internal::RepeatedPtrOverPtrsIterator + const_pointer_iterator; pointer_iterator pointer_begin(); const_pointer_iterator pointer_begin() const; pointer_iterator pointer_end(); @@ -853,7 +873,11 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { // Returns (an estimate of) the number of bytes used by the repeated field, // excluding sizeof(*this). - int SpaceUsedExcludingSelf() const; + size_t SpaceUsedExcludingSelfLong() const; + + int SpaceUsedExcludingSelf() const { + return internal::ToIntSize(SpaceUsedExcludingSelfLong()); + } // Advanced memory management -------------------------------------- // When hardcore memory management becomes necessary -- as it sometimes @@ -970,6 +994,11 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { return GetArenaNoVirtual(); } + // For internal use only. + // + // This is public due to it being called by generated code. + using RepeatedPtrFieldBase::InternalSwap; + private: // Note: RepeatedPtrField SHOULD NOT be subclassed by users. class TypeHandler; @@ -1088,6 +1117,14 @@ inline Element* RepeatedField::AddAlreadyReserved() { return &rep_->elements[current_size_++]; } +template +inline Element* RepeatedField::AddNAlreadyReserved(int elements) { + GOOGLE_DCHECK_LE(current_size_ + elements, total_size_); + Element* ret = &rep_->elements[current_size_]; + current_size_ += elements; + return ret; +} + template inline void RepeatedField::Resize(int new_size, const Element& value) { GOOGLE_DCHECK_GE(new_size, 0); @@ -1208,9 +1245,17 @@ inline const Element* RepeatedField::data() const { return rep_ ? rep_->elements : NULL; } +template +inline const Element* RepeatedField::unsafe_data() const { + GOOGLE_DCHECK(rep_); + return rep_->elements; +} template inline void RepeatedField::InternalSwap(RepeatedField* other) { + GOOGLE_DCHECK(this != other); + GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + std::swap(rep_, other->rep_); std::swap(current_size_, other->current_size_); std::swap(total_size_, other->total_size_); @@ -1219,7 +1264,7 @@ inline void RepeatedField::InternalSwap(RepeatedField* other) { template void RepeatedField::Swap(RepeatedField* other) { if (this == other) return; - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { + if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { InternalSwap(other); } else { RepeatedField temp(other->GetArenaNoVirtual()); @@ -1232,7 +1277,6 @@ void RepeatedField::Swap(RepeatedField* other) { template void RepeatedField::UnsafeArenaSwap(RepeatedField* other) { if (this == other) return; - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); InternalSwap(other); } @@ -1274,9 +1318,8 @@ RepeatedField::cend() const { } template -inline int RepeatedField::SpaceUsedExcludingSelf() const { - return rep_ ? - (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; +inline size_t RepeatedField::SpaceUsedExcludingSelfLong() const { + return rep_ ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; } // Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant @@ -1288,9 +1331,9 @@ void RepeatedField::Reserve(int new_size) { Arena* arena = GetArenaNoVirtual(); new_size = std::max(google::protobuf::internal::kMinRepeatedFieldAllocationSize, std::max(total_size_ * 2, new_size)); - GOOGLE_CHECK_LE(static_cast(new_size), - (std::numeric_limits::max() - kRepHeaderSize) / - sizeof(Element)) + GOOGLE_DCHECK_LE( + static_cast(new_size), + (std::numeric_limits::max() - kRepHeaderSize) / sizeof(Element)) << "Requested size is too large to fit into size_t."; size_t bytes = kRepHeaderSize + sizeof(Element) * new_size; if (arena == NULL) { @@ -1476,9 +1519,10 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add( template inline void RepeatedPtrFieldBase::Add( typename TypeHandler::Type&& value, - std::enable_if*) { + internal::enable_if*) { if (rep_ != NULL && current_size_ < rep_->allocated_size) { - cast(rep_->elements[current_size_++]) = std::move(value); + *cast(rep_->elements[current_size_++]) = std::move(value); + return; } if (!rep_ || rep_->allocated_size == total_size_) { Reserve(total_size_ + 1); @@ -1606,11 +1650,11 @@ inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) { } template -inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const { - int allocated_bytes = total_size_ * sizeof(void*); +inline size_t RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() const { + size_t allocated_bytes = total_size_ * sizeof(void*); if (rep_ != NULL) { for (int i = 0; i < rep_->allocated_size; ++i) { - allocated_bytes += TypeHandler::SpaceUsed( + allocated_bytes += TypeHandler::SpaceUsedLong( *cast(rep_->elements[i])); } allocated_bytes += kRepHeaderSize; @@ -1819,7 +1863,6 @@ class RepeatedPtrField::TypeHandler : public internal::StringTypeHandler { }; - template inline RepeatedPtrField::RepeatedPtrField() : RepeatedPtrFieldBase() {} @@ -2036,7 +2079,6 @@ inline void RepeatedPtrField::Swap(RepeatedPtrField* other) { template inline void RepeatedPtrField::UnsafeArenaSwap( RepeatedPtrField* other) { - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); if (this == other) return; RepeatedPtrFieldBase::InternalSwap(other); @@ -2053,8 +2095,8 @@ inline Arena* RepeatedPtrField::GetArenaNoVirtual() const { } template -inline int RepeatedPtrField::SpaceUsedExcludingSelf() const { - return RepeatedPtrFieldBase::SpaceUsedExcludingSelf(); +inline size_t RepeatedPtrField::SpaceUsedExcludingSelfLong() const { + return RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong(); } template @@ -2212,18 +2254,17 @@ class RepeatedPtrIterator // the array. // The VoidPtr template parameter holds the type-agnostic pointer value // referenced by the iterator. It should either be "void *" for a mutable -// iterator, or "const void *" for a constant iterator. -template +// iterator, or "const void* const" for a constant iterator. +template class RepeatedPtrOverPtrsIterator - : public std::iterator { + : public std::iterator { public: typedef RepeatedPtrOverPtrsIterator iterator; - typedef std::iterator< - std::random_access_iterator_tag, Element*> superclass; + typedef std::iterator superclass; // Shadow the value_type in std::iterator<> because const_iterator::value_type // needs to be T, not const T. - typedef typename remove_const::type value_type; + typedef typename remove_const::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. @@ -2235,7 +2276,7 @@ class RepeatedPtrOverPtrsIterator explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {} // dereferenceable - reference operator*() const { return *reinterpret_cast(it_); } + reference operator*() const { return *reinterpret_cast(it_); } pointer operator->() const { return &(operator*()); } // {inc,dec}rementable @@ -2291,6 +2332,9 @@ class RepeatedPtrOverPtrsIterator }; void RepeatedPtrFieldBase::InternalSwap(RepeatedPtrFieldBase* other) { + GOOGLE_DCHECK(this != other); + GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + std::swap(rep_, other->rep_); std::swap(current_size_, other->current_size_); std::swap(total_size_, other->total_size_); @@ -2337,7 +2381,7 @@ RepeatedPtrField::pointer_begin() { template inline typename RepeatedPtrField::const_pointer_iterator RepeatedPtrField::pointer_begin() const { - return const_pointer_iterator(const_cast(raw_mutable_data())); + return const_pointer_iterator(const_cast(raw_data())); } template inline typename RepeatedPtrField::pointer_iterator @@ -2348,7 +2392,7 @@ template inline typename RepeatedPtrField::const_pointer_iterator RepeatedPtrField::pointer_end() const { return const_pointer_iterator( - const_cast(raw_mutable_data() + size())); + const_cast(raw_data() + size())); } -- cgit v1.2.3