diff options
author | jieluo@google.com <jieluo@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2014-07-18 00:47:59 +0000 |
---|---|---|
committer | jieluo@google.com <jieluo@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2014-07-18 00:47:59 +0000 |
commit | 4de8f55113007fdc8e34107950e605fc0209d465 (patch) | |
tree | 92b7da8757a7740d9e1f2d3ead233542947d8c8c /src/google/protobuf/repeated_field.h | |
parent | c5553a3d18f80132b9079c5504bc0aa1f7f950a0 (diff) |
down integrate to svn
Diffstat (limited to 'src/google/protobuf/repeated_field.h')
-rw-r--r-- | src/google/protobuf/repeated_field.h | 95 |
1 files changed, 87 insertions, 8 deletions
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index ff5d1f4b..1e9728ac 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -46,7 +46,6 @@ #ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__ #define GOOGLE_PROTOBUF_REPEATED_FIELD_H__ -#include <algorithm> #include <string> #include <iterator> #include <google/protobuf/stubs/common.h> @@ -72,6 +71,22 @@ static const int kMinRepeatedFieldAllocationSize = 4; // A utility function for logging that doesn't need any template types. 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); +} + +template <typename Iter> +inline int CalculateReserve(Iter begin, Iter end, std::input_iterator_tag) { + return -1; +} + +template <typename Iter> +inline int CalculateReserve(Iter begin, Iter end) { + typedef typename std::iterator_traits<Iter>::iterator_category Category; + return CalculateReserve(begin, end, Category()); +} } // namespace internal @@ -90,6 +105,7 @@ class RepeatedField { RepeatedField& operator=(const RepeatedField& other); + bool empty() const; int size() const; const Element& Get(int index) const; @@ -121,6 +137,11 @@ class RepeatedField { Element* AddAlreadyReserved(); int Capacity() const; + // Like STL resize. Uses value to fill appended elements. + // Like Truncate() if new_size <= size(), otherwise this is + // O(new_size - size()). + void Resize(int new_size, const Element& value); + // Gets the underlying array. This pointer is possibly invalidated by // any add or remove operation. Element* mutable_data(); @@ -245,6 +266,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { template <typename TypeHandler> void Destroy(); + bool empty() const; int size() const; template <typename TypeHandler> @@ -309,8 +331,6 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { typename TypeHandler::Type* ReleaseCleared(); private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); - static const int kInitialSize = 0; void** elements_; @@ -326,6 +346,8 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { static inline const typename TypeHandler::Type* cast(const void* element) { return reinterpret_cast<const typename TypeHandler::Type*>(element); } + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); }; template <typename GenericType> @@ -410,6 +432,7 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase { RepeatedPtrField& operator=(const RepeatedPtrField& other); + bool empty() const; int size() const; const Element& Get(int index) const; @@ -568,8 +591,16 @@ inline RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end) : elements_(NULL), current_size_(0), total_size_(kInitialSize) { - for (; begin != end; ++begin) { - Add(*begin); + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + Reserve(reserve); + for (; begin != end; ++begin) { + AddAlreadyReserved(*begin); + } + } else { + for (; begin != end; ++begin) { + Add(*begin); + } } } @@ -587,6 +618,11 @@ RepeatedField<Element>::operator=(const RepeatedField& other) { } template <typename Element> +inline bool RepeatedField<Element>::empty() const { + return current_size_ == 0; +} + +template <typename Element> inline int RepeatedField<Element>::size() const { return current_size_; } @@ -608,20 +644,33 @@ inline Element* RepeatedField<Element>::AddAlreadyReserved() { return &elements_[current_size_++]; } +template<typename Element> +inline void RepeatedField<Element>::Resize(int new_size, const Element& value) { + GOOGLE_DCHECK_GE(new_size, 0); + if (new_size > size()) { + Reserve(new_size); + std::fill(&elements_[current_size_], &elements_[new_size], value); + } + current_size_ = new_size; +} + template <typename Element> inline const Element& RepeatedField<Element>::Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return elements_[index]; } template <typename Element> inline Element* RepeatedField<Element>::Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return elements_ + index; } template <typename Element> inline void RepeatedField<Element>::Set(int index, const Element& value) { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); elements_[index] = value; } @@ -672,6 +721,7 @@ inline void RepeatedField<Element>::Clear() { template <typename Element> inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) { + GOOGLE_CHECK_NE(&other, this); if (other.current_size_ != 0) { Reserve(current_size_ + other.current_size_); CopyArray(elements_ + current_size_, other.elements_, other.current_size_); @@ -681,6 +731,7 @@ inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) { template <typename Element> inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) { + if (&other == this) return; Clear(); MergeFrom(other); } @@ -714,7 +765,8 @@ void RepeatedField<Element>::Swap(RepeatedField* other) { template <typename Element> void RepeatedField<Element>::SwapElements(int index1, int index2) { - std::swap(elements_[index1], elements_[index2]); + using std::swap; // enable ADL with fallback + swap(elements_[index1], elements_[index2]); } template <typename Element> @@ -814,6 +866,10 @@ void RepeatedPtrFieldBase::Destroy() { delete [] elements_; } +inline bool RepeatedPtrFieldBase::empty() const { + return current_size_ == 0; +} + inline int RepeatedPtrFieldBase::size() const { return current_size_; } @@ -821,6 +877,7 @@ inline int RepeatedPtrFieldBase::size() const { template <typename TypeHandler> inline const typename TypeHandler::Type& RepeatedPtrFieldBase::Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return *cast<TypeHandler>(elements_[index]); } @@ -829,6 +886,7 @@ RepeatedPtrFieldBase::Get(int index) const { template <typename TypeHandler> inline typename TypeHandler::Type* RepeatedPtrFieldBase::Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return cast<TypeHandler>(elements_[index]); } @@ -861,6 +919,7 @@ void RepeatedPtrFieldBase::Clear() { template <typename TypeHandler> inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { + GOOGLE_CHECK_NE(&other, this); Reserve(current_size_ + other.current_size_); for (int i = 0; i < other.current_size_; i++) { TypeHandler::Merge(other.template Get<TypeHandler>(i), Add<TypeHandler>()); @@ -869,6 +928,7 @@ inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { template <typename TypeHandler> inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) { + if (&other == this) return; RepeatedPtrFieldBase::Clear<TypeHandler>(); RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other); } @@ -901,7 +961,8 @@ RepeatedPtrFieldBase::data() const { } inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) { - std::swap(elements_[index1], elements_[index2]); + using std::swap; // enable ADL with fallback + swap(elements_[index1], elements_[index2]); } template <typename TypeHandler> @@ -1001,7 +1062,8 @@ inline RepeatedPtrField<Element>::RepeatedPtrField() {} template <typename Element> inline RepeatedPtrField<Element>::RepeatedPtrField( - const RepeatedPtrField& other) { + const RepeatedPtrField& other) + : RepeatedPtrFieldBase() { CopyFrom(other); } @@ -1009,6 +1071,10 @@ template <typename Element> template <typename Iter> inline RepeatedPtrField<Element>::RepeatedPtrField( Iter begin, const Iter& end) { + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + Reserve(reserve); + } for (; begin != end; ++begin) { *Add() = *begin; } @@ -1028,6 +1094,11 @@ inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=( } template <typename Element> +inline bool RepeatedPtrField<Element>::empty() const { + return RepeatedPtrFieldBase::empty(); +} + +template <typename Element> inline int RepeatedPtrField<Element>::size() const { return RepeatedPtrFieldBase::size(); } @@ -1182,6 +1253,10 @@ class RepeatedPtrIterator 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; + // Let the compiler know that these are type names, so we don't have to // write "typename" in front of them everywhere. typedef typename superclass::reference reference; @@ -1273,6 +1348,10 @@ class RepeatedPtrOverPtrsIterator 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; + // Let the compiler know that these are type names, so we don't have to // write "typename" in front of them everywhere. typedef typename superclass::reference reference; |