aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/repeated_field.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/repeated_field.h')
-rw-r--r--src/google/protobuf/repeated_field.h553
1 files changed, 323 insertions, 230 deletions
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index db5893b5..b47ea994 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -51,15 +51,17 @@
#include <algorithm>
#endif
-#include <string>
#include <iterator>
+#include <limits>
+#include <string>
#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/generated_message_util.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.
@@ -76,6 +78,8 @@ class Message;
namespace internal {
+class MergePartialFromCodedStreamHelper;
+
static const int kMinRepeatedFieldAllocationSize = 4;
// A utility function for logging that doesn't need any template types.
@@ -83,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>
@@ -105,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);
@@ -116,6 +120,9 @@ class RepeatedField PROTOBUF_FINAL {
RepeatedField& operator=(const RepeatedField& other);
+ RepeatedField(RepeatedField&& other) noexcept;
+ RepeatedField& operator=(RepeatedField&& other) noexcept;
+
bool empty() const;
int size() const;
@@ -155,6 +162,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 +224,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 +250,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
@@ -261,13 +278,24 @@ 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_;
+
// Move the contents of |from| into |to|, possibly clobbering |from| in the
// process. For primitive types this is just a memcpy(), but it could be
// specialized for non-primitive types to, say, swap each element instead.
@@ -276,11 +304,9 @@ 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;
+ return (total_size_ == 0) ? ptr_.arena : ptr_.rep->arena;
}
// Internal helper to delete all elements and deallocate the storage.
@@ -291,7 +317,7 @@ class RepeatedField PROTOBUF_FINAL {
Element* e = &rep->elements[0];
Element* limit = &rep->elements[size];
for (; e < limit; e++) {
- e->Element::~Element();
+ e->~Element();
}
if (rep->arena == NULL) {
#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
@@ -303,6 +329,9 @@ class RepeatedField PROTOBUF_FINAL {
}
}
}
+
+ friend class internal::WireFormatLite;
+ const Element* unsafe_data() const;
};
template<typename Element>
@@ -321,7 +350,8 @@ namespace internal {
// shouldn't be necessary, but our compiler doesn't optimize std::copy very
// effectively.
template <typename Element,
- bool HasTrivialCopy = has_trivial_copy<Element>::value>
+ bool HasTrivialCopy =
+ std::is_pod<Element>::value>
struct ElementCopier {
void operator()(Element* to, const Element* from, int array_size);
};
@@ -335,8 +365,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<typename T>
-struct TypeImplementsMergeBehavior {
+template <typename T>
+struct TypeImplementsMergeBehaviorProbeForMergeFrom {
typedef char HasMerge;
typedef long HasNoMerge;
@@ -355,14 +385,19 @@ struct TypeImplementsMergeBehavior {
CheckType<U, bool, &U::MergeFrom>*);
template<typename U> static HasNoMerge Check(...);
- // Resovles 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;
};
-template<>
-struct TypeImplementsMergeBehavior< ::std::string > {
- typedef google::protobuf::internal::true_type type;
+template <typename T, typename = void>
+struct TypeImplementsMergeBehavior :
+ TypeImplementsMergeBehaviorProbeForMergeFrom<T> {};
+
+
+template <>
+struct TypeImplementsMergeBehavior< ::std::string> {
+ typedef std::true_type type;
};
// This is the common base class for RepeatedPtrFields. It deals only in void*
@@ -373,37 +408,21 @@ 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);
//
// // Only needs to be implemented if SpaceUsedExcludingSelf() is called.
-// static int SpaceUsed(const Type&);
+// static int SpaceUsedLong(const Type&);
// };
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 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.
- 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;
-
- // 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() {}
@@ -416,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,
- std::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);
@@ -453,14 +488,13 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
const typename TypeHandler::Type* const* data() const;
- template <typename TypeHandler>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(RepeatedPtrFieldBase* other);
+ template <typename TypeHandler> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
+ void Swap(RepeatedPtrFieldBase* other);
void SwapElements(int index1, int index2);
template <typename TypeHandler>
- int SpaceUsedExcludingSelf() const;
-
+ size_t SpaceUsedExcludingSelfLong() const;
// Advanced memory management --------------------------------------
@@ -494,29 +528,24 @@ 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_ATTRIBUTE_NOINLINE
+ template <typename TypeHandler> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value,
Arena* value_arena,
Arena* my_arena);
- template <typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
+ template <typename TypeHandler> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
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_ATTRIBUTE_NOINLINE
+ template<typename TypeHandler> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
void SwapFallback(RepeatedPtrFieldBase* other);
inline Arena* GetArenaNoVirtual() const {
@@ -573,6 +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);
};
@@ -580,17 +636,13 @@ 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, static_cast<GenericType*>(0));
+ return ::google::protobuf::Arena::CreateMaybeMessage<Type>(arena);
}
- // 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) {
@@ -605,13 +657,10 @@ 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 const Type& default_instance() {
- return Type::default_instance();
+ GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
+ static void Merge(const GenericType& from, GenericType* to);
+ static inline size_t SpaceUsedLong(const GenericType& value) {
+ return value.SpaceUsedLong();
}
};
@@ -626,11 +675,9 @@ void GenericTypeHandler<GenericType>::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<MessageLite>::NewFromPrototype(
const MessageLite* prototype, google::protobuf::Arena* arena);
@@ -676,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, std::string&& value) {
+ 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);
@@ -729,21 +753,17 @@ 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 int SpaceUsed(const string& value) {
- return static_cast<int>(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
// 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);
@@ -755,15 +775,16 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase {
RepeatedPtrField& operator=(const RepeatedPtrField& other);
+ RepeatedPtrField(RepeatedPtrField&& other) noexcept;
+ RepeatedPtrField& operator=(RepeatedPtrField&& other) noexcept;
+
bool empty() const;
int size() const;
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); }
@@ -842,10 +863,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<Element, void*>
- pointer_iterator;
- typedef internal::RepeatedPtrOverPtrsIterator<const Element, const void*>
- const_pointer_iterator;
+ typedef internal::RepeatedPtrOverPtrsIterator<Element*, void*>
+ pointer_iterator;
+ typedef internal::RepeatedPtrOverPtrsIterator<const Element* const,
+ const void* const>
+ const_pointer_iterator;
pointer_iterator pointer_begin();
const_pointer_iterator pointer_begin() const;
pointer_iterator pointer_end();
@@ -853,7 +875,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
@@ -888,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.
@@ -970,6 +996,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;
@@ -982,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_;
};
@@ -997,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());
}
}
@@ -1032,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);
@@ -1048,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>
@@ -1062,6 +1087,33 @@ RepeatedField<Element>::operator=(const RepeatedField& other) {
}
template <typename Element>
+inline RepeatedField<Element>::RepeatedField(RepeatedField&& other) noexcept
+ : RepeatedField() {
+ // We don't just call Swap(&other) here because it would perform 3 copies if
+ // the two fields are on different arenas.
+ if (other.GetArenaNoVirtual()) {
+ CopyFrom(other);
+ } else {
+ InternalSwap(&other);
+ }
+}
+
+template <typename Element>
+inline RepeatedField<Element>& RepeatedField<Element>::operator=(
+ RepeatedField&& other) noexcept {
+ // We don't just call Swap(&other) here because it would perform 3 copies if
+ // the two fields are on different arenas.
+ if (this != &other) {
+ if (this->GetArenaNoVirtual() != other.GetArenaNoVirtual()) {
+ CopyFrom(other);
+ } else {
+ InternalSwap(&other);
+ }
+ }
+ return *this;
+}
+
+template <typename Element>
inline bool RepeatedField<Element>::empty() const {
return current_size_ == 0;
}
@@ -1079,13 +1131,23 @@ 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_);
+ // 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;
}
template<typename Element>
@@ -1093,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;
}
@@ -1103,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>
@@ -1168,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());
}
}
@@ -1200,18 +1262,25 @@ 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 {
+ return rep()->elements;
+}
template <typename Element>
inline void RepeatedField<Element>::InternalSwap(RepeatedField* other) {
- std::swap(rep_, other->rep_);
+ GOOGLE_DCHECK(this != other);
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+
+ std::swap(ptr_, other->ptr_);
std::swap(current_size_, other->current_size_);
std::swap(total_size_, other->total_size_);
}
@@ -1219,7 +1288,7 @@ inline void RepeatedField<Element>::InternalSwap(RepeatedField* other) {
template <typename Element>
void RepeatedField<Element>::Swap(RepeatedField* other) {
if (this == other) return;
- if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
InternalSwap(other);
} else {
RepeatedField<Element> temp(other->GetArenaNoVirtual());
@@ -1232,51 +1301,49 @@ void RepeatedField<Element>::Swap(RepeatedField* other) {
template <typename Element>
void RepeatedField<Element>::UnsafeArenaSwap(RepeatedField* other) {
if (this == other) return;
- GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
InternalSwap(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 int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
- return rep_ ?
- (total_size_ * sizeof(Element) + kRepHeaderSize) : 0;
+inline size_t RepeatedField<Element>::SpaceUsedExcludingSelfLong() const {
+ return total_size_ > 0 ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0;
}
// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant
@@ -1284,22 +1351,22 @@ inline int RepeatedField<Element>::SpaceUsedExcludingSelf() 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));
- GOOGLE_CHECK_LE(static_cast<size_t>(new_size),
- (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
- sizeof(Element))
+ GOOGLE_DCHECK_LE(
+ static_cast<size_t>(new_size),
+ (std::numeric_limits<size_t>::max() - kRepHeaderSize) / sizeof(Element))
<< "Requested size is too large to fit into size_t.";
- size_t bytes = kRepHeaderSize + sizeof(Element) * new_size;
+ 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
@@ -1311,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.
@@ -1356,7 +1423,7 @@ void ElementCopier<Element, HasTrivialCopy>::operator()(
template <typename Element>
struct ElementCopier<Element, true> {
void operator()(Element* to, const Element* from, int array_size) {
- memcpy(to, from, array_size * sizeof(Element));
+ memcpy(to, from, static_cast<size_t>(array_size) * sizeof(Element));
}
};
@@ -1433,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) {
@@ -1472,13 +1538,13 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add(
return result;
}
-#if LANG_CXX11
template <typename TypeHandler>
inline void RepeatedPtrFieldBase::Add(
typename TypeHandler::Type&& value,
std::enable_if<TypeHandler::Moveable>*) {
if (rep_ != NULL && current_size_ < rep_->allocated_size) {
- cast<TypeHandler>(rep_->elements[current_size_++]) = std::move(value);
+ *cast<TypeHandler>(rep_->elements[current_size_++]) = std::move(value);
+ return;
}
if (!rep_ || rep_->allocated_size == total_size_) {
Reserve(total_size_ + 1);
@@ -1488,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() {
@@ -1548,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;
@@ -1606,11 +1671,11 @@ inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) {
}
template <typename TypeHandler>
-inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const {
- int allocated_bytes = total_size_ * sizeof(void*);
+inline size_t RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() const {
+ size_t allocated_bytes = static_cast<size_t>(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<TypeHandler>(rep_->elements[i]));
}
allocated_bytes += kRepHeaderSize;
@@ -1631,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();
@@ -1649,7 +1714,6 @@ void RepeatedPtrFieldBase::AddAllocatedInternal(
elems[current_size_] = value;
current_size_ = current_size_ + 1;
rep_->allocated_size = rep_->allocated_size + 1;
- return;
} else {
AddAllocatedSlowWithCopy<TypeHandler>(
value, TypeHandler::GetArena(value), arena);
@@ -1682,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
@@ -1696,7 +1760,6 @@ void RepeatedPtrFieldBase::AddAllocatedInternal(
elems[current_size_] = value;
current_size_ = current_size_ + 1;
++rep_->allocated_size;
- return;
} else {
UnsafeArenaAddAllocated<TypeHandler>(value);
}
@@ -1733,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.
@@ -1754,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; "
@@ -1819,7 +1882,6 @@ class RepeatedPtrField<string>::TypeHandler
: public internal::StringTypeHandler {
};
-
template <typename Element>
inline RepeatedPtrField<Element>::RepeatedPtrField()
: RepeatedPtrFieldBase() {}
@@ -1862,6 +1924,34 @@ inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
}
template <typename Element>
+inline RepeatedPtrField<Element>::RepeatedPtrField(
+ RepeatedPtrField&& other) noexcept
+ : RepeatedPtrField() {
+ // We don't just call Swap(&other) here because it would perform 3 copies if
+ // the two fields are on different arenas.
+ if (other.GetArenaNoVirtual()) {
+ CopyFrom(other);
+ } else {
+ InternalSwap(&other);
+ }
+}
+
+template <typename Element>
+inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
+ RepeatedPtrField&& other) noexcept {
+ // We don't just call Swap(&other) here because it would perform 3 copies if
+ // the two fields are on different arenas.
+ if (this != &other) {
+ if (this->GetArenaNoVirtual() != other.GetArenaNoVirtual()) {
+ CopyFrom(other);
+ } else {
+ InternalSwap(&other);
+ }
+ }
+ return *this;
+}
+
+template <typename Element>
inline bool RepeatedPtrField<Element>::empty() const {
return RepeatedPtrFieldBase::empty();
}
@@ -1887,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() {
@@ -1922,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());
@@ -1955,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
@@ -2036,7 +2124,6 @@ inline void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
template <typename Element>
inline void RepeatedPtrField<Element>::UnsafeArenaSwap(
RepeatedPtrField* other) {
- GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
if (this == other)
return;
RepeatedPtrFieldBase::InternalSwap(other);
@@ -2053,8 +2140,8 @@ inline Arena* RepeatedPtrField<Element>::GetArenaNoVirtual() const {
}
template <typename Element>
-inline int RepeatedPtrField<Element>::SpaceUsedExcludingSelf() const {
- return RepeatedPtrFieldBase::SpaceUsedExcludingSelf<TypeHandler>();
+inline size_t RepeatedPtrField<Element>::SpaceUsedExcludingSelfLong() const {
+ return RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong<TypeHandler>();
}
template <typename Element>
@@ -2128,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.
@@ -2146,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*, OtherElement*>(0);
+ implicit_cast<Element*>(static_cast<OtherElement*>(nullptr));
}
}
@@ -2212,18 +2299,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<typename Element, typename VoidPtr>
+// iterator, or "const void* const" for a constant iterator.
+template <typename Element, typename VoidPtr>
class RepeatedPtrOverPtrsIterator
- : public std::iterator<std::random_access_iterator_tag, Element*> {
+ : public std::iterator<std::random_access_iterator_tag, Element> {
public:
typedef RepeatedPtrOverPtrsIterator<Element, VoidPtr> iterator;
- typedef std::iterator<
- std::random_access_iterator_tag, Element*> superclass;
+ typedef std::iterator<std::random_access_iterator_tag, Element> superclass;
// 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.
@@ -2235,7 +2321,7 @@ class RepeatedPtrOverPtrsIterator
explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {}
// dereferenceable
- reference operator*() const { return *reinterpret_cast<Element**>(it_); }
+ reference operator*() const { return *reinterpret_cast<Element*>(it_); }
pointer operator->() const { return &(operator*()); }
// {inc,dec}rementable
@@ -2291,6 +2377,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 +2426,7 @@ RepeatedPtrField<Element>::pointer_begin() {
template <typename Element>
inline typename RepeatedPtrField<Element>::const_pointer_iterator
RepeatedPtrField<Element>::pointer_begin() const {
- return const_pointer_iterator(const_cast<const void**>(raw_mutable_data()));
+ return const_pointer_iterator(const_cast<const void* const*>(raw_data()));
}
template <typename Element>
inline typename RepeatedPtrField<Element>::pointer_iterator
@@ -2348,7 +2437,7 @@ template <typename Element>
inline typename RepeatedPtrField<Element>::const_pointer_iterator
RepeatedPtrField<Element>::pointer_end() const {
return const_pointer_iterator(
- const_cast<const void**>(raw_mutable_data() + size()));
+ const_cast<const void* const*>(raw_data() + size()));
}
@@ -2405,6 +2494,10 @@ template<typename T> class RepeatedPtrFieldBackInsertIterator
*field_->Add() = *ptr_to_value;
return *this;
}
+ RepeatedPtrFieldBackInsertIterator<T>& operator=(T&& value) {
+ *field_->Add() = std::move(value);
+ return *this;
+ }
RepeatedPtrFieldBackInsertIterator<T>& operator*() {
return *this;
}
@@ -2519,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.