~ubuntu-branches/debian/experimental/protobuf/experimental

« back to all changes in this revision

Viewing changes to src/google/protobuf/repeated_field.h

  • Committer: Package Import Robot
  • Author(s): Robert S. Edmonds, Micah Anderson, Colin Watson, Steve Langasek, Robert S. Edmonds
  • Date: 2013-10-12 18:32:37 UTC
  • mfrom: (1.3.1) (10.1.4 sid)
  • Revision ID: package-import@ubuntu.com-20131012183237-jz6tvmj9tn68atrf
Tags: 2.5.0-1
[ Micah Anderson ]
* New upstream version. (Closes: #704731.)
* Update debian/watch.
* Refresh patches.

[ Colin Watson ]
* Use the autotools-dev dh addon to update config.guess/config.sub for
  arm64. (Closes: #725976.)

[ Steve Langasek ]
* Don't recommend protobuf-compiler from the bindings, it's not used and
  this doesn't need to be pulled in at runtime. (Closes: #703628.)
* Mark protobuf-compiler Multi-Arch: foreign; the output of this command
  is architecture-independent source, we don't need the version of the
  compiler to match the target arch.
* Bump to debhelper compat 9, so that our libs get installed to the
  multiarch locations.
* Mark the library packages Multi-Arch: same.
* Fix debian/rules to support cross-building of the python bindings.
* Build-depend on libpython-dev, not python-dev, for cross-build
  compatibility.
* (Closes: #726083.)

[ Robert S. Edmonds ]
* Upload to experimental.
* Bump ABI version from 7 to 8.
* Bump Standards-Version to 3.9.4.
* Convert from python-support to dh-python.
* Drop support for python2.6.
* python-protobuf: switch back to the pure Python implementation, as
  upstream appears to no longer be maintaining the current C++ based Python
  binding. See the following upstream issues for details:
  - https://code.google.com/p/protobuf/issues/detail?id=434
  - https://code.google.com/p/protobuf/issues/detail?id=503

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__
47
47
#define GOOGLE_PROTOBUF_REPEATED_FIELD_H__
48
48
 
 
49
#include <algorithm>
49
50
#include <string>
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>
53
56
 
54
57
namespace google {
55
58
 
 
59
namespace upb {
 
60
namespace google_opensource {
 
61
class GMR_Handlers;
 
62
}  // namespace google_opensource
 
63
}  // namespace upb
 
64
 
56
65
namespace protobuf {
57
66
 
58
67
class Message;
59
68
 
60
69
namespace internal {
61
70
 
62
 
// We need this (from generated_message_reflection.cc).
63
 
LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
 
71
static const int kMinRepeatedFieldAllocationSize = 4;
64
72
 
 
73
// A utility function for logging that doesn't need any template types.
 
74
void LogIndexOutOfBounds(int index, int size);
65
75
}  // namespace internal
66
76
 
 
77
 
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,
73
84
 public:
74
85
  RepeatedField();
75
86
  RepeatedField(const RepeatedField& other);
 
87
  template <typename Iter>
 
88
  RepeatedField(Iter begin, const Iter& end);
76
89
  ~RepeatedField();
77
90
 
78
91
  RepeatedField& operator=(const RepeatedField& other);
85
98
  void Add(const Element& value);
86
99
  Element* Add();
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();
 
102
 
 
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);
 
108
 
94
109
  void Clear();
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;
124
145
 
125
146
  iterator begin();
126
147
  const_iterator begin() const;
127
148
  iterator end();
128
149
  const_iterator end() const;
129
150
 
 
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());
 
156
  }
 
157
  const_reverse_iterator rbegin() const {
 
158
    return const_reverse_iterator(end());
 
159
  }
 
160
  reverse_iterator rend() {
 
161
    return reverse_iterator(begin());
 
162
  }
 
163
  const_reverse_iterator rend() const {
 
164
    return const_reverse_iterator(begin());
 
165
  }
 
166
 
130
167
  // Returns the number of bytes used by the repeated field, excluding
131
168
  // sizeof(*this)
132
169
  int SpaceUsedExcludingSelf() const;
133
170
 
134
171
 private:
135
 
  static const int kInitialSize = 4;
 
172
  static const int kInitialSize = 0;
136
173
 
137
174
  Element* elements_;
138
175
  int      current_size_;
139
176
  int      total_size_;
140
177
 
141
 
  Element  initial_space_[kInitialSize];
142
 
 
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.
151
186
 
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
 
191
 
 
192
namespace internal {
 
193
 
 
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
 
197
// effectively.
 
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);
 
202
};
 
203
 
155
204
}  // namespace internal
156
205
 
