46
46
#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__
47
47
#define GOOGLE_PROTOBUF_REPEATED_FIELD_H__
50
51
#include <iterator>
51
52
#include <google/protobuf/stubs/common.h>
53
#include <google/protobuf/stubs/type_traits.h>
54
#include <google/protobuf/generated_message_util.h>
52
55
#include <google/protobuf/message_lite.h>
60
namespace google_opensource {
62
} // namespace google_opensource
56
65
namespace protobuf {
60
69
namespace internal {
62
// We need this (from generated_message_reflection.cc).
63
LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
71
static const int kMinRepeatedFieldAllocationSize = 4;
73
// A utility function for logging that doesn't need any template types.
74
void LogIndexOutOfBounds(int index, int size);
65
75
} // namespace internal
67
78
// RepeatedField is used to represent repeated fields of a primitive type (in
68
79
// other words, everything except strings and nested Messages). Most users will
69
80
// not ever use a RepeatedField directly; they will use the get-by-index,
85
98
void Add(const Element& value);
87
100
// Remove the last element in the array.
88
// We don't provide a way to remove any element other than the last
89
// because it invites inefficient use, such as O(n^2) filtering loops
90
// that should have been O(n). If you want to remove an element other
91
// than the last, the best way to do it is to re-arrange the elements
92
// so that the one you want removed is at the end, then call RemoveLast().
93
101
void RemoveLast();
103
// Extract elements with indices in "[start .. start+num-1]".
104
// Copy them into "elements[0 .. num-1]" if "elements" is not NULL.
105
// Caution: implementation also moves elements with indices [start+num ..].
106
// Calling this routine inside a loop can cause quadratic behavior.
107
void ExtractSubrange(int start, int num, Element* elements);
95
110
void MergeFrom(const RepeatedField& other);
96
111
void CopyFrom(const RepeatedField& other);
121
136
typedef Element* iterator;
122
137
typedef const Element* const_iterator;
123
138
typedef Element value_type;
139
typedef value_type& reference;
140
typedef const value_type& const_reference;
141
typedef value_type* pointer;
142
typedef const value_type* const_pointer;
143
typedef int size_type;
144
typedef ptrdiff_t difference_type;
125
146
iterator begin();
126
147
const_iterator begin() const;
128
149
const_iterator end() const;
151
// Reverse iterator support
152
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
153
typedef std::reverse_iterator<iterator> reverse_iterator;
154
reverse_iterator rbegin() {
155
return reverse_iterator(end());
157
const_reverse_iterator rbegin() const {
158
return const_reverse_iterator(end());
160
reverse_iterator rend() {
161
return reverse_iterator(begin());
163
const_reverse_iterator rend() const {
164
return const_reverse_iterator(begin());
130
167
// Returns the number of bytes used by the repeated field, excluding
132
169
int SpaceUsedExcludingSelf() const;
135
static const int kInitialSize = 4;
172
static const int kInitialSize = 0;
137
174
Element* elements_;
138
175
int current_size_;
141
Element initial_space_[kInitialSize];
143
178
// Move the contents of |from| into |to|, possibly clobbering |from| in the
144
179
// process. For primitive types this is just a memcpy(), but it could be
145
180
// specialized for non-primitive types to, say, swap each element instead.
152
187
namespace internal {
153
188
template <typename It> class RepeatedPtrIterator;
154
template <typename It> class RepeatedPtrOverPtrsIterator;
189
template <typename It, typename VoidPtr> class RepeatedPtrOverPtrsIterator;
190
} // namespace internal
194
// This is a helper template to copy an array of elements effeciently when they
195
// have a trivial copy constructor, and correctly otherwise. This really
196
// shouldn't be necessary, but our compiler doesn't optimize std::copy very
198
template <typename Element,
199
bool HasTrivialCopy = has_trivial_copy<Element>::value>
200
struct ElementCopier {
201
void operator()(Element to[], const Element from[], int array_size);
155
204
} // namespace internal
157
206
namespace internal {
288
348
to->CheckTypeAndMergeFrom(from);
352
inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
353
// Yes, the behavior of the code is undefined, but this function is only
354
// called when we're already deep into the world of undefined, because the
355
// caller called Get(index) out of bounds.
356
MessageLite* null = NULL;
361
inline const Message& GenericTypeHandler<Message>::default_instance() {
362
// Yes, the behavior of the code is undefined, but this function is only
363
// called when we're already deep into the world of undefined, because the
364
// caller called Get(index) out of bounds.
365
Message* null = NULL;
291
370
// HACK: If a class is declared as DLL-exported in MSVC, it insists on
292
371
// generating copies of all its methods -- even inline ones -- to include
293
372
// in the DLL. But SpaceUsed() calls StringSpaceUsedExcludingSelf() which
331
415
const Element& Get(int index) const;
332
416
Element* Mutable(int index);
334
void RemoveLast(); // Remove the last element in the array.
419
// Remove the last element in the array.
420
// Ownership of the element is retained by the array.
423
// Delete elements with indices in the range [start .. start+num-1].
424
// Caution: implementation moves all elements with indices [start+num .. ].
425
// Calling this routine inside a loop can cause quadratic behavior.
426
void DeleteSubrange(int start, int num);
336
429
void MergeFrom(const RepeatedPtrField& other);
337
430
void CopyFrom(const RepeatedPtrField& other);
358
451
typedef internal::RepeatedPtrIterator<Element> iterator;
359
452
typedef internal::RepeatedPtrIterator<const Element> const_iterator;
360
453
typedef Element value_type;
454
typedef value_type& reference;
455
typedef const value_type& const_reference;
456
typedef value_type* pointer;
457
typedef const value_type* const_pointer;
458
typedef int size_type;
459
typedef ptrdiff_t difference_type;
362
461
iterator begin();
363
462
const_iterator begin() const;
365
464
const_iterator end() const;
466
// Reverse iterator support
467
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
468
typedef std::reverse_iterator<iterator> reverse_iterator;
469
reverse_iterator rbegin() {
470
return reverse_iterator(end());
472
const_reverse_iterator rbegin() const {
473
return const_reverse_iterator(end());
475
reverse_iterator rend() {
476
return reverse_iterator(begin());
478
const_reverse_iterator rend() const {
479
return const_reverse_iterator(begin());
367
482
// Custom STL-like iterator that iterates over and returns the underlying
368
483
// pointers to Element rather than Element itself.
369
typedef internal::RepeatedPtrOverPtrsIterator<Element> pointer_iterator;
484
typedef internal::RepeatedPtrOverPtrsIterator<Element, void*>
486
typedef internal::RepeatedPtrOverPtrsIterator<const Element, const void*>
487
const_pointer_iterator;
370
488
pointer_iterator pointer_begin();
489
const_pointer_iterator pointer_begin() const;
371
490
pointer_iterator pointer_end();
491
const_pointer_iterator pointer_end() const;
373
493
// Returns (an estimate of) the number of bytes used by the repeated field,
374
494
// excluding sizeof(*this).
375
495
int SpaceUsedExcludingSelf() const;
377
497
// Advanced memory management --------------------------------------
378
// When hardcore memory management becomes necessary -- as it often
498
// When hardcore memory management becomes necessary -- as it sometimes
379
499
// does here at Google -- the following methods may be useful.
381
501
// Add an already-allocated object, passing ownership to the
382
502
// RepeatedPtrField.
383
503
void AddAllocated(Element* value);
384
// Remove the last element and return it, passing ownership to the
504
// Remove the last element and return it, passing ownership to the caller.
386
505
// Requires: size() > 0
387
506
Element* ReleaseLast();
508
// Extract elements with indices in the range "[start .. start+num-1]".
509
// The caller assumes ownership of the extracted elements and is responsible
510
// for deleting them when they are no longer needed.
511
// If "elements" is non-NULL, then pointers to the extracted elements
512
// are stored in "elements[0 .. num-1]" for the convenience of the caller.
513
// If "elements" is NULL, then the caller must use some other mechanism
514
// to perform any further operations (like deletion) on these elements.
515
// Caution: implementation also moves elements with indices [start+num ..].
516
// Calling this routine inside a loop can cause quadratic behavior.
517
void ExtractSubrange(int start, int num, Element** elements);
389
519
// When elements are removed by calls to RemoveLast() or Clear(), they
390
520
// are not actually freed. Instead, they are cleared and kept so that
391
521
// they can be reused later. This can save lots of CPU time when
392
522
// repeatedly reusing a protocol message for similar purposes.
394
// Really, extremely hardcore programs may actually want to manipulate
395
// these objects to better-optimize memory management. These methods
524
// Hardcore programs may choose to manipulate these cleared objects
525
// to better optimize memory management using the following routines.
398
527
// Get the number of cleared objects that are currently being kept
399
528
// around for reuse.
421
550
template <typename Element>
422
551
inline RepeatedField<Element>::RepeatedField()
423
: elements_(initial_space_),
424
553
current_size_(0),
425
554
total_size_(kInitialSize) {
428
557
template <typename Element>
429
558
inline RepeatedField<Element>::RepeatedField(const RepeatedField& other)
430
: elements_(initial_space_),
431
560
current_size_(0),
432
561
total_size_(kInitialSize) {
436
565
template <typename Element>
566
template <typename Iter>
567
inline RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
570
total_size_(kInitialSize) {
571
for (; begin != end; ++begin) {
576
template <typename Element>
437
577
RepeatedField<Element>::~RepeatedField() {
438
if (elements_ != initial_space_) {
443
581
template <typename Element>
444
582
inline RepeatedField<Element>&
445
583
RepeatedField<Element>::operator=(const RepeatedField& other) {
508
647
template <typename Element>
648
void RepeatedField<Element>::ExtractSubrange(
649
int start, int num, Element* elements) {
650
GOOGLE_DCHECK_GE(start, 0);
651
GOOGLE_DCHECK_GE(num, 0);
652
GOOGLE_DCHECK_LE(start + num, this->size());
654
// Save the values of the removed elements if requested.
655
if (elements != NULL) {
656
for (int i = 0; i < num; ++i)
657
elements[i] = this->Get(i + start);
660
// Slide remaining elements down to fill the gap.
662
for (int i = start + num; i < this->size(); ++i)
663
this->Set(i - num, this->Get(i));
664
this->Truncate(this->size() - num);
668
template <typename Element>
509
669
inline void RepeatedField<Element>::Clear() {
510
670
current_size_ = 0;
513
673
template <typename Element>
514
674
inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
515
Reserve(current_size_ + other.current_size_);
516
CopyArray(elements_ + current_size_, other.elements_, other.current_size_);
517
current_size_ += other.current_size_;
675
if (other.current_size_ != 0) {
676
Reserve(current_size_ + other.current_size_);
677
CopyArray(elements_ + current_size_, other.elements_, other.current_size_);
678
current_size_ += other.current_size_;
520
682
template <typename Element>
537
699
template <typename Element>
538
700
void RepeatedField<Element>::Swap(RepeatedField* other) {
701
if (this == other) return;
539
702
Element* swap_elements = elements_;
540
703
int swap_current_size = current_size_;
541
704
int swap_total_size = total_size_;
542
// We may not be using initial_space_ but it's not worth checking. Just
544
Element swap_initial_space[kInitialSize];
545
MoveArray(swap_initial_space, initial_space_, kInitialSize);
547
706
elements_ = other->elements_;
548
707
current_size_ = other->current_size_;
549
708
total_size_ = other->total_size_;
550
MoveArray(initial_space_, other->initial_space_, kInitialSize);
552
710
other->elements_ = swap_elements;
553
711
other->current_size_ = swap_current_size;
554
712
other->total_size_ = swap_total_size;
555
MoveArray(other->initial_space_, swap_initial_space, kInitialSize);
557
if (elements_ == other->initial_space_) {
558
elements_ = initial_space_;
560
if (other->elements_ == initial_space_) {
561
other->elements_ = other->initial_space_;
565
715
template <typename Element>
591
741
template <typename Element>
592
742
inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
593
return (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
743
return (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0;
596
// Avoid inlining of Reserve(): new, memcpy, and delete[] lead to a significant
746
// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant
597
747
// amount of code bloat.
598
748
template <typename Element>
599
749
void RepeatedField<Element>::Reserve(int new_size) {
600
750
if (total_size_ >= new_size) return;
602
752
Element* old_elements = elements_;
603
total_size_ = max(total_size_ * 2, new_size);
753
total_size_ = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
754
max(total_size_ * 2, new_size));
604
755
elements_ = new Element[total_size_];
605
MoveArray(elements_, old_elements, current_size_);
606
if (old_elements != initial_space_) {
756
if (old_elements != NULL) {
757
MoveArray(elements_, old_elements, current_size_);
607
758
delete [] old_elements;
617
768
template <typename Element>
618
769
inline void RepeatedField<Element>::MoveArray(
619
770
Element to[], Element from[], int array_size) {
620
memcpy(to, from, array_size * sizeof(Element));
771
CopyArray(to, from, array_size);
623
774
template <typename Element>
624
775
inline void RepeatedField<Element>::CopyArray(
625
776
Element to[], const Element from[], int array_size) {
626
memcpy(to, from, array_size * sizeof(Element));
777
internal::ElementCopier<Element>()(to, from, array_size);
782
template <typename Element, bool HasTrivialCopy>
783
void ElementCopier<Element, HasTrivialCopy>::operator()(
784
Element to[], const Element from[], int array_size) {
785
std::copy(from, from + array_size, to);
788
template <typename Element>
789
struct ElementCopier<Element, true> {
790
void operator()(Element to[], const Element from[], int array_size) {
791
memcpy(to, from, array_size * sizeof(Element));
795
} // namespace internal
630
798
// -------------------------------------------------------------------
878
1056
template <typename Element>
1057
inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) {
1058
GOOGLE_DCHECK_GE(start, 0);
1059
GOOGLE_DCHECK_GE(num, 0);
1060
GOOGLE_DCHECK_LE(start + num, size());
1061
for (int i = 0; i < num; ++i)
1062
delete RepeatedPtrFieldBase::Mutable<TypeHandler>(start + i);
1063
ExtractSubrange(start, num, NULL);
1066
template <typename Element>
1067
inline void RepeatedPtrField<Element>::ExtractSubrange(
1068
int start, int num, Element** elements) {
1069
GOOGLE_DCHECK_GE(start, 0);
1070
GOOGLE_DCHECK_GE(num, 0);
1071
GOOGLE_DCHECK_LE(start + num, size());
1074
// Save the values of the removed elements if requested.
1075
if (elements != NULL) {
1076
for (int i = 0; i < num; ++i)
1077
elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
1079
CloseGap(start, num);
1083
template <typename Element>
879
1084
inline void RepeatedPtrField<Element>::Clear() {
880
1085
RepeatedPtrFieldBase::Clear<TypeHandler>();
1057
1262
// rather than the objects themselves as RepeatedPtrIterator does.
1058
1263
// Consider using this when working with stl algorithms that change
1060
template<typename Element>
1265
// The VoidPtr template parameter holds the type-agnostic pointer value
1266
// referenced by the iterator. It should either be "void *" for a mutable
1267
// iterator, or "const void *" for a constant iterator.
1268
template<typename Element, typename VoidPtr>
1061
1269
class RepeatedPtrOverPtrsIterator
1062
1270
: public std::iterator<std::random_access_iterator_tag, Element*> {
1064
typedef RepeatedPtrOverPtrsIterator<Element> iterator;
1272
typedef RepeatedPtrOverPtrsIterator<Element, VoidPtr> iterator;
1065
1273
typedef std::iterator<
1066
1274
std::random_access_iterator_tag, Element*> superclass;
1160
1367
return pointer_iterator(raw_mutable_data());
1162
1369
template <typename Element>
1370
inline typename RepeatedPtrField<Element>::const_pointer_iterator
1371
RepeatedPtrField<Element>::pointer_begin() const {
1372
return const_pointer_iterator(const_cast<const void**>(raw_mutable_data()));
1374
template <typename Element>
1163
1375
inline typename RepeatedPtrField<Element>::pointer_iterator
1164
1376
RepeatedPtrField<Element>::pointer_end() {
1165
1377
return pointer_iterator(raw_mutable_data() + size());
1379
template <typename Element>
1380
inline typename RepeatedPtrField<Element>::const_pointer_iterator
1381
RepeatedPtrField<Element>::pointer_end() const {
1382
return const_pointer_iterator(
1383
const_cast<const void**>(raw_mutable_data() + size()));
1169
1387
// Iterators and helper functions that follow the spirit of the STL
1264
1482
} // namespace internal
1266
1484
// Provides a back insert iterator for RepeatedField instances,
1267
// similar to std::back_inserter(). Note the identically named
1268
// function for RepeatedPtrField instances.
1485
// similar to std::back_inserter().
1269
1486
template<typename T> internal::RepeatedFieldBackInsertIterator<T>
1270
1487
RepeatedFieldBackInserter(RepeatedField<T>* const mutable_field) {
1271
1488
return internal::RepeatedFieldBackInsertIterator<T>(mutable_field);
1274
1491
// Provides a back insert iterator for RepeatedPtrField instances,
1275
// similar to std::back_inserter(). Note the identically named
1276
// function for RepeatedField instances.
1492
// similar to std::back_inserter().
1493
template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
1494
RepeatedPtrFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
1495
return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
1498
// Special back insert iterator for RepeatedPtrField instances, just in
1499
// case someone wants to write generic template code that can access both
1500
// RepeatedFields and RepeatedPtrFields using a common name.
1277
1501
template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
1278
1502
RepeatedFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
1279
1503
return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);