aboutsummaryrefslogtreecommitdiffhomepage
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.h168
1 files changed, 106 insertions, 62 deletions
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 <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>
@@ -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<typename Element>
@@ -321,7 +335,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 =
+ has_trivial_copy<Element>::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<typename T>
-struct TypeImplementsMergeBehavior {
+template <typename T>
+struct TypeImplementsMergeBehaviorProbeForMergeFrom {
typedef char HasMerge;
typedef long HasNoMerge;
@@ -360,8 +375,13 @@ struct TypeImplementsMergeBehavior {
(sizeof(Check<T>(0)) == sizeof(HasMerge))> type;
};
-template<>
-struct TypeImplementsMergeBehavior< ::std::string > {
+template <typename T, typename = void>
+struct TypeImplementsMergeBehavior :
+ TypeImplementsMergeBehaviorProbeForMergeFrom<T> {};
+
+
+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<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.
+ // 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,
@@ -400,6 +420,10 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
// 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;
@@ -426,7 +450,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
#if LANG_CXX11
template <typename TypeHandler>
void Add(typename TypeHandler::Type&& value,
- std::enable_if<TypeHandler::Moveable>* dummy = NULL);
+ internal::enable_if<TypeHandler::Moveable>* dummy = NULL);
#endif
template <typename TypeHandler>
@@ -459,7 +483,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
void SwapElements(int index1, int index2);
template <typename TypeHandler>
- 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<Type>(
arena, static_cast<GenericType*>(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<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);
@@ -708,7 +728,7 @@ class StringTypeHandler {
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
@@ -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<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
@@ -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<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 +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;
@@ -1089,6 +1118,14 @@ inline Element* RepeatedField<Element>::AddAlreadyReserved() {
}
template<typename Element>
+inline Element* RepeatedField<Element>::AddNAlreadyReserved(int elements) {
+ GOOGLE_DCHECK_LE(current_size_ + elements, total_size_);
+ Element* ret = &rep_->elements[current_size_];
+ current_size_ += elements;
+ return ret;
+}
+
+template<typename Element>
inline void RepeatedField<Element>::Resize(int new_size, const Element& value) {
GOOGLE_DCHECK_GE(new_size, 0);
if (new_size > current_size_) {
@@ -1208,9 +1245,17 @@ inline const Element* RepeatedField<Element>::data() const {
return rep_ ? rep_->elements : NULL;
}
+template <typename Element>
+inline const Element* RepeatedField<Element>::unsafe_data() const {
+ GOOGLE_DCHECK(rep_);
+ return rep_->elements;
+}
template <typename Element>
inline void RepeatedField<Element>::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<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,7 +1277,6 @@ 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);
}
@@ -1274,9 +1318,8 @@ RepeatedField<Element>::cend() const {
}
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 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<Element>::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<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;
if (arena == NULL) {
@@ -1476,9 +1519,10 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add(
template <typename TypeHandler>
inline void RepeatedPtrFieldBase::Add(
typename TypeHandler::Type&& value,
- std::enable_if<TypeHandler::Moveable>*) {
+ internal::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);
@@ -1606,11 +1650,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 = 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;
@@ -1819,7 +1863,6 @@ class RepeatedPtrField<string>::TypeHandler
: public internal::StringTypeHandler {
};
-
template <typename Element>
inline RepeatedPtrField<Element>::RepeatedPtrField()
: RepeatedPtrFieldBase() {}
@@ -2036,7 +2079,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 +2095,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>
@@ -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<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 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 +2276,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 +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<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 +2392,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()));
}