157
206
namespace internal {
186
235
  // use of AddFromCleared(), which is not part of the public interface.
187
236
  friend class ExtensionSet;
188
237
 
 
238
  // To parse directly into a proto2 generated class, the upb class GMR_Handlers
 
239
  // needs to be able to modify a RepeatedPtrFieldBase directly.
 
240
  friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;
 
241
 
189
242
  RepeatedPtrFieldBase();
190
243
 
191
244
  // Must be called from destructor.
209
262
  template <typename TypeHandler>
210
263
  void CopyFrom(const RepeatedPtrFieldBase& other);
211
264
 
 
265
  void CloseGap(int start, int num) {
 
266
    // Close up a gap of "num" elements starting at offset "start".
 
267
    for (int i = start + num; i < allocated_size_; ++i)
 
268
      elements_[i - num] = elements_[i];
 
269
    current_size_ -= num;
 
270
    allocated_size_ -= num;
 
271
  }
 
272
 
212
273
  void Reserve(int new_size);
213
274
 
214
275
  int Capacity() const;
250
311
 private:
251
312
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
252
313
 
253
 
  static const int kInitialSize = 4;
 
314
  static const int kInitialSize = 0;
254
315
 
255
316
  void** elements_;
256
317
  int    current_size_;
257
318
  int    allocated_size_;
258
319
  int    total_size_;
259
320
 
260
 
  void*  initial_space_[kInitialSize];
261
 
 
262
321
  template <typename TypeHandler>
263
322
  static inline typename TypeHandler::Type* cast(void* element) {
264
323
    return reinterpret_cast<typename TypeHandler::Type*>(element);
280
339
    to->MergeFrom(from);
281
340
  }
282
341
  static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); }
 
342
  static const Type& default_instance() { return Type::default_instance(); }
283
343
};
284
344
 
285
345
template <>
288
348
  to->CheckTypeAndMergeFrom(from);
289
349
}
290
350
 
 
351
template <>
 
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;
 
357
  return *null;
 
358
}
 
359
 
 
360
template <>
 
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;
 
366
  return *null;
 
367
}
 
368
 
 
369
 
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
303
382
  static void Delete(string* value);
304
383
  static void Clear(string* value) { value->clear(); }
305
384
  static void Merge(const string& from, string* to) { *to = from; }
 
385
  static const Type& default_instance() {
 
386
    return ::google::protobuf::internal::kEmptyString;
 
387
  }
306
388
};
307
389
 
308
 
class LIBPROTOBUF_EXPORT StringTypeHandler : public StringTypeHandlerBase {
 
390
class StringTypeHandler : public StringTypeHandlerBase {
309
391
 public:
310
392
  static int SpaceUsed(const string& value)  {
311
393
    return sizeof(value) + StringSpaceUsedExcludingSelf(value);
322
404
 public:
323
405
  RepeatedPtrField();
324
406
  RepeatedPtrField(const RepeatedPtrField& other);
 
407
  template <typename Iter>
 
408
  RepeatedPtrField(Iter begin, const Iter& end);
325
409
  ~RepeatedPtrField();
326
410
 
327
411
  RepeatedPtrField& operator=(const RepeatedPtrField& other);
331
415
  const Element& Get(int index) const;
332
416
  Element* Mutable(int index);
333
417
  Element* Add();
334
 
  void RemoveLast();  // Remove the last element in the array.
 
418
 
 
419
  // Remove the last element in the array.
 
420
  // Ownership of the element is retained by the array.
 
421
  void RemoveLast();
 
422
 
 
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);
 
427
 
335
428
  void Clear();
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;
361
460
 
362
461
  iterator begin();
363
462
  const_iterator begin() const;
364
463
  iterator end();
365
464
  const_iterator end() const;
366
465
 
 
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());
 
471
  }
 
