aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/repeated_field.h
diff options
context:
space:
mode:
authorGravatar jieluo@google.com <jieluo@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2014-07-18 00:47:59 +0000
committerGravatar jieluo@google.com <jieluo@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2014-07-18 00:47:59 +0000
commit4de8f55113007fdc8e34107950e605fc0209d465 (patch)
tree92b7da8757a7740d9e1f2d3ead233542947d8c8c /src/google/protobuf/repeated_field.h
parentc5553a3d18f80132b9079c5504bc0aa1f7f950a0 (diff)
down integrate to svn
Diffstat (limited to 'src/google/protobuf/repeated_field.h')
-rw-r--r--src/google/protobuf/repeated_field.h95
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;