1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34 //
35 // RepeatedField and RepeatedPtrField are used by generated protocol message
36 // classes to manipulate repeated fields. These classes are very similar to
37 // STL's vector, but include a number of optimizations found to be useful
38 // specifically in the case of Protocol Buffers. RepeatedPtrField is
39 // particularly different from STL vector as it manages ownership of the
40 // pointers that it contains.
41 //
42 // Typically, clients should not need to access RepeatedField objects directly,
43 // but should instead use the accessor functions generated automatically by the
44 // protocol compiler.
45
46 #ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__
47 #define GOOGLE_PROTOBUF_REPEATED_FIELD_H__
48
49 #include <string>
50 #include <iterator>
51 #include <google/protobuf/stubs/common.h>
52 #include <google/protobuf/message_lite.h>
53
54 namespace google {
55
56 namespace protobuf {
57
58 class Message;
59
60 namespace internal {
61
62 // We need this (from generated_message_reflection.cc).
63 LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
64
65 } // namespace internal
66
67 // RepeatedField is used to represent repeated fields of a primitive type (in
68 // other words, everything except strings and nested Messages). Most users will
69 // not ever use a RepeatedField directly; they will use the get-by-index,
70 // set-by-index, and add accessors that are generated for all repeated fields.
71 template <typename Element>
72 class RepeatedField {
73 public:
74 RepeatedField();
75 ~RepeatedField();
76
77 int size() const;
78
79 const Element& Get(int index) const;
80 Element* Mutable(int index);
81 void Set(int index, const Element& value);
82 void Add(const Element& value);
83 Element* Add();
84 // Remove the last element in the array.
85 // We don't provide a way to remove any element other than the last
86 // because it invites inefficient use, such as O(n^2) filtering loops
87 // that should have been O(n). If you want to remove an element other
88 // than the last, the best way to do it is to re-arrange the elements
89 // so that the one you want removed is at the end, then call RemoveLast().
90 void RemoveLast();
91 void Clear();
92 void MergeFrom(const RepeatedField& other);
93
94 // Reserve space to expand the field to at least the given size. If the
95 // array is grown, it will always be at least doubled in size.
96 void Reserve(int new_size);
97
98 // Resize the RepeatedField to a new, smaller size. This is O(1).
99 void Truncate(int new_size);
100
101 void AddAlreadyReserved(const Element& value);
102 Element* AddAlreadyReserved();
103 int Capacity() const;
104
105 // Gets the underlying array. This pointer is possibly invalidated by
106 // any add or remove operation.
107 Element* mutable_data();
108 const Element* data() const;
109
110 // Swap entire contents with "other".
111 void Swap(RepeatedField* other);
112
113 // Swap two elements.
114 void SwapElements(int index1, int index2);
115
116 // STL-like iterator support
117 typedef Element* iterator;
118 typedef const Element* const_iterator;
119
120 iterator begin();
121 const_iterator begin() const;
122 iterator end();
123 const_iterator end() const;
124
125 // Returns the number of bytes used by the repeated field, excluding
126 // sizeof(*this)
127 int SpaceUsedExcludingSelf() const;
128
129 private:
130 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedField);
131
132 static const int kInitialSize = 4;
133
134 Element* elements_;
135 int current_size_;
136 int total_size_;
137
138 Element initial_space_[kInitialSize];
139
140 // Move the contents of |from| into |to|, possibly clobbering |from| in the
141 // process. For primitive types this is just a memcpy(), but it could be
142 // specialized for non-primitive types to, say, swap each element instead.
143 void MoveArray(Element to[], Element from[], int size);
144
145 // Copy the elements of |from| into |to|.
146 void CopyArray(Element to[], const Element from[], int size);
147 };
148
149 namespace internal {
150 template <typename It> class RepeatedPtrIterator;
151 template <typename It> class RepeatedPtrOverPtrsIterator;
152 } // namespace internal
153
154 namespace internal {
155
156 // This is the common base class for RepeatedPtrFields. It deals only in void*
157 // pointers. Users should not use this interface directly.
158 //
159 // The methods of this interface correspond to the methods of RepeatedPtrField,
160 // but may have a template argument called TypeHandler. Its signature is:
161 // class TypeHandler {
162 // public:
163 // typedef MyType Type;
164 // static Type* New();
165 // static void Delete(Type*);
166 // static void Clear(Type*);
167 // static void Merge(const Type& from, Type* to);
168 //
169 // // Only needs to be implemented if SpaceUsedExcludingSelf() is called.
170 // static int SpaceUsed(const Type&);
171 // };
172 class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
173 protected:
174 // The reflection implementation needs to call protected methods directly,
175 // reinterpreting pointers as being to Message instead of a specific Message
176 // subclass.
177 friend class GeneratedMessageReflection;
178
179 // ExtensionSet stores repeated message extensions as
180 // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to
181 // implement SpaceUsed(), and thus need to call SpaceUsedExcludingSelf()
182 // reinterpreting MessageLite as Message. ExtensionSet also needs to make
183 // use of AddFromCleared(), which is not part of the public interface.
184 friend class ExtensionSet;
185
186 RepeatedPtrFieldBase();
187
188 // Must be called from destructor.
189 template <typename TypeHandler>
190 void Destroy();
191
192 int size() const;
193
194 template <typename TypeHandler>
195 const typename TypeHandler::Type& Get(int index) const;
196 template <typename TypeHandler>
197 typename TypeHandler::Type* Mutable(int index);
198 template <typename TypeHandler>
199 typename TypeHandler::Type* Add();
200 template <typename TypeHandler>
201 void RemoveLast();
202 template <typename TypeHandler>
203 void Clear();
204 template <typename TypeHandler>
205 void MergeFrom(const RepeatedPtrFieldBase& other);
206
207 void Reserve(int new_size);
208
209 int Capacity() const;
210
211 // Used for constructing iterators.
212 void* const* raw_data() const;
213 void** raw_mutable_data() const;
214
215 template <typename TypeHandler>
216 typename TypeHandler::Type** mutable_data();
217 template <typename TypeHandler>
218 const typename TypeHandler::Type* const* data() const;
219
220 void Swap(RepeatedPtrFieldBase* other);
221
222 void SwapElements(int index1, int index2);
223
224 template <typename TypeHandler>
225 int SpaceUsedExcludingSelf() const;
226
227
228 // Advanced memory management --------------------------------------
229
230 // Like Add(), but if there are no cleared objects to use, returns NULL.
231 template <typename TypeHandler>
232 typename TypeHandler::Type* AddFromCleared();
233
234 template <typename TypeHandler>
235 void AddAllocated(typename TypeHandler::Type* value);
236 template <typename TypeHandler>
237 typename TypeHandler::Type* ReleaseLast();
238
239 int ClearedCount() const;
240 template <typename TypeHandler>
241 void AddCleared(typename TypeHandler::Type* value);
242 template <typename TypeHandler>
243 typename TypeHandler::Type* ReleaseCleared();
244
245 private:
246 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
247
248 static const int kInitialSize = 4;
249
250 void** elements_;
251 int current_size_;
252 int allocated_size_;
253 int total_size_;
254
255 void* initial_space_[kInitialSize];
256
257 template <typename TypeHandler>
cast(void * element)258 static inline typename TypeHandler::Type* cast(void* element) {
259 return reinterpret_cast<typename TypeHandler::Type*>(element);
260 }
261 template <typename TypeHandler>
cast(const void * element)262 static inline const typename TypeHandler::Type* cast(const void* element) {
263 return reinterpret_cast<const typename TypeHandler::Type*>(element);
264 }
265 };
266
267 template <typename GenericType>
268 class GenericTypeHandler {
269 public:
270 typedef GenericType Type;
New()271 static GenericType* New() { return new GenericType; }
Delete(GenericType * value)272 static void Delete(GenericType* value) { delete value; }
Clear(GenericType * value)273 static void Clear(GenericType* value) { value->Clear(); }
Merge(const GenericType & from,GenericType * to)274 static void Merge(const GenericType& from, GenericType* to) {
275 to->MergeFrom(from);
276 }
SpaceUsed(const GenericType & value)277 static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); }
278 };
279
280 template <>
Merge(const MessageLite & from,MessageLite * to)281 inline void GenericTypeHandler<MessageLite>::Merge(
282 const MessageLite& from, MessageLite* to) {
283 to->CheckTypeAndMergeFrom(from);
284 }
285
286 // HACK: If a class is declared as DLL-exported in MSVC, it insists on
287 // generating copies of all its methods -- even inline ones -- to include
288 // in the DLL. But SpaceUsed() calls StringSpaceUsedExcludingSelf() which
289 // isn't in the lite library, therefore the lite library cannot link if
290 // StringTypeHandler is exported. So, we factor out StringTypeHandlerBase,
291 // export that, then make StringTypeHandler be a subclass which is NOT
292 // exported.
293 // TODO(kenton): There has to be a better way.
294 class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
295 public:
296 typedef string Type;
297 static string* New();
298 static void Delete(string* value);
Clear(string * value)299 static void Clear(string* value) { value->clear(); }
Merge(const string & from,string * to)300 static void Merge(const string& from, string* to) { *to = from; }
301 };
302
303 class StringTypeHandler : public StringTypeHandlerBase {
304 public:
SpaceUsed(const string & value)305 static int SpaceUsed(const string& value) {
306 return sizeof(value) + StringSpaceUsedExcludingSelf(value);
307 }
308 };
309
310
311 } // namespace internal
312
313 // RepeatedPtrField is like RepeatedField, but used for repeated strings or
314 // Messages.
315 template <typename Element>
316 class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
317 public:
318 RepeatedPtrField();
319
320 ~RepeatedPtrField();
321
322 int size() const;
323
324 const Element& Get(int index) const;
325 Element* Mutable(int index);
326 Element* Add();
327 void RemoveLast(); // Remove the last element in the array.
328 void Clear();
329 void MergeFrom(const RepeatedPtrField& other);
330
331 // Reserve space to expand the field to at least the given size. This only
332 // resizes the pointer array; it doesn't allocate any objects. If the
333 // array is grown, it will always be at least doubled in size.
334 void Reserve(int new_size);
335
336 int Capacity() const;
337
338 // Gets the underlying array. This pointer is possibly invalidated by
339 // any add or remove operation.
340 Element** mutable_data();
341 const Element* const* data() const;
342
343 // Swap entire contents with "other".
344 void Swap(RepeatedPtrField* other);
345
346 // Swap two elements.
347 void SwapElements(int index1, int index2);
348
349 // STL-like iterator support
350 typedef internal::RepeatedPtrIterator<Element> iterator;
351 typedef internal::RepeatedPtrIterator<const Element> const_iterator;
352
353 iterator begin();
354 const_iterator begin() const;
355 iterator end();
356 const_iterator end() const;
357
358 // Custom STL-like iterator that iterates over and returns the underlying
359 // pointers to Element rather than Element itself.
360 typedef internal::RepeatedPtrOverPtrsIterator<Element> pointer_iterator;
361 pointer_iterator pointer_begin();
362 pointer_iterator pointer_end();
363
364 // Returns (an estimate of) the number of bytes used by the repeated field,
365 // excluding sizeof(*this).
366 int SpaceUsedExcludingSelf() const;
367
368 // The spaced used just by the pointer array, not counting the objects pointed
369 // at. Returns zero if the array is inlined (i.e. initial_space_ is being
370 // used).
371 int SpaceUsedByArray() const;
372
373 // Advanced memory management --------------------------------------
374 // When hardcore memory management becomes necessary -- as it often
375 // does here at Google -- the following methods may be useful.
376
377 // Add an already-allocated object, passing ownership to the
378 // RepeatedPtrField.
379 void AddAllocated(Element* value);
380 // Remove the last element and return it, passing ownership to the
381 // caller.
382 // Requires: size() > 0
383 Element* ReleaseLast();
384
385 // When elements are removed by calls to RemoveLast() or Clear(), they
386 // are not actually freed. Instead, they are cleared and kept so that
387 // they can be reused later. This can save lots of CPU time when
388 // repeatedly reusing a protocol message for similar purposes.
389 //
390 // Really, extremely hardcore programs may actually want to manipulate
391 // these objects to better-optimize memory management. These methods
392 // allow that.
393
394 // Get the number of cleared objects that are currently being kept
395 // around for reuse.
396 int ClearedCount() const;
397 // Add an element to the pool of cleared objects, passing ownership to
398 // the RepeatedPtrField. The element must be cleared prior to calling
399 // this method.
400 void AddCleared(Element* value);
401 // Remove a single element from the cleared pool and return it, passing
402 // ownership to the caller. The element is guaranteed to be cleared.
403 // Requires: ClearedCount() > 0
404 Element* ReleaseCleared();
405
406 protected:
407 // Note: RepeatedPtrField SHOULD NOT be subclassed by users. We only
408 // subclass it in one place as a hack for compatibility with proto1. The
409 // subclass needs to know about TypeHandler in order to call protected
410 // methods on RepeatedPtrFieldBase.
411 class TypeHandler;
412
413
414 private:
415 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField);
416 };
417
418 // implementation ====================================================
419
420 template <typename Element>
RepeatedField()421 inline RepeatedField<Element>::RepeatedField()
422 : elements_(initial_space_),
423 current_size_(0),
424 total_size_(kInitialSize) {
425 }
426
427 template <typename Element>
~RepeatedField()428 RepeatedField<Element>::~RepeatedField() {
429 if (elements_ != initial_space_) {
430 delete [] elements_;
431 }
432 }
433
434 template <typename Element>
size()435 inline int RepeatedField<Element>::size() const {
436 return current_size_;
437 }
438
439 template <typename Element>
Capacity()440 inline int RepeatedField<Element>::Capacity() const {
441 return total_size_;
442 }
443
444 template<typename Element>
AddAlreadyReserved(const Element & value)445 inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) {
446 GOOGLE_DCHECK_LT(size(), Capacity());
447 elements_[current_size_++] = value;
448 }
449
450 template<typename Element>
AddAlreadyReserved()451 inline Element* RepeatedField<Element>::AddAlreadyReserved() {
452 GOOGLE_DCHECK_LT(size(), Capacity());
453 return &elements_[current_size_++];
454 }
455
456 template <typename Element>
Get(int index)457 inline const Element& RepeatedField<Element>::Get(int index) const {
458 GOOGLE_DCHECK_LT(index, size());
459 return elements_[index];
460 }
461
462 template <typename Element>
Mutable(int index)463 inline Element* RepeatedField<Element>::Mutable(int index) {
464 GOOGLE_DCHECK_LT(index, size());
465 return elements_ + index;
466 }
467
468 template <typename Element>
Set(int index,const Element & value)469 inline void RepeatedField<Element>::Set(int index, const Element& value) {
470 GOOGLE_DCHECK_LT(index, size());
471 elements_[index] = value;
472 }
473
474 template <typename Element>
Add(const Element & value)475 inline void RepeatedField<Element>::Add(const Element& value) {
476 if (current_size_ == total_size_) Reserve(total_size_ + 1);
477 elements_[current_size_++] = value;
478 }
479
480 template <typename Element>
Add()481 inline Element* RepeatedField<Element>::Add() {
482 if (current_size_ == total_size_) Reserve(total_size_ + 1);
483 return &elements_[current_size_++];
484 }
485
486 template <typename Element>
RemoveLast()487 inline void RepeatedField<Element>::RemoveLast() {
488 GOOGLE_DCHECK_GT(current_size_, 0);
489 --current_size_;
490 }
491
492 template <typename Element>
Clear()493 inline void RepeatedField<Element>::Clear() {
494 current_size_ = 0;
495 }
496
497 template <typename Element>
MergeFrom(const RepeatedField & other)498 inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
499 Reserve(current_size_ + other.current_size_);
500 CopyArray(elements_ + current_size_, other.elements_, other.current_size_);
501 current_size_ += other.current_size_;
502 }
503
504 template <typename Element>
mutable_data()505 inline Element* RepeatedField<Element>::mutable_data() {
506 return elements_;
507 }
508
509 template <typename Element>
data()510 inline const Element* RepeatedField<Element>::data() const {
511 return elements_;
512 }
513
514
515 template <typename Element>
Swap(RepeatedField * other)516 void RepeatedField<Element>::Swap(RepeatedField* other) {
517 Element* swap_elements = elements_;
518 int swap_current_size = current_size_;
519 int swap_total_size = total_size_;
520 // We may not be using initial_space_ but it's not worth checking. Just
521 // copy it anyway.
522 Element swap_initial_space[kInitialSize];
523 MoveArray(swap_initial_space, initial_space_, kInitialSize);
524
525 elements_ = other->elements_;
526 current_size_ = other->current_size_;
527 total_size_ = other->total_size_;
528 MoveArray(initial_space_, other->initial_space_, kInitialSize);
529
530 other->elements_ = swap_elements;
531 other->current_size_ = swap_current_size;
532 other->total_size_ = swap_total_size;
533 MoveArray(other->initial_space_, swap_initial_space, kInitialSize);
534
535 if (elements_ == other->initial_space_) {
536 elements_ = initial_space_;
537 }
538 if (other->elements_ == initial_space_) {
539 other->elements_ = other->initial_space_;
540 }
541 }
542
543 template <typename Element>
SwapElements(int index1,int index2)544 void RepeatedField<Element>::SwapElements(int index1, int index2) {
545 std::swap(elements_[index1], elements_[index2]);
546 }
547
548 template <typename Element>
549 inline typename RepeatedField<Element>::iterator
begin()550 RepeatedField<Element>::begin() {
551 return elements_;
552 }
553 template <typename Element>
554 inline typename RepeatedField<Element>::const_iterator
begin()555 RepeatedField<Element>::begin() const {
556 return elements_;
557 }
558 template <typename Element>
559 inline typename RepeatedField<Element>::iterator
end()560 RepeatedField<Element>::end() {
561 return elements_ + current_size_;
562 }
563 template <typename Element>
564 inline typename RepeatedField<Element>::const_iterator
end()565 RepeatedField<Element>::end() const {
566 return elements_ + current_size_;
567 }
568
569 template <typename Element>
SpaceUsedExcludingSelf()570 inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
571 return (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
572 }
573
574 // Avoid inlining of Reserve(): new, memcpy, and delete[] lead to a significant
575 // amount of code bloat.
576 template <typename Element>
Reserve(int new_size)577 void RepeatedField<Element>::Reserve(int new_size) {
578 if (total_size_ >= new_size) return;
579
580 Element* old_elements = elements_;
581 total_size_ = max(total_size_ * 2, new_size);
582 elements_ = new Element[total_size_];
583 MoveArray(elements_, old_elements, current_size_);
584 if (old_elements != initial_space_) {
585 delete [] old_elements;
586 }
587 }
588
589 template <typename Element>
Truncate(int new_size)590 inline void RepeatedField<Element>::Truncate(int new_size) {
591 GOOGLE_DCHECK_LE(new_size, current_size_);
592 current_size_ = new_size;
593 }
594
595 template <typename Element>
MoveArray(Element to[],Element from[],int size)596 inline void RepeatedField<Element>::MoveArray(
597 Element to[], Element from[], int size) {
598 memcpy(to, from, size * sizeof(Element));
599 }
600
601 template <typename Element>
CopyArray(Element to[],const Element from[],int size)602 inline void RepeatedField<Element>::CopyArray(
603 Element to[], const Element from[], int size) {
604 memcpy(to, from, size * sizeof(Element));
605 }
606
607
608 // -------------------------------------------------------------------
609
610 namespace internal {
611
RepeatedPtrFieldBase()612 inline RepeatedPtrFieldBase::RepeatedPtrFieldBase()
613 : elements_(initial_space_),
614 current_size_(0),
615 allocated_size_(0),
616 total_size_(kInitialSize) {
617 }
618
619 template <typename TypeHandler>
Destroy()620 void RepeatedPtrFieldBase::Destroy() {
621 for (int i = 0; i < allocated_size_; i++) {
622 TypeHandler::Delete(cast<TypeHandler>(elements_[i]));
623 }
624 if (elements_ != initial_space_) {
625 delete [] elements_;
626 }
627 }
628
size()629 inline int RepeatedPtrFieldBase::size() const {
630 return current_size_;
631 }
632
633
634 template <typename TypeHandler>
635 inline const typename TypeHandler::Type&
Get(int index)636 RepeatedPtrFieldBase::Get(int index) const {
637 GOOGLE_DCHECK_LT(index, size());
638 return *cast<TypeHandler>(elements_[index]);
639 }
640
641 template <typename TypeHandler>
642 inline typename TypeHandler::Type*
Mutable(int index)643 RepeatedPtrFieldBase::Mutable(int index) {
644 GOOGLE_DCHECK_LT(index, size());
645 return cast<TypeHandler>(elements_[index]);
646 }
647
648 template <typename TypeHandler>
Add()649 inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add() {
650 if (current_size_ < allocated_size_) {
651 return cast<TypeHandler>(elements_[current_size_++]);
652 }
653 if (allocated_size_ == total_size_) Reserve(total_size_ + 1);
654 ++allocated_size_;
655 typename TypeHandler::Type* result = TypeHandler::New();
656 elements_[current_size_++] = result;
657 return result;
658 }
659
660 template <typename TypeHandler>
RemoveLast()661 inline void RepeatedPtrFieldBase::RemoveLast() {
662 GOOGLE_DCHECK_GT(current_size_, 0);
663 TypeHandler::Clear(cast<TypeHandler>(elements_[--current_size_]));
664 }
665
666 template <typename TypeHandler>
Clear()667 void RepeatedPtrFieldBase::Clear() {
668 for (int i = 0; i < current_size_; i++) {
669 TypeHandler::Clear(cast<TypeHandler>(elements_[i]));
670 }
671 current_size_ = 0;
672 }
673
674 template <typename TypeHandler>
MergeFrom(const RepeatedPtrFieldBase & other)675 inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) {
676 Reserve(current_size_ + other.current_size_);
677 for (int i = 0; i < other.current_size_; i++) {
678 TypeHandler::Merge(other.Get<TypeHandler>(i), Add<TypeHandler>());
679 }
680 }
681
Capacity()682 inline int RepeatedPtrFieldBase::Capacity() const {
683 return total_size_;
684 }
685
raw_data()686 inline void* const* RepeatedPtrFieldBase::raw_data() const {
687 return elements_;
688 }
689
raw_mutable_data()690 inline void** RepeatedPtrFieldBase::raw_mutable_data() const {
691 return elements_;
692 }
693
694 template <typename TypeHandler>
mutable_data()695 inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() {
696 // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
697 // method entirely.
698 return reinterpret_cast<typename TypeHandler::Type**>(elements_);
699 }
700
701 template <typename TypeHandler>
702 inline const typename TypeHandler::Type* const*
data()703 RepeatedPtrFieldBase::data() const {
704 // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
705 // method entirely.
706 return reinterpret_cast<const typename TypeHandler::Type* const*>(elements_);
707 }
708
SwapElements(int index1,int index2)709 inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) {
710 std::swap(elements_[index1], elements_[index2]);
711 }
712
713 template <typename TypeHandler>
SpaceUsedExcludingSelf()714 inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const {
715 int allocated_bytes =
716 (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
717 for (int i = 0; i < allocated_size_; ++i) {
718 allocated_bytes += TypeHandler::SpaceUsed(*cast<TypeHandler>(elements_[i]));
719 }
720 return allocated_bytes;
721 }
722
723 template <typename TypeHandler>
AddFromCleared()724 inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() {
725 if (current_size_ < allocated_size_) {
726 return cast<TypeHandler>(elements_[current_size_++]);
727 } else {
728 return NULL;
729 }
730 }
731
732 template <typename TypeHandler>
AddAllocated(typename TypeHandler::Type * value)733 void RepeatedPtrFieldBase::AddAllocated(
734 typename TypeHandler::Type* value) {
735 // Make room for the new pointer.
736 if (current_size_ == total_size_) {
737 // The array is completely full with no cleared objects, so grow it.
738 Reserve(total_size_ + 1);
739 ++allocated_size_;
740 } else if (allocated_size_ == total_size_) {
741 // There is no more space in the pointer array because it contains some
742 // cleared objects awaiting reuse. We don't want to grow the array in this
743 // case because otherwise a loop calling AddAllocated() followed by Clear()
744 // would leak memory.
745 TypeHandler::Delete(cast<TypeHandler>(elements_[current_size_]));
746 } else if (current_size_ < allocated_size_) {
747 // We have some cleared objects. We don't care about their order, so we
748 // can just move the first one to the end to make space.
749 elements_[allocated_size_] = elements_[current_size_];
750 ++allocated_size_;
751 } else {
752 // There are no cleared objects.
753 ++allocated_size_;
754 }
755
756 elements_[current_size_++] = value;
757 }
758
759 template <typename TypeHandler>
ReleaseLast()760 inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLast() {
761 GOOGLE_DCHECK_GT(current_size_, 0);
762 typename TypeHandler::Type* result =
763 cast<TypeHandler>(elements_[--current_size_]);
764 --allocated_size_;
765 if (current_size_ < allocated_size_) {
766 // There are cleared elements on the end; replace the removed element
767 // with the last allocated element.
768 elements_[current_size_] = elements_[allocated_size_];
769 }
770 return result;
771 }
772
773
ClearedCount()774 inline int RepeatedPtrFieldBase::ClearedCount() const {
775 return allocated_size_ - current_size_;
776 }
777
778 template <typename TypeHandler>
AddCleared(typename TypeHandler::Type * value)779 inline void RepeatedPtrFieldBase::AddCleared(
780 typename TypeHandler::Type* value) {
781 if (allocated_size_ == total_size_) Reserve(total_size_ + 1);
782 elements_[allocated_size_++] = value;
783 }
784
785 template <typename TypeHandler>
ReleaseCleared()786 inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() {
787 GOOGLE_DCHECK_GT(allocated_size_, current_size_);
788 return cast<TypeHandler>(elements_[--allocated_size_]);
789 }
790
791 } // namespace internal
792
793 // -------------------------------------------------------------------
794
795 template <typename Element>
796 class RepeatedPtrField<Element>::TypeHandler
797 : public internal::GenericTypeHandler<Element> {};
798
799 template <>
800 class RepeatedPtrField<string>::TypeHandler
801 : public internal::StringTypeHandler {};
802
803
804 template <typename Element>
RepeatedPtrField()805 inline RepeatedPtrField<Element>::RepeatedPtrField() {}
806
807 template <typename Element>
~RepeatedPtrField()808 RepeatedPtrField<Element>::~RepeatedPtrField() {
809 Destroy<TypeHandler>();
810 }
811
812 template <typename Element>
size()813 inline int RepeatedPtrField<Element>::size() const {
814 return RepeatedPtrFieldBase::size();
815 }
816
817 template <typename Element>
Get(int index)818 inline const Element& RepeatedPtrField<Element>::Get(int index) const {
819 return RepeatedPtrFieldBase::Get<TypeHandler>(index);
820 }
821
822 template <typename Element>
Mutable(int index)823 inline Element* RepeatedPtrField<Element>::Mutable(int index) {
824 return RepeatedPtrFieldBase::Mutable<TypeHandler>(index);
825 }
826
827 template <typename Element>
Add()828 inline Element* RepeatedPtrField<Element>::Add() {
829 return RepeatedPtrFieldBase::Add<TypeHandler>();
830 }
831
832 template <typename Element>
RemoveLast()833 inline void RepeatedPtrField<Element>::RemoveLast() {
834 RepeatedPtrFieldBase::RemoveLast<TypeHandler>();
835 }
836
837 template <typename Element>
Clear()838 inline void RepeatedPtrField<Element>::Clear() {
839 RepeatedPtrFieldBase::Clear<TypeHandler>();
840 }
841
842 template <typename Element>
MergeFrom(const RepeatedPtrField & other)843 inline void RepeatedPtrField<Element>::MergeFrom(
844 const RepeatedPtrField& other) {
845 RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
846 }
847
848 template <typename Element>
mutable_data()849 inline Element** RepeatedPtrField<Element>::mutable_data() {
850 return RepeatedPtrFieldBase::mutable_data<TypeHandler>();
851 }
852
853 template <typename Element>
data()854 inline const Element* const* RepeatedPtrField<Element>::data() const {
855 return RepeatedPtrFieldBase::data<TypeHandler>();
856 }
857
858 template <typename Element>
Swap(RepeatedPtrField * other)859 void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
860 RepeatedPtrFieldBase::Swap(other);
861 }
862
863 template <typename Element>
SwapElements(int index1,int index2)864 void RepeatedPtrField<Element>::SwapElements(int index1, int index2) {
865 RepeatedPtrFieldBase::SwapElements(index1, index2);
866 }
867
868 template <typename Element>
SpaceUsedExcludingSelf()869 inline int RepeatedPtrField<Element>::SpaceUsedExcludingSelf() const {
870 return RepeatedPtrFieldBase::SpaceUsedExcludingSelf<TypeHandler>();
871 }
872
873 template <typename Element>
AddAllocated(Element * value)874 inline void RepeatedPtrField<Element>::AddAllocated(Element* value) {
875 RepeatedPtrFieldBase::AddAllocated<TypeHandler>(value);
876 }
877
878 template <typename Element>
ReleaseLast()879 inline Element* RepeatedPtrField<Element>::ReleaseLast() {
880 return RepeatedPtrFieldBase::ReleaseLast<TypeHandler>();
881 }
882
883
884 template <typename Element>
ClearedCount()885 inline int RepeatedPtrField<Element>::ClearedCount() const {
886 return RepeatedPtrFieldBase::ClearedCount();
887 }
888
889 template <typename Element>
AddCleared(Element * value)890 inline void RepeatedPtrField<Element>::AddCleared(Element* value) {
891 return RepeatedPtrFieldBase::AddCleared<TypeHandler>(value);
892 }
893
894 template <typename Element>
ReleaseCleared()895 inline Element* RepeatedPtrField<Element>::ReleaseCleared() {
896 return RepeatedPtrFieldBase::ReleaseCleared<TypeHandler>();
897 }
898
899 template <typename Element>
Reserve(int new_size)900 inline void RepeatedPtrField<Element>::Reserve(int new_size) {
901 return RepeatedPtrFieldBase::Reserve(new_size);
902 }
903
904 template <typename Element>
Capacity()905 inline int RepeatedPtrField<Element>::Capacity() const {
906 return RepeatedPtrFieldBase::Capacity();
907 }
908
909 // -------------------------------------------------------------------
910
911 namespace internal {
912
913 // STL-like iterator implementation for RepeatedPtrField. You should not
914 // refer to this class directly; use RepeatedPtrField<T>::iterator instead.
915 //
916 // The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is
917 // very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors-inl.h,
918 // but adds random-access operators and is modified to wrap a void** base
919 // iterator (since RepeatedPtrField stores its array as a void* array and
920 // casting void** to T** would violate C++ aliasing rules).
921 //
922 // This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin
923 // (jyasskin@google.com).
924 template<typename Element>
925 class RepeatedPtrIterator
926 : public std::iterator<
927 std::random_access_iterator_tag, Element> {
928 public:
929 typedef RepeatedPtrIterator<Element> iterator;
930 typedef std::iterator<
931 std::random_access_iterator_tag, Element> superclass;
932
933 // Let the compiler know that these are type names, so we don't have to
934 // write "typename" in front of them everywhere.
935 typedef typename superclass::reference reference;
936 typedef typename superclass::pointer pointer;
937 typedef typename superclass::difference_type difference_type;
938
RepeatedPtrIterator()939 RepeatedPtrIterator() : it_(NULL) {}
RepeatedPtrIterator(void * const * it)940 explicit RepeatedPtrIterator(void* const* it) : it_(it) {}
941
942 // Allow "upcasting" from RepeatedPtrIterator<T**> to
943 // RepeatedPtrIterator<const T*const*>.
944 template<typename OtherElement>
RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement> & other)945 RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement>& other)
946 : it_(other.it_) {
947 // Force a compiler error if the other type is not convertable to ours.
948 if (false) {
949 implicit_cast<Element*, OtherElement*>(0);
950 }
951 }
952
953 // dereferenceable
954 reference operator*() const { return *reinterpret_cast<Element*>(*it_); }
955 pointer operator->() const { return &(operator*()); }
956
957 // {inc,dec}rementable
958 iterator& operator++() { ++it_; return *this; }
959 iterator operator++(int) { return iterator(it_++); }
960 iterator& operator--() { --it_; return *this; }
961 iterator operator--(int) { return iterator(it_--); }
962
963 // equality_comparable
964 bool operator==(const iterator& x) const { return it_ == x.it_; }
965 bool operator!=(const iterator& x) const { return it_ != x.it_; }
966
967 // less_than_comparable
968 bool operator<(const iterator& x) const { return it_ < x.it_; }
969 bool operator<=(const iterator& x) const { return it_ <= x.it_; }
970 bool operator>(const iterator& x) const { return it_ > x.it_; }
971 bool operator>=(const iterator& x) const { return it_ >= x.it_; }
972
973 // addable, subtractable
974 iterator& operator+=(difference_type d) {
975 it_ += d;
976 return *this;
977 }
978 friend iterator operator+(iterator it, difference_type d) {
979 it += d;
980 return it;
981 }
982 friend iterator operator+(difference_type d, iterator it) {
983 it += d;
984 return it;
985 }
986 iterator& operator-=(difference_type d) {
987 it_ -= d;
988 return *this;
989 }
990 friend iterator operator-(iterator it, difference_type d) {
991 it -= d;
992 return it;
993 }
994
995 // indexable
996 reference operator[](difference_type d) const { return *(*this + d); }
997
998 // random access iterator
999 difference_type operator-(const iterator& x) const { return it_ - x.it_; }
1000
1001 private:
1002 template<typename OtherElement>
1003 friend class RepeatedPtrIterator;
1004
1005 // The internal iterator.
1006 void* const* it_;
1007 };
1008
1009 // Provide an iterator that operates on pointers to the underlying objects
1010 // rather than the objects themselves as RepeatedPtrIterator does.
1011 // Consider using this when working with stl algorithms that change
1012 // the array.
1013 template<typename Element>
1014 class RepeatedPtrOverPtrsIterator
1015 : public std::iterator<std::random_access_iterator_tag, Element*> {
1016 public:
1017 typedef RepeatedPtrOverPtrsIterator<Element> iterator;
1018 typedef std::iterator<
1019 std::random_access_iterator_tag, Element*> superclass;
1020
1021 // Let the compiler know that these are type names, so we don't have to
1022 // write "typename" in front of them everywhere.
1023 typedef typename superclass::reference reference;
1024 typedef typename superclass::pointer pointer;
1025 typedef typename superclass::difference_type difference_type;
1026
RepeatedPtrOverPtrsIterator()1027 RepeatedPtrOverPtrsIterator() : it_(NULL) {}
RepeatedPtrOverPtrsIterator(void ** it)1028 explicit RepeatedPtrOverPtrsIterator(void** it) : it_(it) {}
1029
1030 // dereferenceable
1031 reference operator*() const { return *reinterpret_cast<Element**>(it_); }
1032 pointer operator->() const { return &(operator*()); }
1033
1034 // {inc,dec}rementable
1035 iterator& operator++() { ++it_; return *this; }
1036 iterator operator++(int) { return iterator(it_++); }
1037 iterator& operator--() { --it_; return *this; }
1038 iterator operator--(int) { return iterator(it_--); }
1039
1040 // equality_comparable
1041 bool operator==(const iterator& x) const { return it_ == x.it_; }
1042 bool operator!=(const iterator& x) const { return it_ != x.it_; }
1043
1044 // less_than_comparable
1045 bool operator<(const iterator& x) const { return it_ < x.it_; }
1046 bool operator<=(const iterator& x) const { return it_ <= x.it_; }
1047 bool operator>(const iterator& x) const { return it_ > x.it_; }
1048 bool operator>=(const iterator& x) const { return it_ >= x.it_; }
1049
1050 // addable, subtractable
1051 iterator& operator+=(difference_type d) {
1052 it_ += d;
1053 return *this;
1054 }
1055 friend iterator operator+(iterator it, difference_type d) {
1056 it += d;
1057 return it;
1058 }
1059 friend iterator operator+(difference_type d, iterator it) {
1060 it += d;
1061 return it;
1062 }
1063 iterator& operator-=(difference_type d) {
1064 it_ -= d;
1065 return *this;
1066 }
1067 friend iterator operator-(iterator it, difference_type d) {
1068 it -= d;
1069 return it;
1070 }
1071
1072 // indexable
1073 reference operator[](difference_type d) const { return *(*this + d); }
1074
1075 // random access iterator
1076 difference_type operator-(const iterator& x) const { return it_ - x.it_; }
1077
1078 private:
1079 template<typename OtherElement>
1080 friend class RepeatedPtrIterator;
1081
1082 // The internal iterator.
1083 void** it_;
1084 };
1085
1086
1087 } // namespace internal
1088
1089 template <typename Element>
1090 inline typename RepeatedPtrField<Element>::iterator
begin()1091 RepeatedPtrField<Element>::begin() {
1092 return iterator(raw_data());
1093 }
1094 template <typename Element>
1095 inline typename RepeatedPtrField<Element>::const_iterator
begin()1096 RepeatedPtrField<Element>::begin() const {
1097 return iterator(raw_data());
1098 }
1099 template <typename Element>
1100 inline typename RepeatedPtrField<Element>::iterator
end()1101 RepeatedPtrField<Element>::end() {
1102 return iterator(raw_data() + size());
1103 }
1104 template <typename Element>
1105 inline typename RepeatedPtrField<Element>::const_iterator
end()1106 RepeatedPtrField<Element>::end() const {
1107 return iterator(raw_data() + size());
1108 }
1109
1110 template <typename Element>
1111 inline typename RepeatedPtrField<Element>::pointer_iterator
pointer_begin()1112 RepeatedPtrField<Element>::pointer_begin() {
1113 return pointer_iterator(raw_mutable_data());
1114 }
1115 template <typename Element>
1116 inline typename RepeatedPtrField<Element>::pointer_iterator
pointer_end()1117 RepeatedPtrField<Element>::pointer_end() {
1118 return pointer_iterator(raw_mutable_data() + size());
1119 }
1120
1121
1122 // Iterators and helper functions that follow the spirit of the STL
1123 // std::back_insert_iterator and std::back_inserter but are tailor-made
1124 // for RepeatedField and RepatedPtrField. Typical usage would be:
1125 //
1126 // std::copy(some_sequence.begin(), some_sequence.end(),
1127 // google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
1128 //
1129 // Ported by johannes from util/gtl/proto-array-iterators-inl.h
1130
1131 namespace internal {
1132 // A back inserter for RepeatedField objects.
1133 template<typename T> class RepeatedFieldBackInsertIterator
1134 : public std::iterator<std::output_iterator_tag, T> {
1135 public:
RepeatedFieldBackInsertIterator(RepeatedField<T> * const mutable_field)1136 explicit RepeatedFieldBackInsertIterator(
1137 RepeatedField<T>* const mutable_field)
1138 : field_(mutable_field) {
1139 }
1140 RepeatedFieldBackInsertIterator<T>& operator=(const T& value) {
1141 field_->Add(value);
1142 return *this;
1143 }
1144 RepeatedFieldBackInsertIterator<T>& operator*() {
1145 return *this;
1146 }
1147 RepeatedFieldBackInsertIterator<T>& operator++() {
1148 return *this;
1149 }
1150 RepeatedFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
1151 return *this;
1152 }
1153
1154 private:
1155 RepeatedField<T>* const field_;
1156 };
1157
1158 // A back inserter for RepeatedPtrField objects.
1159 template<typename T> class RepeatedPtrFieldBackInsertIterator
1160 : public std::iterator<std::output_iterator_tag, T> {
1161 public:
RepeatedPtrFieldBackInsertIterator(RepeatedPtrField<T> * const mutable_field)1162 RepeatedPtrFieldBackInsertIterator(
1163 RepeatedPtrField<T>* const mutable_field)
1164 : field_(mutable_field) {
1165 }
1166 RepeatedPtrFieldBackInsertIterator<T>& operator=(const T& value) {
1167 *field_->Add() = value;
1168 return *this;
1169 }
1170 RepeatedPtrFieldBackInsertIterator<T>& operator=(
1171 const T* const ptr_to_value) {
1172 *field_->Add() = *ptr_to_value;
1173 return *this;
1174 }
1175 RepeatedPtrFieldBackInsertIterator<T>& operator*() {
1176 return *this;
1177 }
1178 RepeatedPtrFieldBackInsertIterator<T>& operator++() {
1179 return *this;
1180 }
1181 RepeatedPtrFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
1182 return *this;
1183 }
1184
1185 private:
1186 RepeatedPtrField<T>* const field_;
1187 };
1188
1189 // A back inserter for RepeatedPtrFields that inserts by transfering ownership
1190 // of a pointer.
1191 template<typename T> class AllocatedRepeatedPtrFieldBackInsertIterator
1192 : public std::iterator<std::output_iterator_tag, T> {
1193 public:
AllocatedRepeatedPtrFieldBackInsertIterator(RepeatedPtrField<T> * const mutable_field)1194 explicit AllocatedRepeatedPtrFieldBackInsertIterator(
1195 RepeatedPtrField<T>* const mutable_field)
1196 : field_(mutable_field) {
1197 }
1198 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=(
1199 T* const ptr_to_value) {
1200 field_->AddAllocated(ptr_to_value);
1201 return *this;
1202 }
1203 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() {
1204 return *this;
1205 }
1206 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() {
1207 return *this;
1208 }
1209 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
1210 int ignores_parameter) {
1211 return *this;
1212 }
1213
1214 private:
1215 RepeatedPtrField<T>* const field_;
1216 };
1217 } // namespace internal
1218
1219 // Provides a back insert iterator for RepeatedField instances,
1220 // similar to std::back_inserter(). Note the identically named
1221 // function for RepeatedPtrField instances.
1222 template<typename T> internal::RepeatedFieldBackInsertIterator<T>
RepeatedFieldBackInserter(RepeatedField<T> * const mutable_field)1223 RepeatedFieldBackInserter(RepeatedField<T>* const mutable_field) {
1224 return internal::RepeatedFieldBackInsertIterator<T>(mutable_field);
1225 }
1226
1227 // Provides a back insert iterator for RepeatedPtrField instances,
1228 // similar to std::back_inserter(). Note the identically named
1229 // function for RepeatedField instances.
1230 template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
RepeatedFieldBackInserter(RepeatedPtrField<T> * const mutable_field)1231 RepeatedFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
1232 return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
1233 }
1234
1235 // Provides a back insert iterator for RepeatedPtrField instances
1236 // similar to std::back_inserter() which transfers the ownership while
1237 // copying elements.
1238 template<typename T> internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>
AllocatedRepeatedPtrFieldBackInserter(RepeatedPtrField<T> * const mutable_field)1239 AllocatedRepeatedPtrFieldBackInserter(
1240 RepeatedPtrField<T>* const mutable_field) {
1241 return internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>(
1242 mutable_field);
1243 }
1244
1245 } // namespace protobuf
1246
1247 } // namespace google
1248 #endif // GOOGLE_PROTOBUF_REPEATED_FIELD_H__
1249