472
  const_reverse_iterator rbegin() const {
 
473
    return const_reverse_iterator(end());
 
474
  }
 
475
  reverse_iterator rend() {
 
476
    return reverse_iterator(begin());
 
477
  }
 
478
  const_reverse_iterator rend() const {
 
479
    return const_reverse_iterator(begin());
 
480
  }
 
481
 
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*>
 
485
  pointer_iterator;
 
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;
372
492
 
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;
376
496
 
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.
380
500
 
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
385
 
  // caller.
 
504
  // Remove the last element and return it, passing ownership to the caller.
386
505
  // Requires:  size() > 0
387
506
  Element* ReleaseLast();
388
507
 
 
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);
 
518
 
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.
393
523
  //
394
 
  // Really, extremely hardcore programs may actually want to manipulate
395
 
  // these objects to better-optimize memory management.  These methods
396
 
  // allow that.
 
524
  // Hardcore programs may choose to manipulate these cleared objects
 
525
  // to better optimize memory management using the following routines.
397
526
 
398
527
  // Get the number of cleared objects that are currently being kept
399
528
  // around for reuse.
420
549
 
421
550
template <typename Element>
422
551
inline RepeatedField<Element>::RepeatedField()
423
 
  : elements_(initial_space_),
 
552
  : elements_(NULL),
424
553
    current_size_(0),
425
554
    total_size_(kInitialSize) {
426
555
}
427
556
 
428
557
template <typename Element>
429
558
inline RepeatedField<Element>::RepeatedField(const RepeatedField& other)
430
 
  : elements_(initial_space_),
 
559
  : elements_(NULL),
431
560
    current_size_(0),
432
561
    total_size_(kInitialSize) {
433
562
  CopyFrom(other);
434
563
}
435
564
 
436
565
template <typename Element>
 
566
template <typename Iter>
 
567
inline RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
 
568
  : elements_(NULL),
 
569
    current_size_(0),
 
570
    total_size_(kInitialSize) {
 
571
  for (; begin != end; ++begin) {
 
572
    Add(*begin);
 
573
  }
 
574
}
 
575
 
 
576
template <typename Element>
437
577
RepeatedField<Element>::~RepeatedField() {
438
 
  if (elements_ != initial_space_) {
439
 
    delete [] elements_;
440
 
  }
 
578
  delete [] elements_;
441
579
}
442
580
 
443
581
template <typename Element>
444
582
inline RepeatedField<Element>&
445
583
RepeatedField<Element>::operator=(const RepeatedField& other) {
446
 
  CopyFrom(other);
 
584
  if (this != &other)
 
585
    CopyFrom(other);
447
586
  return *this;
448
587
}
449
588
 
506
645
}
507
646
 
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());
 
653
 
 
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);
 
658
  }
 
659
 
 
660
  // Slide remaining elements down to fill the gap.
 
661
  if (num > 0) {
 
662
    for (int i = start + num; i < this->size(); ++i)
 
663
      this->Set(i - num, this->Get(i));
 
664
    this->Truncate(this->size() - num);
 
665
  }
 
666
}
 
667
 
 
668
template <typename Element>
509
669
inline void RepeatedField<Element>::Clear() {
510
670
  current_size_ = 0;
511
671
}
512
672
 
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_;
 
679
  }
518
680
}
519
681
 
520
682
template <typename Element>
536
698
 
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
543
 
  // copy it anyway.
544
 
  Element swap_initial_space[kInitialSize];
545
 
  MoveArray(swap_initial_space, initial_space_, kInitialSize);
546
705
 
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);
551
709
 
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);
556
 
 
557
 
  if (elements_ == other->initial_space_) {
558
 
    elements_ = initial_space_;
559
 
  }
560
 
  if (other->elements_ == initial_space_) {
561
 
    other->elements_ = other->initial_space_;
562
 
  }
563
713
}
564
714
 
565
715
template <typename Element>
590
740
 
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;
594
744
}
595
745
 
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;
601
751
 
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;
608
759
  }
609
760
}
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);
621
772
}
622
773
 
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));
627
 
}
 
777
  internal::ElementCopier<Element>()(to, from, array_size);
 
778
}
 
779
 
 
780
namespace internal {
 
781
 
 
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);
 
786
}
 
787
 
 
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));
 
792
  }
 
793
};
 
794
 
 
795
}  // namespace internal
628
796
 
629
797
 
630
798
// -------------------------------------------------------------------
632
800
namespace internal {
633
801
 
634
802
inline RepeatedPtrFieldBase::RepeatedPtrFieldBase()
635
 
  : elements_(initial_space_),
 
803
  : elements_(NULL),
636
804
    current_size_(0),
637
805
    allocated_size_(0),
638
806
    total_size_(kInitialSize) {
643
811
  for (int i = 0; i < allocated_size_; i++) {
644
812
    TypeHandler::Delete(cast<TypeHandler>(elements_[i]));
645
813
  }
646
 
  if (elements_ != initial_space_) {
647
 
    delete [] elements_;
648
 
  }
 
814
  delete [] elements_;
649
815
}
650
816
 
651
817
inline int RepeatedPtrFieldBase::size() const {
652
818
  return current_size_;
653
819
}
654
820
 
655
 
 
656
821
template <typename TypeHandler>
657
822
inline const typename TypeHandler::Type&
658
823
RepeatedPtrFieldBase::Get(int index) const {
660
825
  return *cast<TypeHandler>(elements_[index]);
661
826
}
662
827
 
 
828
 
663
829
template <typename TypeHandler>
664
830
inline typename TypeHandler::Type*
665
831
RepeatedPtrFieldBase::Mutable(int index) {
741
907
template <typename TypeHandler>
742
908
inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const {
743
909
  int allocated_bytes =
744
 
      (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
 
910
      (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0;
745
911
  for (int i = 0; i < allocated_size_; ++i) {
746
912
    allocated_bytes += TypeHandler::SpaceUsed(*cast<TypeHandler>(elements_[i]));
747
913
  }
798
964
  return result;
799
965
}
800
966
 
801
 
 
802
967
inline int RepeatedPtrFieldBase::ClearedCount() const {
803
968
  return allocated_size_ - current_size_;
804
969
}
822
987
 
823
988
template <typename Element>
824
989
class RepeatedPtrField<Element>::TypeHandler
825
 
    : public internal::GenericTypeHandler<Element> {};
 
990
    : public internal::GenericTypeHandler<Element> {
 
991
};
826
992
 
827
993
template <>
828
994
class RepeatedPtrField<string>::TypeHandler
829
 
    : public internal::StringTypeHandler {};
 
995
    : public internal::StringTypeHandler {
 
996
};
830
997
 
831
998
 
832
999
template <typename Element>
839
1006
}
840
1007
 
841
1008
template <typename Element>
 
1009
template <typename Iter>
 
1010
inline RepeatedPtrField<Element>::RepeatedPtrField(
 
1011
    Iter begin, const Iter& end) {
 
1012
  for (; begin != end; ++begin) {
 
1013
    *Add() = *begin;
 
1014
  }
 
1015
}
 
1016
 
 
1017
template <typename Element>
842
1018
RepeatedPtrField<Element>::~RepeatedPtrField() {
843
1019
  Destroy<TypeHandler>();
844
1020
}
846
1022
template <typename Element>
847
1023
inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
848
1024
    const RepeatedPtrField& other) {
849
 
  CopyFrom(other);
 
1025
  if (this != &other)
 
1026
    CopyFrom(other);
850
1027
  return *this;
851
1028
}
852
1029
 
860
1037
  return RepeatedPtrFieldBase::Get<TypeHandler>(index);
861
1038
}
862
1039
 
 
1040
 
863
1041
template <typename Element>
864
1042
inline Element* RepeatedPtrField<Element>::Mutable(int index) {
865
1043
  return RepeatedPtrFieldBase::Mutable<TypeHandler>(index);
876
1054
}
877
1055
 
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);
 
1064
}
 
1065
 
 
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());
 
1072
 
 
1073
  if (num > 0) {
 
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);
 
1078
    }
 
1079
    CloseGap(start, num);
 
1080
  }
 
1081
}
 
1082
 
 
1083
template <typename Element>
879
1084
inline void RepeatedPtrField<Element>::Clear() {
880
1085
  RepeatedPtrFieldBase::Clear<TypeHandler>();
881
1086
}
961
1166
// refer to this class directly; use RepeatedPtrField<T>::iterator instead.
962
1167
//
963
1168
// The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is
964
 
// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors-inl.h,
 
1169
// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors.h,
965
1170
// but adds random-access operators and is modified to wrap a void** base
966
1171
// iterator (since RepeatedPtrField stores its array as a void* array and
967
1172
// casting void** to T** would violate C++ aliasing rules).
1057
1262
// rather than the objects themselves as RepeatedPtrIterator does.
1058
1263
// Consider using this when working with stl algorithms that change
1059
1264
// the array.
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*> {
1063
1271
 public:
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;
1067
1275
 
1072
1280
  typedef typename superclass::difference_type difference_type;
1073
1281
 
1074
1282
  RepeatedPtrOverPtrsIterator() : it_(NULL) {}
1075
 
  explicit RepeatedPtrOverPtrsIterator(void** it) : it_(it) {}
 
1283
  explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {}
1076
1284
 
1077
1285
  // dereferenceable
1078
1286
  reference operator*() const { return *reinterpret_cast<Element**>(it_); }
1127
1335
  friend class RepeatedPtrIterator;
1128
1336
 
1129
1337
  // The internal iterator.
1130
 
  void** it_;
 
1338
  VoidPtr* it_;
1131
1339
};
1132
1340
 
1133
 
 
1134
1341
}  // namespace internal
1135
1342
 
1136
1343
template <typename Element>
1160
1367
  return pointer_iterator(raw_mutable_data());
1161
1368
}
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()));
 
1373
}
 
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());
1166
1378
}
 
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()));
 
1384
}
1167
1385
 
1168
1386
 
1169
1387
// Iterators and helper functions that follow the spirit of the STL
1173
1391
//   std::copy(some_sequence.begin(), some_sequence.end(),
1174
1392
//             google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
1175
1393
//
1176
 
// Ported by johannes from util/gtl/proto-array-iterators-inl.h
 
1394
// Ported by johannes from util/gtl/proto-array-iterators.h
1177
1395
 
1178
1396
namespace internal {
1179
1397
// A back inserter for RepeatedField objects.
1194
1412
  RepeatedFieldBackInsertIterator<T>& operator++() {
1195
1413
    return *this;
1196
1414
  }
1197
 
  RepeatedFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
 
1415
  RepeatedFieldBackInsertIterator<T>& operator++(int /* unused */) {
1198
1416
    return *this;
1199
1417
  }
1200
1418
 
1225
1443
  RepeatedPtrFieldBackInsertIterator<T>& operator++() {
1226
1444
    return *this;
1227
1445
  }
1228
 
  RepeatedPtrFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
 
1446
  RepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) {
1229
1447
    return *this;
1230
1448
  }
1231
1449
 
1254
1472
    return *this;
1255
1473
  }
1256
1474
  AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
1257
 
      int ignores_parameter) {
 
1475
      int /* unused */) {
1258
1476
    return *this;
1259
1477
  }
1260
1478
 
1264
1482
}  // namespace internal
1265
1483
 
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);
1272
1489
}
1273
1490
 
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);
 
1496
}
 
1497
 
 
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);