blob: 5447fa42af68c2c47d67caaab52634ad0041913a [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
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
jieluo@google.com7ee0f3e2014-07-31 00:24:48 +000049#ifdef _MSC_VER
jieluo@google.com83964a92014-08-07 19:08:05 +000050// This is required for min/max on VS2013 only.
jieluo@google.com7ee0f3e2014-07-31 00:24:48 +000051#include <algorithm>
52#endif
53
temporal40ee5512008-07-10 02:12:20 +000054#include <string>
55#include <iterator>
Feng Xiao6ef984a2014-11-10 17:34:54 -080056#include <google/protobuf/stubs/casts.h>
Feng Xiaoeee38b02015-08-22 18:25:48 -070057#include <google/protobuf/stubs/logging.h>
temporal40ee5512008-07-10 02:12:20 +000058#include <google/protobuf/stubs/common.h>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000059#include <google/protobuf/stubs/type_traits.h>
Feng Xiao6ef984a2014-11-10 17:34:54 -080060#include <google/protobuf/arena.h>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000061#include <google/protobuf/generated_message_util.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000062#include <google/protobuf/message_lite.h>
temporal40ee5512008-07-10 02:12:20 +000063
temporal40ee5512008-07-10 02:12:20 +000064namespace google {
kenton@google.comfccb1462009-12-18 02:11:36 +000065
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000066namespace upb {
liujisi@google.com98080e82013-01-10 21:05:26 +000067namespace google_opensource {
68class GMR_Handlers;
69} // namespace google_opensource
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000070} // namespace upb
71
temporal40ee5512008-07-10 02:12:20 +000072namespace protobuf {
73
kenton@google.com80b1d622009-07-29 01:13:20 +000074class Message;
75
temporal40ee5512008-07-10 02:12:20 +000076namespace internal {
77
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000078static const int kMinRepeatedFieldAllocationSize = 4;
kenton@google.com26bd9ee2008-11-21 00:06:27 +000079
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000080// A utility function for logging that doesn't need any template types.
81void LogIndexOutOfBounds(int index, int size);
jieluo@google.com4de8f552014-07-18 00:47:59 +000082
83template <typename Iter>
84inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) {
85 return std::distance(begin, end);
86}
87
88template <typename Iter>
Austin Schuh918e3ee2014-10-31 16:27:55 -070089inline int CalculateReserve(Iter /*begin*/, Iter /*end*/,
Feng Xiaof157a562014-11-14 11:50:31 -080090 std::input_iterator_tag /*unused*/) {
jieluo@google.com4de8f552014-07-18 00:47:59 +000091 return -1;
92}
93
94template <typename Iter>
95inline int CalculateReserve(Iter begin, Iter end) {
96 typedef typename std::iterator_traits<Iter>::iterator_category Category;
97 return CalculateReserve(begin, end, Category());
98}
temporal40ee5512008-07-10 02:12:20 +000099} // namespace internal
100
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000101
temporal40ee5512008-07-10 02:12:20 +0000102// RepeatedField is used to represent repeated fields of a primitive type (in
103// other words, everything except strings and nested Messages). Most users will
104// not ever use a RepeatedField directly; they will use the get-by-index,
105// set-by-index, and add accessors that are generated for all repeated fields.
106template <typename Element>
kenton@google.com80b1d622009-07-29 01:13:20 +0000107class RepeatedField {
temporal40ee5512008-07-10 02:12:20 +0000108 public:
109 RepeatedField();
Feng Xiao6ef984a2014-11-10 17:34:54 -0800110 explicit RepeatedField(Arena* arena);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000111 RepeatedField(const RepeatedField& other);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000112 template <typename Iter>
113 RepeatedField(Iter begin, const Iter& end);
temporal40ee5512008-07-10 02:12:20 +0000114 ~RepeatedField();
115
liujisi@google.com33165fe2010-11-02 13:14:58 +0000116 RepeatedField& operator=(const RepeatedField& other);
117
jieluo@google.com4de8f552014-07-18 00:47:59 +0000118 bool empty() const;
temporal40ee5512008-07-10 02:12:20 +0000119 int size() const;
120
kenton@google.comfccb1462009-12-18 02:11:36 +0000121 const Element& Get(int index) const;
temporal40ee5512008-07-10 02:12:20 +0000122 Element* Mutable(int index);
kenton@google.comfccb1462009-12-18 02:11:36 +0000123 void Set(int index, const Element& value);
124 void Add(const Element& value);
125 Element* Add();
temporal40ee5512008-07-10 02:12:20 +0000126 // Remove the last element in the array.
temporal40ee5512008-07-10 02:12:20 +0000127 void RemoveLast();
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000128
129 // Extract elements with indices in "[start .. start+num-1]".
130 // Copy them into "elements[0 .. num-1]" if "elements" is not NULL.
131 // Caution: implementation also moves elements with indices [start+num ..].
132 // Calling this routine inside a loop can cause quadratic behavior.
133 void ExtractSubrange(int start, int num, Element* elements);
134
temporal40ee5512008-07-10 02:12:20 +0000135 void Clear();
136 void MergeFrom(const RepeatedField& other);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000137 void CopyFrom(const RepeatedField& other);
temporal40ee5512008-07-10 02:12:20 +0000138
139 // Reserve space to expand the field to at least the given size. If the
140 // array is grown, it will always be at least doubled in size.
141 void Reserve(int new_size);
142
kenton@google.comfccb1462009-12-18 02:11:36 +0000143 // Resize the RepeatedField to a new, smaller size. This is O(1).
144 void Truncate(int new_size);
145
146 void AddAlreadyReserved(const Element& value);
147 Element* AddAlreadyReserved();
148 int Capacity() const;
149
jieluo@google.com4de8f552014-07-18 00:47:59 +0000150 // Like STL resize. Uses value to fill appended elements.
151 // Like Truncate() if new_size <= size(), otherwise this is
152 // O(new_size - size()).
153 void Resize(int new_size, const Element& value);
154
temporal40ee5512008-07-10 02:12:20 +0000155 // Gets the underlying array. This pointer is possibly invalidated by
156 // any add or remove operation.
157 Element* mutable_data();
158 const Element* data() const;
159
Feng Xiao6ef984a2014-11-10 17:34:54 -0800160 // Swap entire contents with "other". If they are separate arenas then, copies
161 // data between each other.
temporal40ee5512008-07-10 02:12:20 +0000162 void Swap(RepeatedField* other);
163
Feng Xiao6ef984a2014-11-10 17:34:54 -0800164 // Swap entire contents with "other". Should be called only if the caller can
165 // guarantee that both repeated fields are on the same arena or are on the
166 // heap. Swapping between different arenas is disallowed and caught by a
167 // GOOGLE_DCHECK (see API docs for details).
168 void UnsafeArenaSwap(RepeatedField* other);
169
kenton@google.com80b1d622009-07-29 01:13:20 +0000170 // Swap two elements.
kenton@google.comceb561d2009-06-25 19:05:36 +0000171 void SwapElements(int index1, int index2);
172
temporal40ee5512008-07-10 02:12:20 +0000173 // STL-like iterator support
174 typedef Element* iterator;
175 typedef const Element* const_iterator;
liujisi@google.com33165fe2010-11-02 13:14:58 +0000176 typedef Element value_type;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000177 typedef value_type& reference;
178 typedef const value_type& const_reference;
179 typedef value_type* pointer;
180 typedef const value_type* const_pointer;
181 typedef int size_type;
182 typedef ptrdiff_t difference_type;
temporal40ee5512008-07-10 02:12:20 +0000183
184 iterator begin();
185 const_iterator begin() const;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800186 const_iterator cbegin() const;
temporal40ee5512008-07-10 02:12:20 +0000187 iterator end();
188 const_iterator end() const;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800189 const_iterator cend() const;
temporal40ee5512008-07-10 02:12:20 +0000190
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000191 // Reverse iterator support
192 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
193 typedef std::reverse_iterator<iterator> reverse_iterator;
194 reverse_iterator rbegin() {
195 return reverse_iterator(end());
196 }
197 const_reverse_iterator rbegin() const {
198 return const_reverse_iterator(end());
199 }
200 reverse_iterator rend() {
201 return reverse_iterator(begin());
202 }
203 const_reverse_iterator rend() const {
204 return const_reverse_iterator(begin());
205 }
206
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000207 // Returns the number of bytes used by the repeated field, excluding
208 // sizeof(*this)
209 int SpaceUsedExcludingSelf() const;
210
Feng Xiaoe841bac2015-12-11 17:09:20 -0800211 // Removes the element referenced by position.
212 //
213 // Returns an iterator to the element immediately following the removed
214 // element.
215 //
216 // Invalidates all iterators at or after the removed element, including end().
Feng Xiao6ef984a2014-11-10 17:34:54 -0800217 iterator erase(const_iterator position);
218
Feng Xiaoe841bac2015-12-11 17:09:20 -0800219 // Removes the elements in the range [first, last).
220 //
221 // Returns an iterator to the element immediately following the removed range.
222 //
223 // Invalidates all iterators at or after the removed range, including end().
Feng Xiao6ef984a2014-11-10 17:34:54 -0800224 iterator erase(const_iterator first, const_iterator last);
225
226 // Get the Arena on which this RepeatedField stores its elements.
227 ::google::protobuf::Arena* GetArena() const {
228 return GetArenaNoVirtual();
229 }
230
temporal40ee5512008-07-10 02:12:20 +0000231 private:
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000232 static const int kInitialSize = 0;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800233 // A note on the representation here (see also comment below for
234 // RepeatedPtrFieldBase's struct Rep):
235 //
236 // We maintain the same sizeof(RepeatedField) as before we added arena support
237 // so that we do not degrade performance by bloating memory usage. Directly
238 // adding an arena_ element to RepeatedField is quite costly. By using
239 // indirection in this way, we keep the same size when the RepeatedField is
240 // empty (common case), and add only an 8-byte header to the elements array
241 // when non-empty. We make sure to place the size fields directly in the
242 // RepeatedField class to avoid costly cache misses due to the indirection.
243 int current_size_;
244 int total_size_;
245 struct Rep {
246 Arena* arena;
247 Element elements[1];
248 };
Feng Xiaobe20ae02014-12-05 02:54:43 -0800249 // We can not use sizeof(Rep) - sizeof(Element) due to the trailing padding on
250 // the struct. We can not use sizeof(Arena*) as well because there might be
251 // a "gap" after the field arena and before the field elements (e.g., when
252 // Element is double and pointer is 32bit).
253 static const size_t kRepHeaderSize;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800254 // Contains arena ptr and the elements array. We also keep the invariant that
255 // if rep_ is NULL, then arena is NULL.
256 Rep* rep_;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000257
Feng Xiao6ef984a2014-11-10 17:34:54 -0800258 friend class Arena;
259 typedef void InternalArenaConstructable_;
temporal40ee5512008-07-10 02:12:20 +0000260
kenton@google.comfccb1462009-12-18 02:11:36 +0000261 // Move the contents of |from| into |to|, possibly clobbering |from| in the
262 // process. For primitive types this is just a memcpy(), but it could be
263 // specialized for non-primitive types to, say, swap each element instead.
Feng Xiao6ef984a2014-11-10 17:34:54 -0800264 void MoveArray(Element* to, Element* from, int size);
kenton@google.comfccb1462009-12-18 02:11:36 +0000265
266 // Copy the elements of |from| into |to|.
Feng Xiao6ef984a2014-11-10 17:34:54 -0800267 void CopyArray(Element* to, const Element* from, int size);
268
269 inline void InternalSwap(RepeatedField* other);
270
271 // Internal helper expected by Arena methods.
272 inline Arena* GetArenaNoVirtual() const {
273 return (rep_ == NULL) ? NULL : rep_->arena;
274 }
temporal40ee5512008-07-10 02:12:20 +0000275};
276
Feng Xiaobe20ae02014-12-05 02:54:43 -0800277template<typename Element>
278const size_t RepeatedField<Element>::kRepHeaderSize =
279 reinterpret_cast<size_t>(&reinterpret_cast<Rep*>(16)->elements[0]) - 16;
280
temporal40ee5512008-07-10 02:12:20 +0000281namespace internal {
282template <typename It> class RepeatedPtrIterator;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000283template <typename It, typename VoidPtr> class RepeatedPtrOverPtrsIterator;
284} // namespace internal
285
286namespace internal {
287
288// This is a helper template to copy an array of elements effeciently when they
289// have a trivial copy constructor, and correctly otherwise. This really
290// shouldn't be necessary, but our compiler doesn't optimize std::copy very
291// effectively.
292template <typename Element,
293 bool HasTrivialCopy = has_trivial_copy<Element>::value>
294struct ElementCopier {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800295 void operator()(Element* to, const Element* from, int array_size);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000296};
297
temporal40ee5512008-07-10 02:12:20 +0000298} // namespace internal
299
kenton@google.com80b1d622009-07-29 01:13:20 +0000300namespace internal {
301
Feng Xiao6ef984a2014-11-10 17:34:54 -0800302// type-traits helper for RepeatedPtrFieldBase: we only want to invoke
303// arena-related "copy if on different arena" behavior if the necessary methods
304// exist on the contained type. In particular, we rely on MergeFrom() existing
305// as a general proxy for the fact that a copy will work, and we also provide a
306// specific override for string*.
307template<typename T>
308struct TypeImplementsMergeBehavior {
309 typedef char HasMerge;
310 typedef long HasNoMerge;
311
312 // We accept either of:
313 // - void MergeFrom(const T& other)
314 // - bool MergeFrom(const T& other)
315 //
316 // We mangle these names a bit to avoid compatibility issues in 'unclean'
317 // include environments that may have, e.g., "#define test ..." (yes, this
318 // exists).
319 template<typename U, typename RetType, RetType (U::*)(const U& arg)>
320 struct CheckType;
321 template<typename U> static HasMerge Check(
322 CheckType<U, void, &U::MergeFrom>*);
323 template<typename U> static HasMerge Check(
324 CheckType<U, bool, &U::MergeFrom>*);
325 template<typename U> static HasNoMerge Check(...);
326
327 // Resovles to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
328 typedef google::protobuf::internal::integral_constant<bool,
329 (sizeof(Check<T>(0)) == sizeof(HasMerge))> type;
330};
331
332template<>
333struct TypeImplementsMergeBehavior< ::std::string > {
334 typedef google::protobuf::internal::true_type type;
335};
336
kenton@google.com80b1d622009-07-29 01:13:20 +0000337// This is the common base class for RepeatedPtrFields. It deals only in void*
338// pointers. Users should not use this interface directly.
339//
340// The methods of this interface correspond to the methods of RepeatedPtrField,
341// but may have a template argument called TypeHandler. Its signature is:
342// class TypeHandler {
343// public:
344// typedef MyType Type;
345// static Type* New();
346// static void Delete(Type*);
347// static void Clear(Type*);
348// static void Merge(const Type& from, Type* to);
349//
350// // Only needs to be implemented if SpaceUsedExcludingSelf() is called.
351// static int SpaceUsed(const Type&);
352// };
353class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
354 protected:
355 // The reflection implementation needs to call protected methods directly,
356 // reinterpreting pointers as being to Message instead of a specific Message
357 // subclass.
358 friend class GeneratedMessageReflection;
359
360 // ExtensionSet stores repeated message extensions as
361 // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to
362 // implement SpaceUsed(), and thus need to call SpaceUsedExcludingSelf()
363 // reinterpreting MessageLite as Message. ExtensionSet also needs to make
364 // use of AddFromCleared(), which is not part of the public interface.
365 friend class ExtensionSet;
366
Feng Xiaof157a562014-11-14 11:50:31 -0800367 // The MapFieldBase implementation needs to call protected methods directly,
368 // reinterpreting pointers as being to Message instead of a specific Message
369 // subclass.
370 friend class MapFieldBase;
371
liujisi@google.com98080e82013-01-10 21:05:26 +0000372 // To parse directly into a proto2 generated class, the upb class GMR_Handlers
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000373 // needs to be able to modify a RepeatedPtrFieldBase directly.
Feng Xiaoeee38b02015-08-22 18:25:48 -0700374 friend class upb::google_opensource::GMR_Handlers;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000375
kenton@google.com80b1d622009-07-29 01:13:20 +0000376 RepeatedPtrFieldBase();
Feng Xiao6ef984a2014-11-10 17:34:54 -0800377 explicit RepeatedPtrFieldBase(::google::protobuf::Arena* arena);
378 ~RepeatedPtrFieldBase() {}
kenton@google.com80b1d622009-07-29 01:13:20 +0000379
380 // Must be called from destructor.
381 template <typename TypeHandler>
382 void Destroy();
383
jieluo@google.com4de8f552014-07-18 00:47:59 +0000384 bool empty() const;
kenton@google.com80b1d622009-07-29 01:13:20 +0000385 int size() const;
386
387 template <typename TypeHandler>
388 const typename TypeHandler::Type& Get(int index) const;
389 template <typename TypeHandler>
390 typename TypeHandler::Type* Mutable(int index);
391 template <typename TypeHandler>
Feng Xiao6ef984a2014-11-10 17:34:54 -0800392 void Delete(int index);
393 template <typename TypeHandler>
394 typename TypeHandler::Type* Add(typename TypeHandler::Type* prototype = NULL);
395
kenton@google.com80b1d622009-07-29 01:13:20 +0000396 template <typename TypeHandler>
397 void RemoveLast();
398 template <typename TypeHandler>
399 void Clear();
400 template <typename TypeHandler>
401 void MergeFrom(const RepeatedPtrFieldBase& other);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000402 template <typename TypeHandler>
403 void CopyFrom(const RepeatedPtrFieldBase& other);
kenton@google.com80b1d622009-07-29 01:13:20 +0000404
Feng Xiao6ef984a2014-11-10 17:34:54 -0800405 void CloseGap(int start, int num);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000406
kenton@google.com80b1d622009-07-29 01:13:20 +0000407 void Reserve(int new_size);
408
kenton@google.comfccb1462009-12-18 02:11:36 +0000409 int Capacity() const;
410
kenton@google.com80b1d622009-07-29 01:13:20 +0000411 // Used for constructing iterators.
412 void* const* raw_data() const;
kenton@google.comfccb1462009-12-18 02:11:36 +0000413 void** raw_mutable_data() const;
kenton@google.com80b1d622009-07-29 01:13:20 +0000414
415 template <typename TypeHandler>
416 typename TypeHandler::Type** mutable_data();
417 template <typename TypeHandler>
418 const typename TypeHandler::Type* const* data() const;
419
Feng Xiao6ef984a2014-11-10 17:34:54 -0800420 template <typename TypeHandler>
Feng Xiaoeee38b02015-08-22 18:25:48 -0700421 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(RepeatedPtrFieldBase* other);
kenton@google.com80b1d622009-07-29 01:13:20 +0000422
423 void SwapElements(int index1, int index2);
424
425 template <typename TypeHandler>
426 int SpaceUsedExcludingSelf() const;
427
kenton@google.comfccb1462009-12-18 02:11:36 +0000428
kenton@google.com80b1d622009-07-29 01:13:20 +0000429 // Advanced memory management --------------------------------------
430
431 // Like Add(), but if there are no cleared objects to use, returns NULL.
432 template <typename TypeHandler>
433 typename TypeHandler::Type* AddFromCleared();
434
Feng Xiao6ef984a2014-11-10 17:34:54 -0800435 template<typename TypeHandler>
436 void AddAllocated(typename TypeHandler::Type* value) {
437 typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
438 AddAllocatedInternal<TypeHandler>(value, t);
439 }
440
kenton@google.com80b1d622009-07-29 01:13:20 +0000441 template <typename TypeHandler>
Feng Xiao6ef984a2014-11-10 17:34:54 -0800442 void UnsafeArenaAddAllocated(typename TypeHandler::Type* value);
443
kenton@google.com80b1d622009-07-29 01:13:20 +0000444 template <typename TypeHandler>
Feng Xiao6ef984a2014-11-10 17:34:54 -0800445 typename TypeHandler::Type* ReleaseLast() {
446 typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
447 return ReleaseLastInternal<TypeHandler>(t);
448 }
449
450 // Releases last element and returns it, but does not do out-of-arena copy.
451 // And just returns the raw pointer to the contained element in the arena.
452 template <typename TypeHandler>
453 typename TypeHandler::Type* UnsafeArenaReleaseLast();
kenton@google.com80b1d622009-07-29 01:13:20 +0000454
kenton@google.comfccb1462009-12-18 02:11:36 +0000455 int ClearedCount() const;
kenton@google.com80b1d622009-07-29 01:13:20 +0000456 template <typename TypeHandler>
457 void AddCleared(typename TypeHandler::Type* value);
458 template <typename TypeHandler>
459 typename TypeHandler::Type* ReleaseCleared();
460
Feng Xiao6ef984a2014-11-10 17:34:54 -0800461 protected:
462 inline void InternalSwap(RepeatedPtrFieldBase* other);
463
464 template <typename TypeHandler>
465 void AddAllocatedInternal(typename TypeHandler::Type* value,
466 google::protobuf::internal::true_type);
467 template <typename TypeHandler>
468 void AddAllocatedInternal(typename TypeHandler::Type* value,
469 google::protobuf::internal::false_type);
470
Feng Xiaoeee38b02015-08-22 18:25:48 -0700471 template <typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
Feng Xiao6ef984a2014-11-10 17:34:54 -0800472 void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value,
473 Arena* value_arena,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700474 Arena* my_arena);
475 template <typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
476 void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800477
478 template <typename TypeHandler>
479 typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::true_type);
480 template <typename TypeHandler>
481 typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::false_type);
482
Feng Xiaoeee38b02015-08-22 18:25:48 -0700483 template<typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
484 void SwapFallback(RepeatedPtrFieldBase* other);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800485
486 inline Arena* GetArenaNoVirtual() const {
487 return arena_;
488 }
489
kenton@google.com80b1d622009-07-29 01:13:20 +0000490 private:
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000491 static const int kInitialSize = 0;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800492 // A few notes on internal representation:
493 //
494 // We use an indirected approach, with struct Rep, to keep
495 // sizeof(RepeatedPtrFieldBase) equivalent to what it was before arena support
496 // was added, namely, 3 8-byte machine words on x86-64. An instance of Rep is
497 // allocated only when the repeated field is non-empty, and it is a
498 // dynamically-sized struct (the header is directly followed by elements[]).
499 // We place arena_ and current_size_ directly in the object to avoid cache
500 // misses due to the indirection, because these fields are checked frequently.
501 // Placing all fields directly in the RepeatedPtrFieldBase instance costs
502 // significant performance for memory-sensitive workloads.
503 Arena* arena_;
kenton@google.com80b1d622009-07-29 01:13:20 +0000504 int current_size_;
kenton@google.com80b1d622009-07-29 01:13:20 +0000505 int total_size_;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800506 struct Rep {
507 int allocated_size;
508 void* elements[1];
509 };
510 static const size_t kRepHeaderSize = sizeof(Rep) - sizeof(void*);
511 // Contains arena ptr and the elements array. We also keep the invariant that
512 // if rep_ is NULL, then arena is NULL.
513 Rep* rep_;
kenton@google.com80b1d622009-07-29 01:13:20 +0000514
kenton@google.com80b1d622009-07-29 01:13:20 +0000515 template <typename TypeHandler>
516 static inline typename TypeHandler::Type* cast(void* element) {
517 return reinterpret_cast<typename TypeHandler::Type*>(element);
518 }
519 template <typename TypeHandler>
520 static inline const typename TypeHandler::Type* cast(const void* element) {
521 return reinterpret_cast<const typename TypeHandler::Type*>(element);
522 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000523
Feng Xiao6ef984a2014-11-10 17:34:54 -0800524 // Non-templated inner function to avoid code duplication. Takes a function
525 // pointer to the type-specific (templated) inner allocate/merge loop.
526 void MergeFromInternal(
527 const RepeatedPtrFieldBase& other,
528 void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int));
529
530 template<typename TypeHandler>
531 void MergeFromInnerLoop(
532 void** our_elems, void** other_elems, int length, int already_allocated);
533
534 // Internal helper: extend array space if necessary to contain |extend_amount|
535 // more elements, and return a pointer to the element immediately following
536 // the old list of elements. This interface factors out common behavior from
537 // Reserve() and MergeFrom() to reduce code size. |extend_amount| must be > 0.
538 void** InternalExtend(int extend_amount);
539
jieluo@google.com4de8f552014-07-18 00:47:59 +0000540 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
kenton@google.com80b1d622009-07-29 01:13:20 +0000541};
542
543template <typename GenericType>
544class GenericTypeHandler {
545 public:
546 typedef GenericType Type;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800547 static inline GenericType* New(Arena* arena) {
548 return ::google::protobuf::Arena::CreateMaybeMessage<Type>(
549 arena, static_cast<GenericType*>(0));
550 }
551 // We force NewFromPrototype() and Delete() to be non-inline to reduce code
552 // size: else, several other methods get inlined copies of message types'
Feng Xiaoeee38b02015-08-22 18:25:48 -0700553 // constructors and destructors.
554 GOOGLE_ATTRIBUTE_NOINLINE static GenericType* NewFromPrototype(
555 const GenericType* prototype, ::google::protobuf::Arena* arena = NULL);
556 GOOGLE_ATTRIBUTE_NOINLINE static void Delete(GenericType* value, Arena* arena);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800557 static inline ::google::protobuf::Arena* GetArena(GenericType* value) {
558 return ::google::protobuf::Arena::GetArena<Type>(value);
559 }
560 static inline void* GetMaybeArenaPointer(GenericType* value) {
561 return ::google::protobuf::Arena::GetArena<Type>(value);
562 }
563
564 static inline void Clear(GenericType* value) { value->Clear(); }
Feng Xiaoeee38b02015-08-22 18:25:48 -0700565 GOOGLE_ATTRIBUTE_NOINLINE static void Merge(const GenericType& from,
566 GenericType* to);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800567 static inline int SpaceUsed(const GenericType& value) {
568 return value.SpaceUsed();
569 }
570 static inline const Type& default_instance() {
571 return Type::default_instance();
572 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000573};
574
Feng Xiaoeee38b02015-08-22 18:25:48 -0700575template <typename GenericType>
576GenericType* GenericTypeHandler<GenericType>::NewFromPrototype(
Swen Kooij37d6cf92016-01-28 11:40:07 +0200577 const GenericType* /* prototype */, ::google::protobuf::Arena* arena) {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700578 return New(arena);
Bo Yang5db21732015-05-21 14:28:59 -0700579}
Feng Xiaoeee38b02015-08-22 18:25:48 -0700580template <typename GenericType>
581void GenericTypeHandler<GenericType>::Delete(GenericType* value, Arena* arena) {
582 if (arena == NULL) {
583 delete value;
584 }
585}
586template <typename GenericType>
587void GenericTypeHandler<GenericType>::Merge(const GenericType& from,
588 GenericType* to) {
589 to->MergeFrom(from);
590}
591
592// NewFromPrototype() and Merge() cannot be defined here; if they're declared
593// inline the compiler will complain about not matching GOOGLE_ATTRIBUTE_NOINLINE
594// above, and if not, compilation will result in multiple definitions. These
595// are therefore declared as specializations here and defined in
596// message_lite.cc.
597template<>
598MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
599 const MessageLite* prototype, google::protobuf::Arena* arena);
Bo Yang5db21732015-05-21 14:28:59 -0700600template<>
601inline google::protobuf::Arena* GenericTypeHandler<MessageLite>::GetArena(
602 MessageLite* value) {
603 return value->GetArena();
604}
605template<>
606inline void* GenericTypeHandler<MessageLite>::GetMaybeArenaPointer(
607 MessageLite* value) {
608 return value->GetMaybeArenaPointer();
609}
kenton@google.com80b1d622009-07-29 01:13:20 +0000610template <>
Feng Xiaoeee38b02015-08-22 18:25:48 -0700611void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
612 MessageLite* to);
kenton@google.com80b1d622009-07-29 01:13:20 +0000613
Feng Xiao6ef984a2014-11-10 17:34:54 -0800614// Declarations of the specialization as we cannot define them here, as the
615// header that defines ProtocolMessage depends on types defined in this header.
616#define DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(TypeName) \
617 template<> \
618 TypeName* GenericTypeHandler<TypeName>::NewFromPrototype( \
619 const TypeName* prototype, google::protobuf::Arena* arena); \
620 template<> \
621 google::protobuf::Arena* GenericTypeHandler<TypeName>::GetArena( \
622 TypeName* value); \
623 template<> \
624 void* GenericTypeHandler<TypeName>::GetMaybeArenaPointer( \
625 TypeName* value);
626
627// Message specialization bodies defined in message.cc. This split is necessary
628// to allow proto2-lite (which includes this header) to be independent of
629// Message.
Swen Kooij37d6cf92016-01-28 11:40:07 +0200630DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message)
Feng Xiao6ef984a2014-11-10 17:34:54 -0800631
632
Bo Yangd6c9f642015-04-24 15:34:40 -0700633#undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES
Feng Xiao6ef984a2014-11-10 17:34:54 -0800634
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000635template <>
636inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
637 // Yes, the behavior of the code is undefined, but this function is only
638 // called when we're already deep into the world of undefined, because the
639 // caller called Get(index) out of bounds.
640 MessageLite* null = NULL;
641 return *null;
642}
643
644template <>
645inline const Message& GenericTypeHandler<Message>::default_instance() {
646 // Yes, the behavior of the code is undefined, but this function is only
647 // called when we're already deep into the world of undefined, because the
648 // caller called Get(index) out of bounds.
649 Message* null = NULL;
650 return *null;
651}
652
653
kenton@google.com9270a992009-08-01 02:16:55 +0000654// HACK: If a class is declared as DLL-exported in MSVC, it insists on
655// generating copies of all its methods -- even inline ones -- to include
656// in the DLL. But SpaceUsed() calls StringSpaceUsedExcludingSelf() which
657// isn't in the lite library, therefore the lite library cannot link if
658// StringTypeHandler is exported. So, we factor out StringTypeHandlerBase,
659// export that, then make StringTypeHandler be a subclass which is NOT
660// exported.
Jisi Liu46e8ff62015-10-05 11:59:43 -0700661// TODO(kenton): Now that StringSpaceUsedExcludingSelf() is in the lite
Peter Kastingb913cbd2015-08-27 14:37:18 -0700662// library, this can be cleaned up.
kenton@google.com9270a992009-08-01 02:16:55 +0000663class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
kenton@google.com80b1d622009-07-29 01:13:20 +0000664 public:
665 typedef string Type;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800666
667 static inline string* New(Arena* arena) {
668 return Arena::Create<string>(arena);
669 }
670 static inline string* NewFromPrototype(const string*,
671 ::google::protobuf::Arena* arena) {
672 return New(arena);
673 }
674 static inline ::google::protobuf::Arena* GetArena(string*) {
675 return NULL;
676 }
Swen Kooij37d6cf92016-01-28 11:40:07 +0200677 static inline void* GetMaybeArenaPointer(string* /* value */) {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800678 return NULL;
679 }
680 static inline void Delete(string* value, Arena* arena) {
681 if (arena == NULL) {
682 delete value;
683 }
684 }
685 static inline void Clear(string* value) { value->clear(); }
686 static inline void Merge(const string& from, string* to) { *to = from; }
687 static inline const Type& default_instance() {
xiaofeng@google.com37c74262014-02-13 22:09:48 +0000688 return ::google::protobuf::internal::GetEmptyString();
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000689 }
kenton@google.com9270a992009-08-01 02:16:55 +0000690};
691
liujisi@google.com2a89d002011-07-05 17:16:07 +0000692class StringTypeHandler : public StringTypeHandlerBase {
kenton@google.com9270a992009-08-01 02:16:55 +0000693 public:
kenton@google.com80b1d622009-07-29 01:13:20 +0000694 static int SpaceUsed(const string& value) {
John Burke3937ded2016-01-19 15:13:25 -0800695 return static_cast<int>(sizeof(value)) + StringSpaceUsedExcludingSelf(value);
kenton@google.com80b1d622009-07-29 01:13:20 +0000696 }
697};
698
kenton@google.comfccb1462009-12-18 02:11:36 +0000699
kenton@google.com80b1d622009-07-29 01:13:20 +0000700} // namespace internal
701
temporal40ee5512008-07-10 02:12:20 +0000702// RepeatedPtrField is like RepeatedField, but used for repeated strings or
703// Messages.
704template <typename Element>
kenton@google.com80b1d622009-07-29 01:13:20 +0000705class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
temporal40ee5512008-07-10 02:12:20 +0000706 public:
707 RepeatedPtrField();
Feng Xiao6ef984a2014-11-10 17:34:54 -0800708 explicit RepeatedPtrField(::google::protobuf::Arena* arena);
709
liujisi@google.com33165fe2010-11-02 13:14:58 +0000710 RepeatedPtrField(const RepeatedPtrField& other);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000711 template <typename Iter>
712 RepeatedPtrField(Iter begin, const Iter& end);
temporal40ee5512008-07-10 02:12:20 +0000713 ~RepeatedPtrField();
714
liujisi@google.com33165fe2010-11-02 13:14:58 +0000715 RepeatedPtrField& operator=(const RepeatedPtrField& other);
716
jieluo@google.com4de8f552014-07-18 00:47:59 +0000717 bool empty() const;
temporal40ee5512008-07-10 02:12:20 +0000718 int size() const;
719
720 const Element& Get(int index) const;
721 Element* Mutable(int index);
722 Element* Add();
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000723
724 // Remove the last element in the array.
725 // Ownership of the element is retained by the array.
726 void RemoveLast();
727
728 // Delete elements with indices in the range [start .. start+num-1].
729 // Caution: implementation moves all elements with indices [start+num .. ].
730 // Calling this routine inside a loop can cause quadratic behavior.
731 void DeleteSubrange(int start, int num);
732
temporal40ee5512008-07-10 02:12:20 +0000733 void Clear();
734 void MergeFrom(const RepeatedPtrField& other);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000735 void CopyFrom(const RepeatedPtrField& other);
temporal40ee5512008-07-10 02:12:20 +0000736
737 // Reserve space to expand the field to at least the given size. This only
738 // resizes the pointer array; it doesn't allocate any objects. If the
739 // array is grown, it will always be at least doubled in size.
740 void Reserve(int new_size);
741
kenton@google.comfccb1462009-12-18 02:11:36 +0000742 int Capacity() const;
743
temporal40ee5512008-07-10 02:12:20 +0000744 // Gets the underlying array. This pointer is possibly invalidated by
745 // any add or remove operation.
746 Element** mutable_data();
747 const Element* const* data() const;
748
Feng Xiao6ef984a2014-11-10 17:34:54 -0800749 // Swap entire contents with "other". If they are on separate arenas, then
750 // copies data.
temporal40ee5512008-07-10 02:12:20 +0000751 void Swap(RepeatedPtrField* other);
752
Feng Xiao6ef984a2014-11-10 17:34:54 -0800753 // Swap entire contents with "other". Caller should guarantee that either both
754 // fields are on the same arena or both are on the heap. Swapping between
755 // different arenas with this function is disallowed and is caught via
756 // GOOGLE_DCHECK.
757 void UnsafeArenaSwap(RepeatedPtrField* other);
758
kenton@google.com80b1d622009-07-29 01:13:20 +0000759 // Swap two elements.
kenton@google.comceb561d2009-06-25 19:05:36 +0000760 void SwapElements(int index1, int index2);
761
temporal40ee5512008-07-10 02:12:20 +0000762 // STL-like iterator support
kenton@google.com80b1d622009-07-29 01:13:20 +0000763 typedef internal::RepeatedPtrIterator<Element> iterator;
764 typedef internal::RepeatedPtrIterator<const Element> const_iterator;
liujisi@google.com33165fe2010-11-02 13:14:58 +0000765 typedef Element value_type;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000766 typedef value_type& reference;
767 typedef const value_type& const_reference;
768 typedef value_type* pointer;
769 typedef const value_type* const_pointer;
770 typedef int size_type;
771 typedef ptrdiff_t difference_type;
temporal40ee5512008-07-10 02:12:20 +0000772
773 iterator begin();
774 const_iterator begin() const;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800775 const_iterator cbegin() const;
temporal40ee5512008-07-10 02:12:20 +0000776 iterator end();
777 const_iterator end() const;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800778 const_iterator cend() const;
temporal40ee5512008-07-10 02:12:20 +0000779
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000780 // Reverse iterator support
781 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
782 typedef std::reverse_iterator<iterator> reverse_iterator;
783 reverse_iterator rbegin() {
784 return reverse_iterator(end());
785 }
786 const_reverse_iterator rbegin() const {
787 return const_reverse_iterator(end());
788 }
789 reverse_iterator rend() {
790 return reverse_iterator(begin());
791 }
792 const_reverse_iterator rend() const {
793 return const_reverse_iterator(begin());
794 }
795
kenton@google.comfccb1462009-12-18 02:11:36 +0000796 // Custom STL-like iterator that iterates over and returns the underlying
797 // pointers to Element rather than Element itself.
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000798 typedef internal::RepeatedPtrOverPtrsIterator<Element, void*>
799 pointer_iterator;
800 typedef internal::RepeatedPtrOverPtrsIterator<const Element, const void*>
801 const_pointer_iterator;
kenton@google.comfccb1462009-12-18 02:11:36 +0000802 pointer_iterator pointer_begin();
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000803 const_pointer_iterator pointer_begin() const;
kenton@google.comfccb1462009-12-18 02:11:36 +0000804 pointer_iterator pointer_end();
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000805 const_pointer_iterator pointer_end() const;
kenton@google.comfccb1462009-12-18 02:11:36 +0000806
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000807 // Returns (an estimate of) the number of bytes used by the repeated field,
808 // excluding sizeof(*this).
809 int SpaceUsedExcludingSelf() const;
810
temporal40ee5512008-07-10 02:12:20 +0000811 // Advanced memory management --------------------------------------
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000812 // When hardcore memory management becomes necessary -- as it sometimes
temporal40ee5512008-07-10 02:12:20 +0000813 // does here at Google -- the following methods may be useful.
814
815 // Add an already-allocated object, passing ownership to the
816 // RepeatedPtrField.
Feng Xiao6ef984a2014-11-10 17:34:54 -0800817 //
818 // Note that some special behavior occurs with respect to arenas:
819 //
820 // (i) if this field holds submessages, the new submessage will be copied if
821 // the original is in an arena and this RepeatedPtrField is either in a
822 // different arena, or on the heap.
823 // (ii) if this field holds strings, the passed-in string *must* be
824 // heap-allocated, not arena-allocated. There is no way to dynamically check
825 // this at runtime, so User Beware.
temporal40ee5512008-07-10 02:12:20 +0000826 void AddAllocated(Element* value);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800827
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000828 // Remove the last element and return it, passing ownership to the caller.
temporal40ee5512008-07-10 02:12:20 +0000829 // Requires: size() > 0
Feng Xiao6ef984a2014-11-10 17:34:54 -0800830 //
831 // If this RepeatedPtrField is on an arena, an object copy is required to pass
832 // ownership back to the user (for compatible semantics). Use
833 // UnsafeArenaReleaseLast() if this behavior is undesired.
temporal40ee5512008-07-10 02:12:20 +0000834 Element* ReleaseLast();
835
Feng Xiao6ef984a2014-11-10 17:34:54 -0800836 // Add an already-allocated object, skipping arena-ownership checks. The user
837 // must guarantee that the given object is in the same arena as this
838 // RepeatedPtrField.
839 void UnsafeArenaAddAllocated(Element* value);
840
841 // Remove the last element and return it. Works only when operating on an
842 // arena. The returned pointer is to the original object in the arena, hence
843 // has the arena's lifetime.
844 // Requires: current_size_ > 0
845 Element* UnsafeArenaReleaseLast();
846
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000847 // Extract elements with indices in the range "[start .. start+num-1]".
848 // The caller assumes ownership of the extracted elements and is responsible
849 // for deleting them when they are no longer needed.
850 // If "elements" is non-NULL, then pointers to the extracted elements
851 // are stored in "elements[0 .. num-1]" for the convenience of the caller.
852 // If "elements" is NULL, then the caller must use some other mechanism
853 // to perform any further operations (like deletion) on these elements.
854 // Caution: implementation also moves elements with indices [start+num ..].
855 // Calling this routine inside a loop can cause quadratic behavior.
Feng Xiao6ef984a2014-11-10 17:34:54 -0800856 //
857 // Memory copying behavior is identical to ReleaseLast(), described above: if
858 // this RepeatedPtrField is on an arena, an object copy is performed for each
859 // returned element, so that all returned element pointers are to
860 // heap-allocated copies. If this copy is not desired, the user should call
861 // UnsafeArenaExtractSubrange().
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000862 void ExtractSubrange(int start, int num, Element** elements);
863
Feng Xiao6ef984a2014-11-10 17:34:54 -0800864 // Identical to ExtractSubrange() described above, except that when this
865 // repeated field is on an arena, no object copies are performed. Instead, the
866 // raw object pointers are returned. Thus, if on an arena, the returned
867 // objects must not be freed, because they will not be heap-allocated objects.
868 void UnsafeArenaExtractSubrange(int start, int num, Element** elements);
869
temporal40ee5512008-07-10 02:12:20 +0000870 // When elements are removed by calls to RemoveLast() or Clear(), they
871 // are not actually freed. Instead, they are cleared and kept so that
872 // they can be reused later. This can save lots of CPU time when
873 // repeatedly reusing a protocol message for similar purposes.
874 //
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000875 // Hardcore programs may choose to manipulate these cleared objects
876 // to better optimize memory management using the following routines.
temporal40ee5512008-07-10 02:12:20 +0000877
878 // Get the number of cleared objects that are currently being kept
879 // around for reuse.
kenton@google.comfccb1462009-12-18 02:11:36 +0000880 int ClearedCount() const;
temporal40ee5512008-07-10 02:12:20 +0000881 // Add an element to the pool of cleared objects, passing ownership to
882 // the RepeatedPtrField. The element must be cleared prior to calling
883 // this method.
Feng Xiao6ef984a2014-11-10 17:34:54 -0800884 //
885 // This method cannot be called when the repeated field is on an arena or when
886 // |value| is; both cases will trigger a GOOGLE_DCHECK-failure.
temporal40ee5512008-07-10 02:12:20 +0000887 void AddCleared(Element* value);
888 // Remove a single element from the cleared pool and return it, passing
889 // ownership to the caller. The element is guaranteed to be cleared.
890 // Requires: ClearedCount() > 0
Feng Xiao6ef984a2014-11-10 17:34:54 -0800891 //
892 //
893 // This method cannot be called when the repeated field is on an arena; doing
894 // so will trigger a GOOGLE_DCHECK-failure.
temporal40ee5512008-07-10 02:12:20 +0000895 Element* ReleaseCleared();
896
Feng Xiaoe841bac2015-12-11 17:09:20 -0800897 // Removes the element referenced by position.
898 //
899 // Returns an iterator to the element immediately following the removed
900 // element.
901 //
902 // Invalidates all iterators at or after the removed element, including end().
Feng Xiao6ef984a2014-11-10 17:34:54 -0800903 iterator erase(const_iterator position);
904
905 // Removes the elements in the range [first, last).
Feng Xiaoe841bac2015-12-11 17:09:20 -0800906 //
907 // Returns an iterator to the element immediately following the removed range.
908 //
909 // Invalidates all iterators at or after the removed range, including end().
Feng Xiao6ef984a2014-11-10 17:34:54 -0800910 iterator erase(const_iterator first, const_iterator last);
911
912 // Gets the arena on which this RepeatedPtrField stores its elements.
913 ::google::protobuf::Arena* GetArena() const {
914 return GetArenaNoVirtual();
915 }
916
kenton@google.comfccb1462009-12-18 02:11:36 +0000917 protected:
918 // Note: RepeatedPtrField SHOULD NOT be subclassed by users. We only
919 // subclass it in one place as a hack for compatibility with proto1. The
920 // subclass needs to know about TypeHandler in order to call protected
921 // methods on RepeatedPtrFieldBase.
kenton@google.com80b1d622009-07-29 01:13:20 +0000922 class TypeHandler;
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000923
Feng Xiao6ef984a2014-11-10 17:34:54 -0800924 // Internal arena accessor expected by helpers in Arena.
925 inline Arena* GetArenaNoVirtual() const;
926
927 private:
928 // Implementations for ExtractSubrange(). The copying behavior must be
929 // included only if the type supports the necessary operations (e.g.,
930 // MergeFrom()), so we must resolve this at compile time. ExtractSubrange()
931 // uses SFINAE to choose one of the below implementations.
932 void ExtractSubrangeInternal(int start, int num, Element** elements,
933 google::protobuf::internal::true_type);
934 void ExtractSubrangeInternal(int start, int num, Element** elements,
935 google::protobuf::internal::false_type);
936
937 friend class Arena;
938 typedef void InternalArenaConstructable_;
939
temporal40ee5512008-07-10 02:12:20 +0000940};
941
942// implementation ====================================================
943
944template <typename Element>
945inline RepeatedField<Element>::RepeatedField()
Feng Xiao6ef984a2014-11-10 17:34:54 -0800946 : current_size_(0),
947 total_size_(0),
948 rep_(NULL) {
949}
950
951template <typename Element>
952inline RepeatedField<Element>::RepeatedField(Arena* arena)
953 : current_size_(0),
954 total_size_(0),
955 rep_(NULL) {
956 // In case arena is NULL, then we do not create rep_, as code has an invariant
957 // `rep_ == NULL then arena == NULL`.
958 if (arena != NULL) {
959 rep_ = reinterpret_cast<Rep*>(
960 ::google::protobuf::Arena::CreateArray<char>(arena, kRepHeaderSize));
961 rep_->arena = arena;
962 }
temporal40ee5512008-07-10 02:12:20 +0000963}
964
965template <typename Element>
liujisi@google.com33165fe2010-11-02 13:14:58 +0000966inline RepeatedField<Element>::RepeatedField(const RepeatedField& other)
Feng Xiao6ef984a2014-11-10 17:34:54 -0800967 : current_size_(0),
968 total_size_(0),
969 rep_(NULL) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000970 CopyFrom(other);
971}
972
973template <typename Element>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000974template <typename Iter>
Feng Xiao6ef984a2014-11-10 17:34:54 -0800975RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
976 : current_size_(0),
977 total_size_(0),
978 rep_(NULL) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000979 int reserve = internal::CalculateReserve(begin, end);
980 if (reserve != -1) {
981 Reserve(reserve);
982 for (; begin != end; ++begin) {
983 AddAlreadyReserved(*begin);
984 }
985 } else {
986 for (; begin != end; ++begin) {
987 Add(*begin);
988 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000989 }
990}
991
992template <typename Element>
temporal40ee5512008-07-10 02:12:20 +0000993RepeatedField<Element>::~RepeatedField() {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800994 // See explanation in Reserve(): we need to invoke destructors here for the
995 // case that Element has a non-trivial destructor. If Element has a trivial
996 // destructor (for example, if it's a primitive type, like int32), this entire
997 // loop will be removed by the optimizer.
998 if (rep_ != NULL) {
999 Element* e = &rep_->elements[0];
1000 Element* limit = &rep_->elements[total_size_];
1001 for (; e < limit; e++) {
1002 e->Element::~Element();
1003 }
1004 if (rep_->arena == NULL) {
1005 delete[] reinterpret_cast<char*>(rep_);
1006 }
1007 }
temporal40ee5512008-07-10 02:12:20 +00001008}
1009
1010template <typename Element>
liujisi@google.com33165fe2010-11-02 13:14:58 +00001011inline RepeatedField<Element>&
1012RepeatedField<Element>::operator=(const RepeatedField& other) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001013 if (this != &other)
1014 CopyFrom(other);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001015 return *this;
1016}
1017
1018template <typename Element>
jieluo@google.com4de8f552014-07-18 00:47:59 +00001019inline bool RepeatedField<Element>::empty() const {
1020 return current_size_ == 0;
1021}
1022
1023template <typename Element>
temporal40ee5512008-07-10 02:12:20 +00001024inline int RepeatedField<Element>::size() const {
1025 return current_size_;
1026}
1027
kenton@google.comfccb1462009-12-18 02:11:36 +00001028template <typename Element>
1029inline int RepeatedField<Element>::Capacity() const {
1030 return total_size_;
1031}
1032
1033template<typename Element>
1034inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001035 GOOGLE_DCHECK_LT(current_size_, total_size_);
1036 rep_->elements[current_size_++] = value;
kenton@google.comfccb1462009-12-18 02:11:36 +00001037}
1038
1039template<typename Element>
1040inline Element* RepeatedField<Element>::AddAlreadyReserved() {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001041 GOOGLE_DCHECK_LT(current_size_, total_size_);
1042 return &rep_->elements[current_size_++];
kenton@google.comfccb1462009-12-18 02:11:36 +00001043}
temporal40ee5512008-07-10 02:12:20 +00001044
jieluo@google.com4de8f552014-07-18 00:47:59 +00001045template<typename Element>
1046inline void RepeatedField<Element>::Resize(int new_size, const Element& value) {
1047 GOOGLE_DCHECK_GE(new_size, 0);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001048 if (new_size > current_size_) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001049 Reserve(new_size);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001050 std::fill(&rep_->elements[current_size_],
1051 &rep_->elements[new_size], value);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001052 }
1053 current_size_ = new_size;
1054}
1055
temporal40ee5512008-07-10 02:12:20 +00001056template <typename Element>
kenton@google.comfccb1462009-12-18 02:11:36 +00001057inline const Element& RepeatedField<Element>::Get(int index) const {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001058 GOOGLE_DCHECK_GE(index, 0);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001059 GOOGLE_DCHECK_LT(index, current_size_);
1060 return rep_->elements[index];
temporal40ee5512008-07-10 02:12:20 +00001061}
1062
1063template <typename Element>
1064inline Element* RepeatedField<Element>::Mutable(int index) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001065 GOOGLE_DCHECK_GE(index, 0);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001066 GOOGLE_DCHECK_LT(index, current_size_);
1067 return &rep_->elements[index];
temporal40ee5512008-07-10 02:12:20 +00001068}
1069
1070template <typename Element>
kenton@google.comfccb1462009-12-18 02:11:36 +00001071inline void RepeatedField<Element>::Set(int index, const Element& value) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001072 GOOGLE_DCHECK_GE(index, 0);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001073 GOOGLE_DCHECK_LT(index, current_size_);
1074 rep_->elements[index] = value;
temporal40ee5512008-07-10 02:12:20 +00001075}
1076
1077template <typename Element>
kenton@google.comfccb1462009-12-18 02:11:36 +00001078inline void RepeatedField<Element>::Add(const Element& value) {
temporal40ee5512008-07-10 02:12:20 +00001079 if (current_size_ == total_size_) Reserve(total_size_ + 1);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001080 rep_->elements[current_size_++] = value;
temporal40ee5512008-07-10 02:12:20 +00001081}
1082
1083template <typename Element>
kenton@google.comfccb1462009-12-18 02:11:36 +00001084inline Element* RepeatedField<Element>::Add() {
1085 if (current_size_ == total_size_) Reserve(total_size_ + 1);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001086 return &rep_->elements[current_size_++];
kenton@google.comfccb1462009-12-18 02:11:36 +00001087}
1088
1089template <typename Element>
temporal40ee5512008-07-10 02:12:20 +00001090inline void RepeatedField<Element>::RemoveLast() {
1091 GOOGLE_DCHECK_GT(current_size_, 0);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001092 current_size_--;
temporal40ee5512008-07-10 02:12:20 +00001093}
1094
1095template <typename Element>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001096void RepeatedField<Element>::ExtractSubrange(
1097 int start, int num, Element* elements) {
1098 GOOGLE_DCHECK_GE(start, 0);
1099 GOOGLE_DCHECK_GE(num, 0);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001100 GOOGLE_DCHECK_LE(start + num, this->current_size_);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001101
1102 // Save the values of the removed elements if requested.
1103 if (elements != NULL) {
1104 for (int i = 0; i < num; ++i)
1105 elements[i] = this->Get(i + start);
1106 }
1107
1108 // Slide remaining elements down to fill the gap.
1109 if (num > 0) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001110 for (int i = start + num; i < this->current_size_; ++i)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001111 this->Set(i - num, this->Get(i));
Feng Xiao6ef984a2014-11-10 17:34:54 -08001112 this->Truncate(this->current_size_ - num);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001113 }
1114}
1115
1116template <typename Element>
temporal40ee5512008-07-10 02:12:20 +00001117inline void RepeatedField<Element>::Clear() {
1118 current_size_ = 0;
1119}
1120
1121template <typename Element>
kenton@google.comfccb1462009-12-18 02:11:36 +00001122inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001123 GOOGLE_CHECK_NE(&other, this);
xiaofeng@google.comfcb8a502012-09-24 06:48:20 +00001124 if (other.current_size_ != 0) {
1125 Reserve(current_size_ + other.current_size_);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001126 CopyArray(rep_->elements + current_size_,
1127 other.rep_->elements, other.current_size_);
xiaofeng@google.comfcb8a502012-09-24 06:48:20 +00001128 current_size_ += other.current_size_;
1129 }
temporal40ee5512008-07-10 02:12:20 +00001130}
1131
1132template <typename Element>
liujisi@google.com33165fe2010-11-02 13:14:58 +00001133inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001134 if (&other == this) return;
liujisi@google.com33165fe2010-11-02 13:14:58 +00001135 Clear();
1136 MergeFrom(other);
1137}
1138
1139template <typename Element>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001140inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
1141 const_iterator position) {
1142 return erase(position, position + 1);
1143}
1144
1145template <typename Element>
1146inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
1147 const_iterator first, const_iterator last) {
1148 size_type first_offset = first - cbegin();
Feng Xiao93d68382015-05-31 00:15:55 -07001149 if (first != last) {
1150 Truncate(std::copy(last, cend(), begin() + first_offset) - cbegin());
1151 }
Feng Xiao6ef984a2014-11-10 17:34:54 -08001152 return begin() + first_offset;
1153}
1154
1155template <typename Element>
temporal40ee5512008-07-10 02:12:20 +00001156inline Element* RepeatedField<Element>::mutable_data() {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001157 return rep_ ? rep_->elements : NULL;
temporal40ee5512008-07-10 02:12:20 +00001158}
1159
1160template <typename Element>
1161inline const Element* RepeatedField<Element>::data() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001162 return rep_ ? rep_->elements : NULL;
temporal40ee5512008-07-10 02:12:20 +00001163}
1164
1165
1166template <typename Element>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001167inline void RepeatedField<Element>::InternalSwap(RepeatedField* other) {
1168 std::swap(rep_, other->rep_);
1169 std::swap(current_size_, other->current_size_);
1170 std::swap(total_size_, other->total_size_);
1171}
1172
1173template <typename Element>
temporal40ee5512008-07-10 02:12:20 +00001174void RepeatedField<Element>::Swap(RepeatedField* other) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001175 if (this == other) return;
Feng Xiao6ef984a2014-11-10 17:34:54 -08001176 if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
1177 InternalSwap(other);
1178 } else {
1179 RepeatedField<Element> temp(other->GetArenaNoVirtual());
1180 temp.MergeFrom(*this);
1181 CopyFrom(*other);
1182 other->UnsafeArenaSwap(&temp);
1183 }
1184}
temporal40ee5512008-07-10 02:12:20 +00001185
Feng Xiao6ef984a2014-11-10 17:34:54 -08001186template <typename Element>
1187void RepeatedField<Element>::UnsafeArenaSwap(RepeatedField* other) {
1188 if (this == other) return;
1189 GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
1190 InternalSwap(other);
temporal40ee5512008-07-10 02:12:20 +00001191}
1192
1193template <typename Element>
kenton@google.comceb561d2009-06-25 19:05:36 +00001194void RepeatedField<Element>::SwapElements(int index1, int index2) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001195 using std::swap; // enable ADL with fallback
Feng Xiao6ef984a2014-11-10 17:34:54 -08001196 swap(rep_->elements[index1], rep_->elements[index2]);
kenton@google.comceb561d2009-06-25 19:05:36 +00001197}
1198
1199template <typename Element>
temporal40ee5512008-07-10 02:12:20 +00001200inline typename RepeatedField<Element>::iterator
1201RepeatedField<Element>::begin() {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001202 return rep_ ? rep_->elements : NULL;
temporal40ee5512008-07-10 02:12:20 +00001203}
1204template <typename Element>
1205inline typename RepeatedField<Element>::const_iterator
1206RepeatedField<Element>::begin() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001207 return rep_ ? rep_->elements : NULL;
1208}
1209template <typename Element>
1210inline typename RepeatedField<Element>::const_iterator
1211RepeatedField<Element>::cbegin() const {
1212 return rep_ ? rep_->elements : NULL;
temporal40ee5512008-07-10 02:12:20 +00001213}
1214template <typename Element>
1215inline typename RepeatedField<Element>::iterator
1216RepeatedField<Element>::end() {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001217 return rep_ ? rep_->elements + current_size_ : NULL;
temporal40ee5512008-07-10 02:12:20 +00001218}
1219template <typename Element>
1220inline typename RepeatedField<Element>::const_iterator
1221RepeatedField<Element>::end() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001222 return rep_ ? rep_->elements + current_size_ : NULL;
1223}
1224template <typename Element>
1225inline typename RepeatedField<Element>::const_iterator
1226RepeatedField<Element>::cend() const {
1227 return rep_ ? rep_->elements + current_size_ : NULL;
temporal40ee5512008-07-10 02:12:20 +00001228}
1229
kenton@google.com26bd9ee2008-11-21 00:06:27 +00001230template <typename Element>
1231inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001232 return rep_ ?
1233 (total_size_ * sizeof(Element) + kRepHeaderSize) : 0;
kenton@google.com26bd9ee2008-11-21 00:06:27 +00001234}
temporal40ee5512008-07-10 02:12:20 +00001235
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001236// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant
kenton@google.comfccb1462009-12-18 02:11:36 +00001237// amount of code bloat.
temporal40ee5512008-07-10 02:12:20 +00001238template <typename Element>
kenton@google.comfccb1462009-12-18 02:11:36 +00001239void RepeatedField<Element>::Reserve(int new_size) {
temporal40ee5512008-07-10 02:12:20 +00001240 if (total_size_ >= new_size) return;
Feng Xiao6ef984a2014-11-10 17:34:54 -08001241 Rep* old_rep = rep_;
1242 Arena* arena = GetArenaNoVirtual();
1243 new_size = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
1244 max(total_size_ * 2, new_size));
Jan Tattermusch276ce8c2015-08-26 13:10:05 -07001245 GOOGLE_CHECK_LE(static_cast<size_t>(new_size),
Feng Xiaoeee38b02015-08-22 18:25:48 -07001246 (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
1247 sizeof(Element))
1248 << "Requested size is too large to fit into size_t.";
Feng Xiao6ef984a2014-11-10 17:34:54 -08001249 if (arena == NULL) {
1250 rep_ = reinterpret_cast<Rep*>(
Feng Xiaoeee38b02015-08-22 18:25:48 -07001251 new char[kRepHeaderSize + sizeof(Element) * new_size]);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001252 } else {
1253 rep_ = reinterpret_cast<Rep*>(
1254 ::google::protobuf::Arena::CreateArray<char>(arena,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001255 kRepHeaderSize + sizeof(Element) * new_size));
Feng Xiao6ef984a2014-11-10 17:34:54 -08001256 }
1257 rep_->arena = arena;
Bo Yang5db21732015-05-21 14:28:59 -07001258 int old_total_size = total_size_;
Feng Xiao6ef984a2014-11-10 17:34:54 -08001259 total_size_ = new_size;
1260 // Invoke placement-new on newly allocated elements. We shouldn't have to do
1261 // this, since Element is supposed to be POD, but a previous version of this
1262 // code allocated storage with "new Element[size]" and some code uses
1263 // RepeatedField with non-POD types, relying on constructor invocation. If
1264 // Element has a trivial constructor (e.g., int32), gcc (tested with -O2)
1265 // completely removes this loop because the loop body is empty, so this has no
1266 // effect unless its side-effects are required for correctness.
1267 // Note that we do this before MoveArray() below because Element's copy
1268 // assignment implementation will want an initialized instance first.
1269 Element* e = &rep_->elements[0];
1270 Element* limit = &rep_->elements[total_size_];
1271 for (; e < limit; e++) {
1272 new (e) Element();
1273 }
1274 if (current_size_ > 0) {
1275 MoveArray(rep_->elements, old_rep->elements, current_size_);
1276 }
Bo Yang5db21732015-05-21 14:28:59 -07001277 if (old_rep) {
1278 // Likewise, we need to invoke destructors on the old array. If Element has
1279 // no destructor, this loop will disappear.
1280 e = &old_rep->elements[0];
1281 limit = &old_rep->elements[old_total_size];
1282 for (; e < limit; e++) {
1283 e->Element::~Element();
1284 }
1285 if (arena == NULL) {
1286 delete[] reinterpret_cast<char*>(old_rep);
1287 }
temporal40ee5512008-07-10 02:12:20 +00001288 }
1289}
1290
kenton@google.comfccb1462009-12-18 02:11:36 +00001291template <typename Element>
1292inline void RepeatedField<Element>::Truncate(int new_size) {
1293 GOOGLE_DCHECK_LE(new_size, current_size_);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001294 if (current_size_ > 0) {
1295 current_size_ = new_size;
1296 }
kenton@google.comfccb1462009-12-18 02:11:36 +00001297}
1298
1299template <typename Element>
1300inline void RepeatedField<Element>::MoveArray(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001301 Element* to, Element* from, int array_size) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001302 CopyArray(to, from, array_size);
kenton@google.comfccb1462009-12-18 02:11:36 +00001303}
1304
1305template <typename Element>
1306inline void RepeatedField<Element>::CopyArray(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001307 Element* to, const Element* from, int array_size) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001308 internal::ElementCopier<Element>()(to, from, array_size);
kenton@google.comfccb1462009-12-18 02:11:36 +00001309}
1310
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001311namespace internal {
1312
1313template <typename Element, bool HasTrivialCopy>
1314void ElementCopier<Element, HasTrivialCopy>::operator()(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001315 Element* to, const Element* from, int array_size) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001316 std::copy(from, from + array_size, to);
1317}
1318
1319template <typename Element>
1320struct ElementCopier<Element, true> {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001321 void operator()(Element* to, const Element* from, int array_size) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001322 memcpy(to, from, array_size * sizeof(Element));
1323 }
1324};
1325
1326} // namespace internal
1327
kenton@google.comfccb1462009-12-18 02:11:36 +00001328
temporal40ee5512008-07-10 02:12:20 +00001329// -------------------------------------------------------------------
1330
kenton@google.com80b1d622009-07-29 01:13:20 +00001331namespace internal {
1332
1333inline RepeatedPtrFieldBase::RepeatedPtrFieldBase()
Feng Xiao6ef984a2014-11-10 17:34:54 -08001334 : arena_(NULL),
temporal40ee5512008-07-10 02:12:20 +00001335 current_size_(0),
Feng Xiao6ef984a2014-11-10 17:34:54 -08001336 total_size_(0),
1337 rep_(NULL) {
1338}
1339
1340inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(::google::protobuf::Arena* arena)
1341 : arena_(arena),
1342 current_size_(0),
1343 total_size_(0),
1344 rep_(NULL) {
temporal40ee5512008-07-10 02:12:20 +00001345}
1346
kenton@google.com80b1d622009-07-29 01:13:20 +00001347template <typename TypeHandler>
1348void RepeatedPtrFieldBase::Destroy() {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001349 if (rep_ != NULL) {
1350 for (int i = 0; i < rep_->allocated_size; i++) {
1351 TypeHandler::Delete(cast<TypeHandler>(rep_->elements[i]), arena_);
1352 }
1353 if (arena_ == NULL) {
1354 delete [] reinterpret_cast<char*>(rep_);
1355 }
temporal40ee5512008-07-10 02:12:20 +00001356 }
Feng Xiao6ef984a2014-11-10 17:34:54 -08001357 rep_ = NULL;
1358}
1359
1360template <typename TypeHandler>
1361inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
1362 if (other->GetArenaNoVirtual() == GetArenaNoVirtual()) {
1363 InternalSwap(other);
1364 } else {
1365 SwapFallback<TypeHandler>(other);
1366 }
1367}
1368
1369template <typename TypeHandler>
Feng Xiaoeee38b02015-08-22 18:25:48 -07001370void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001371 GOOGLE_DCHECK(other->GetArenaNoVirtual() != GetArenaNoVirtual());
1372
1373 // Copy semantics in this case. We try to improve efficiency by placing the
1374 // temporary on |other|'s arena so that messages are copied cross-arena only
1375 // once, not twice.
1376 RepeatedPtrFieldBase temp(other->GetArenaNoVirtual());
1377 temp.MergeFrom<TypeHandler>(*this);
1378 this->Clear<TypeHandler>();
1379 this->MergeFrom<TypeHandler>(*other);
1380 other->Clear<TypeHandler>();
1381 other->InternalSwap(&temp);
1382 temp.Destroy<TypeHandler>(); // Frees rep_ if `other` had no arena.
temporal40ee5512008-07-10 02:12:20 +00001383}
1384
jieluo@google.com4de8f552014-07-18 00:47:59 +00001385inline bool RepeatedPtrFieldBase::empty() const {
1386 return current_size_ == 0;
1387}
1388
kenton@google.com80b1d622009-07-29 01:13:20 +00001389inline int RepeatedPtrFieldBase::size() const {
temporal40ee5512008-07-10 02:12:20 +00001390 return current_size_;
1391}
1392
kenton@google.com80b1d622009-07-29 01:13:20 +00001393template <typename TypeHandler>
1394inline const typename TypeHandler::Type&
1395RepeatedPtrFieldBase::Get(int index) const {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001396 GOOGLE_DCHECK_GE(index, 0);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001397 GOOGLE_DCHECK_LT(index, current_size_);
1398 return *cast<TypeHandler>(rep_->elements[index]);
temporal40ee5512008-07-10 02:12:20 +00001399}
1400
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001401
kenton@google.com80b1d622009-07-29 01:13:20 +00001402template <typename TypeHandler>
1403inline typename TypeHandler::Type*
1404RepeatedPtrFieldBase::Mutable(int index) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001405 GOOGLE_DCHECK_GE(index, 0);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001406 GOOGLE_DCHECK_LT(index, current_size_);
1407 return cast<TypeHandler>(rep_->elements[index]);
temporal40ee5512008-07-10 02:12:20 +00001408}
1409
kenton@google.com80b1d622009-07-29 01:13:20 +00001410template <typename TypeHandler>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001411inline void RepeatedPtrFieldBase::Delete(int index) {
1412 GOOGLE_DCHECK_GE(index, 0);
1413 GOOGLE_DCHECK_LT(index, current_size_);
1414 TypeHandler::Delete(cast<TypeHandler>(rep_->elements[index]), arena_);
1415}
1416
1417template <typename TypeHandler>
1418inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add(
1419 typename TypeHandler::Type* prototype) {
1420 if (rep_ != NULL && current_size_ < rep_->allocated_size) {
1421 return cast<TypeHandler>(rep_->elements[current_size_++]);
kenton@google.com80b1d622009-07-29 01:13:20 +00001422 }
Feng Xiao6ef984a2014-11-10 17:34:54 -08001423 if (!rep_ || rep_->allocated_size == total_size_) {
1424 Reserve(total_size_ + 1);
1425 }
1426 ++rep_->allocated_size;
1427 typename TypeHandler::Type* result =
1428 TypeHandler::NewFromPrototype(prototype, arena_);
1429 rep_->elements[current_size_++] = result;
kenton@google.com80b1d622009-07-29 01:13:20 +00001430 return result;
temporal40ee5512008-07-10 02:12:20 +00001431}
1432
kenton@google.com80b1d622009-07-29 01:13:20 +00001433template <typename TypeHandler>
1434inline void RepeatedPtrFieldBase::RemoveLast() {
temporal40ee5512008-07-10 02:12:20 +00001435 GOOGLE_DCHECK_GT(current_size_, 0);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001436 TypeHandler::Clear(cast<TypeHandler>(rep_->elements[--current_size_]));
temporal40ee5512008-07-10 02:12:20 +00001437}
1438
kenton@google.com80b1d622009-07-29 01:13:20 +00001439template <typename TypeHandler>
1440void RepeatedPtrFieldBase::Clear() {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001441 const int n = current_size_;
1442 GOOGLE_DCHECK_GE(n, 0);
1443 if (n > 0) {
Bo Yang5db21732015-05-21 14:28:59 -07001444 void* const* elements = rep_->elements;
Feng Xiao6ef984a2014-11-10 17:34:54 -08001445 int i = 0;
1446 do {
1447 TypeHandler::Clear(cast<TypeHandler>(elements[i++]));
1448 } while (i < n);
1449 current_size_ = 0;
temporal40ee5512008-07-10 02:12:20 +00001450 }
temporal40ee5512008-07-10 02:12:20 +00001451}
1452
Feng Xiao6ef984a2014-11-10 17:34:54 -08001453// To avoid unnecessary code duplication and reduce binary size, we use a
1454// layered approach to implementing MergeFrom(). The toplevel method is
1455// templated, so we get a small thunk per concrete message type in the binary.
1456// This calls a shared implementation with most of the logic, passing a function
1457// pointer to another type-specific piece of code that calls the object-allocate
1458// and merge handlers.
kenton@google.com80b1d622009-07-29 01:13:20 +00001459template <typename TypeHandler>
kenton@google.comfccb1462009-12-18 02:11:36 +00001460inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001461 GOOGLE_DCHECK_NE(&other, this);
1462 if (other.current_size_ == 0) return;
1463 MergeFromInternal(
1464 other, &RepeatedPtrFieldBase::MergeFromInnerLoop<TypeHandler>);
1465}
1466
1467inline void RepeatedPtrFieldBase::MergeFromInternal(
1468 const RepeatedPtrFieldBase& other,
1469 void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int)) {
1470 // Note: wrapper has already guaranteed that other.rep_ != NULL here.
1471 int other_size = other.current_size_;
1472 void** other_elements = other.rep_->elements;
1473 void** new_elements = InternalExtend(other_size);
1474 int allocated_elems = rep_->allocated_size - current_size_;
1475 (this->*inner_loop)(new_elements, other_elements,
1476 other_size, allocated_elems);
1477 current_size_ += other_size;
1478 if (rep_->allocated_size < current_size_) {
1479 rep_->allocated_size = current_size_;
1480 }
1481}
1482
1483// Merges other_elems to our_elems.
1484template<typename TypeHandler>
1485void RepeatedPtrFieldBase::MergeFromInnerLoop(
1486 void** our_elems, void** other_elems, int length, int already_allocated) {
1487 // Split into two loops, over ranges [0, allocated) and [allocated, length),
1488 // to avoid a branch within the loop.
1489 for (int i = 0; i < already_allocated && i < length; i++) {
1490 // Already allocated: use existing element.
1491 typename TypeHandler::Type* other_elem =
1492 reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
1493 typename TypeHandler::Type* new_elem =
1494 reinterpret_cast<typename TypeHandler::Type*>(our_elems[i]);
1495 TypeHandler::Merge(*other_elem, new_elem);
1496 }
1497 Arena* arena = GetArenaNoVirtual();
1498 for (int i = already_allocated; i < length; i++) {
1499 // Not allocated: alloc a new element first, then merge it.
1500 typename TypeHandler::Type* other_elem =
1501 reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
1502 typename TypeHandler::Type* new_elem =
1503 TypeHandler::NewFromPrototype(other_elem, arena);
1504 TypeHandler::Merge(*other_elem, new_elem);
1505 our_elems[i] = new_elem;
temporal40ee5512008-07-10 02:12:20 +00001506 }
1507}
1508
liujisi@google.com33165fe2010-11-02 13:14:58 +00001509template <typename TypeHandler>
1510inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001511 if (&other == this) return;
liujisi@google.com33165fe2010-11-02 13:14:58 +00001512 RepeatedPtrFieldBase::Clear<TypeHandler>();
1513 RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
1514}
1515
kenton@google.comfccb1462009-12-18 02:11:36 +00001516inline int RepeatedPtrFieldBase::Capacity() const {
1517 return total_size_;
1518}
1519
kenton@google.com80b1d622009-07-29 01:13:20 +00001520inline void* const* RepeatedPtrFieldBase::raw_data() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001521 return rep_ ? rep_->elements : NULL;
temporal40ee5512008-07-10 02:12:20 +00001522}
1523
kenton@google.comfccb1462009-12-18 02:11:36 +00001524inline void** RepeatedPtrFieldBase::raw_mutable_data() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001525 return rep_ ? const_cast<void**>(rep_->elements) : NULL;
kenton@google.comfccb1462009-12-18 02:11:36 +00001526}
1527
kenton@google.com80b1d622009-07-29 01:13:20 +00001528template <typename TypeHandler>
1529inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() {
1530 // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
1531 // method entirely.
Feng Xiao6ef984a2014-11-10 17:34:54 -08001532 return reinterpret_cast<typename TypeHandler::Type**>(raw_mutable_data());
temporal40ee5512008-07-10 02:12:20 +00001533}
1534
kenton@google.com80b1d622009-07-29 01:13:20 +00001535template <typename TypeHandler>
1536inline const typename TypeHandler::Type* const*
1537RepeatedPtrFieldBase::data() const {
1538 // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
1539 // method entirely.
Feng Xiao6ef984a2014-11-10 17:34:54 -08001540 return reinterpret_cast<const typename TypeHandler::Type* const*>(raw_data());
temporal40ee5512008-07-10 02:12:20 +00001541}
1542
kenton@google.com80b1d622009-07-29 01:13:20 +00001543inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001544 using std::swap; // enable ADL with fallback
Feng Xiao6ef984a2014-11-10 17:34:54 -08001545 swap(rep_->elements[index1], rep_->elements[index2]);
kenton@google.comceb561d2009-06-25 19:05:36 +00001546}
1547
kenton@google.com80b1d622009-07-29 01:13:20 +00001548template <typename TypeHandler>
1549inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001550 int allocated_bytes = total_size_ * sizeof(void*);
1551 if (rep_ != NULL) {
1552 for (int i = 0; i < rep_->allocated_size; ++i) {
1553 allocated_bytes += TypeHandler::SpaceUsed(
1554 *cast<TypeHandler>(rep_->elements[i]));
1555 }
1556 allocated_bytes += kRepHeaderSize;
kenton@google.com26bd9ee2008-11-21 00:06:27 +00001557 }
1558 return allocated_bytes;
1559}
1560
kenton@google.com80b1d622009-07-29 01:13:20 +00001561template <typename TypeHandler>
1562inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001563 if (rep_ != NULL && current_size_ < rep_->allocated_size) {
1564 return cast<TypeHandler>(rep_->elements[current_size_++]);
kenton@google.com80b1d622009-07-29 01:13:20 +00001565 } else {
1566 return NULL;
1567 }
kenton@google.com26bd9ee2008-11-21 00:06:27 +00001568}
1569
Feng Xiao6ef984a2014-11-10 17:34:54 -08001570// AddAllocated version that implements arena-safe copying behavior.
kenton@google.com80b1d622009-07-29 01:13:20 +00001571template <typename TypeHandler>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001572void RepeatedPtrFieldBase::AddAllocatedInternal(
1573 typename TypeHandler::Type* value,
1574 google::protobuf::internal::true_type) {
1575 Arena* element_arena = reinterpret_cast<Arena*>(
1576 TypeHandler::GetMaybeArenaPointer(value));
1577 Arena* arena = GetArenaNoVirtual();
1578 if (arena == element_arena && rep_ &&
1579 rep_->allocated_size < total_size_) {
1580 // Fast path: underlying arena representation (tagged pointer) is equal to
1581 // our arena pointer, and we can add to array without resizing it (at least
1582 // one slot that is not allocated).
1583 void** elems = rep_->elements;
1584 if (current_size_ < rep_->allocated_size) {
1585 // Make space at [current] by moving first allocated element to end of
1586 // allocated list.
1587 elems[rep_->allocated_size] = elems[current_size_];
1588 }
1589 elems[current_size_] = value;
1590 current_size_ = current_size_ + 1;
1591 rep_->allocated_size = rep_->allocated_size + 1;
1592 return;
1593 } else {
1594 AddAllocatedSlowWithCopy<TypeHandler>(
1595 value, TypeHandler::GetArena(value), arena);
1596 }
1597}
1598
1599// Slowpath handles all cases, copying if necessary.
1600template<typename TypeHandler>
1601void RepeatedPtrFieldBase::AddAllocatedSlowWithCopy(
1602 // Pass value_arena and my_arena to avoid duplicate virtual call (value) or
1603 // load (mine).
1604 typename TypeHandler::Type* value, Arena* value_arena, Arena* my_arena) {
1605 // Ensure that either the value is in the same arena, or if not, we do the
1606 // appropriate thing: Own() it (if it's on heap and we're in an arena) or copy
1607 // it to our arena/heap (otherwise).
1608 if (my_arena != NULL && value_arena == NULL) {
1609 my_arena->Own(value);
1610 } else if (my_arena != value_arena) {
1611 typename TypeHandler::Type* new_value =
1612 TypeHandler::NewFromPrototype(value, my_arena);
1613 TypeHandler::Merge(*value, new_value);
1614 TypeHandler::Delete(value, value_arena);
1615 value = new_value;
1616 }
1617
1618 UnsafeArenaAddAllocated<TypeHandler>(value);
1619}
1620
1621// AddAllocated version that does not implement arena-safe copying behavior.
1622template <typename TypeHandler>
1623void RepeatedPtrFieldBase::AddAllocatedInternal(
1624 typename TypeHandler::Type* value,
1625 google::protobuf::internal::false_type) {
1626 if (rep_ && rep_->allocated_size < total_size_) {
1627 // Fast path: underlying arena representation (tagged pointer) is equal to
1628 // our arena pointer, and we can add to array without resizing it (at least
1629 // one slot that is not allocated).
1630 void** elems = rep_->elements;
1631 if (current_size_ < rep_->allocated_size) {
1632 // Make space at [current] by moving first allocated element to end of
1633 // allocated list.
1634 elems[rep_->allocated_size] = elems[current_size_];
1635 }
1636 elems[current_size_] = value;
1637 current_size_ = current_size_ + 1;
1638 ++rep_->allocated_size;
1639 return;
1640 } else {
1641 UnsafeArenaAddAllocated<TypeHandler>(value);
1642 }
1643}
1644
1645template <typename TypeHandler>
1646void RepeatedPtrFieldBase::UnsafeArenaAddAllocated(
kenton@google.com80b1d622009-07-29 01:13:20 +00001647 typename TypeHandler::Type* value) {
kenton@google.comfccb1462009-12-18 02:11:36 +00001648 // Make room for the new pointer.
Feng Xiao6ef984a2014-11-10 17:34:54 -08001649 if (!rep_ || current_size_ == total_size_) {
kenton@google.comfccb1462009-12-18 02:11:36 +00001650 // The array is completely full with no cleared objects, so grow it.
1651 Reserve(total_size_ + 1);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001652 ++rep_->allocated_size;
1653 } else if (rep_->allocated_size == total_size_) {
kenton@google.comfccb1462009-12-18 02:11:36 +00001654 // There is no more space in the pointer array because it contains some
1655 // cleared objects awaiting reuse. We don't want to grow the array in this
1656 // case because otherwise a loop calling AddAllocated() followed by Clear()
1657 // would leak memory.
Feng Xiao6ef984a2014-11-10 17:34:54 -08001658 TypeHandler::Delete(
1659 cast<TypeHandler>(rep_->elements[current_size_]), arena_);
1660 } else if (current_size_ < rep_->allocated_size) {
kenton@google.comfccb1462009-12-18 02:11:36 +00001661 // We have some cleared objects. We don't care about their order, so we
1662 // can just move the first one to the end to make space.
Feng Xiao6ef984a2014-11-10 17:34:54 -08001663 rep_->elements[rep_->allocated_size] = rep_->elements[current_size_];
1664 ++rep_->allocated_size;
kenton@google.comfccb1462009-12-18 02:11:36 +00001665 } else {
1666 // There are no cleared objects.
Feng Xiao6ef984a2014-11-10 17:34:54 -08001667 ++rep_->allocated_size;
temporal40ee5512008-07-10 02:12:20 +00001668 }
kenton@google.comfccb1462009-12-18 02:11:36 +00001669
Feng Xiao6ef984a2014-11-10 17:34:54 -08001670 rep_->elements[current_size_++] = value;
1671}
1672
1673// ReleaseLast() for types that implement merge/copy behavior.
1674template <typename TypeHandler>
1675inline typename TypeHandler::Type*
1676RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::true_type) {
1677 // First, release an element.
1678 typename TypeHandler::Type* result = UnsafeArenaReleaseLast<TypeHandler>();
1679 // Now perform a copy if we're on an arena.
1680 Arena* arena = GetArenaNoVirtual();
1681 if (arena == NULL) {
1682 return result;
1683 } else {
1684 typename TypeHandler::Type* new_result =
1685 TypeHandler::NewFromPrototype(result, NULL);
1686 TypeHandler::Merge(*result, new_result);
1687 return new_result;
1688 }
1689}
1690
1691// ReleaseLast() for types that *do not* implement merge/copy behavior -- this
1692// is the same as UnsafeArenaReleaseLast(). Note that we GOOGLE_DCHECK-fail if we're on
1693// an arena, since the user really should implement the copy operation in this
1694// case.
1695template <typename TypeHandler>
1696inline typename TypeHandler::Type*
1697RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::false_type) {
1698 GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
1699 << "ReleaseLast() called on a RepeatedPtrField that is on an arena, "
1700 << "with a type that does not implement MergeFrom. This is unsafe; "
1701 << "please implement MergeFrom for your type.";
1702 return UnsafeArenaReleaseLast<TypeHandler>();
temporal40ee5512008-07-10 02:12:20 +00001703}
1704
kenton@google.com80b1d622009-07-29 01:13:20 +00001705template <typename TypeHandler>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001706inline typename TypeHandler::Type*
1707 RepeatedPtrFieldBase::UnsafeArenaReleaseLast() {
temporal40ee5512008-07-10 02:12:20 +00001708 GOOGLE_DCHECK_GT(current_size_, 0);
kenton@google.com80b1d622009-07-29 01:13:20 +00001709 typename TypeHandler::Type* result =
Feng Xiao6ef984a2014-11-10 17:34:54 -08001710 cast<TypeHandler>(rep_->elements[--current_size_]);
1711 --rep_->allocated_size;
1712 if (current_size_ < rep_->allocated_size) {
temporal40ee5512008-07-10 02:12:20 +00001713 // There are cleared elements on the end; replace the removed element
1714 // with the last allocated element.
Feng Xiao6ef984a2014-11-10 17:34:54 -08001715 rep_->elements[current_size_] = rep_->elements[rep_->allocated_size];
temporal40ee5512008-07-10 02:12:20 +00001716 }
1717 return result;
1718}
1719
kenton@google.comfccb1462009-12-18 02:11:36 +00001720inline int RepeatedPtrFieldBase::ClearedCount() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001721 return rep_ ? (rep_->allocated_size - current_size_) : 0;
temporal40ee5512008-07-10 02:12:20 +00001722}
1723
kenton@google.com80b1d622009-07-29 01:13:20 +00001724template <typename TypeHandler>
1725inline void RepeatedPtrFieldBase::AddCleared(
1726 typename TypeHandler::Type* value) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001727 GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
1728 << "AddCleared() can only be used on a RepeatedPtrField not on an arena.";
1729 GOOGLE_DCHECK(TypeHandler::GetArena(value) == NULL)
1730 << "AddCleared() can only accept values not on an arena.";
1731 if (!rep_ || rep_->allocated_size == total_size_) {
1732 Reserve(total_size_ + 1);
1733 }
1734 rep_->elements[rep_->allocated_size++] = value;
temporal40ee5512008-07-10 02:12:20 +00001735}
1736
kenton@google.com80b1d622009-07-29 01:13:20 +00001737template <typename TypeHandler>
1738inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001739 GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
1740 << "ReleaseCleared() can only be used on a RepeatedPtrField not on "
1741 << "an arena.";
1742 GOOGLE_DCHECK(GetArenaNoVirtual() == NULL);
1743 GOOGLE_DCHECK(rep_ != NULL);
1744 GOOGLE_DCHECK_GT(rep_->allocated_size, current_size_);
1745 return cast<TypeHandler>(rep_->elements[--rep_->allocated_size]);
temporal40ee5512008-07-10 02:12:20 +00001746}
1747
kenton@google.com80b1d622009-07-29 01:13:20 +00001748} // namespace internal
1749
1750// -------------------------------------------------------------------
1751
temporal40ee5512008-07-10 02:12:20 +00001752template <typename Element>
kenton@google.com80b1d622009-07-29 01:13:20 +00001753class RepeatedPtrField<Element>::TypeHandler
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001754 : public internal::GenericTypeHandler<Element> {
1755};
kenton@google.com80b1d622009-07-29 01:13:20 +00001756
1757template <>
1758class RepeatedPtrField<string>::TypeHandler
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001759 : public internal::StringTypeHandler {
1760};
kenton@google.com80b1d622009-07-29 01:13:20 +00001761
1762
1763template <typename Element>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001764inline RepeatedPtrField<Element>::RepeatedPtrField()
1765 : RepeatedPtrFieldBase() {}
1766
1767template <typename Element>
1768inline RepeatedPtrField<Element>::RepeatedPtrField(::google::protobuf::Arena* arena) :
1769 RepeatedPtrFieldBase(arena) {}
temporal40ee5512008-07-10 02:12:20 +00001770
kenton@google.com80b1d622009-07-29 01:13:20 +00001771template <typename Element>
liujisi@google.com33165fe2010-11-02 13:14:58 +00001772inline RepeatedPtrField<Element>::RepeatedPtrField(
jieluo@google.com4de8f552014-07-18 00:47:59 +00001773 const RepeatedPtrField& other)
Feng Xiao6ef984a2014-11-10 17:34:54 -08001774 : RepeatedPtrFieldBase() {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001775 CopyFrom(other);
1776}
1777
1778template <typename Element>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001779template <typename Iter>
1780inline RepeatedPtrField<Element>::RepeatedPtrField(
1781 Iter begin, const Iter& end) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001782 int reserve = internal::CalculateReserve(begin, end);
1783 if (reserve != -1) {
1784 Reserve(reserve);
1785 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001786 for (; begin != end; ++begin) {
1787 *Add() = *begin;
1788 }
1789}
1790
1791template <typename Element>
kenton@google.com80b1d622009-07-29 01:13:20 +00001792RepeatedPtrField<Element>::~RepeatedPtrField() {
1793 Destroy<TypeHandler>();
1794}
1795
1796template <typename Element>
liujisi@google.com33165fe2010-11-02 13:14:58 +00001797inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
1798 const RepeatedPtrField& other) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001799 if (this != &other)
1800 CopyFrom(other);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001801 return *this;
1802}
1803
1804template <typename Element>
jieluo@google.com4de8f552014-07-18 00:47:59 +00001805inline bool RepeatedPtrField<Element>::empty() const {
1806 return RepeatedPtrFieldBase::empty();
1807}
1808
1809template <typename Element>
kenton@google.com80b1d622009-07-29 01:13:20 +00001810inline int RepeatedPtrField<Element>::size() const {
1811 return RepeatedPtrFieldBase::size();
1812}
1813
1814template <typename Element>
1815inline const Element& RepeatedPtrField<Element>::Get(int index) const {
1816 return RepeatedPtrFieldBase::Get<TypeHandler>(index);
1817}
1818
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001819
kenton@google.com80b1d622009-07-29 01:13:20 +00001820template <typename Element>
1821inline Element* RepeatedPtrField<Element>::Mutable(int index) {
1822 return RepeatedPtrFieldBase::Mutable<TypeHandler>(index);
1823}
1824
1825template <typename Element>
1826inline Element* RepeatedPtrField<Element>::Add() {
1827 return RepeatedPtrFieldBase::Add<TypeHandler>();
1828}
1829
1830template <typename Element>
1831inline void RepeatedPtrField<Element>::RemoveLast() {
1832 RepeatedPtrFieldBase::RemoveLast<TypeHandler>();
1833}
1834
1835template <typename Element>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001836inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) {
1837 GOOGLE_DCHECK_GE(start, 0);
1838 GOOGLE_DCHECK_GE(num, 0);
1839 GOOGLE_DCHECK_LE(start + num, size());
Feng Xiao6ef984a2014-11-10 17:34:54 -08001840 for (int i = 0; i < num; ++i) {
1841 RepeatedPtrFieldBase::Delete<TypeHandler>(start + i);
1842 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001843 ExtractSubrange(start, num, NULL);
1844}
1845
1846template <typename Element>
1847inline void RepeatedPtrField<Element>::ExtractSubrange(
1848 int start, int num, Element** elements) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001849 typename internal::TypeImplementsMergeBehavior<
1850 typename TypeHandler::Type>::type t;
1851 ExtractSubrangeInternal(start, num, elements, t);
1852}
1853
1854// ExtractSubrange() implementation for types that implement merge/copy
1855// behavior.
1856template <typename Element>
1857inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
1858 int start, int num, Element** elements, google::protobuf::internal::true_type) {
1859 GOOGLE_DCHECK_GE(start, 0);
1860 GOOGLE_DCHECK_GE(num, 0);
1861 GOOGLE_DCHECK_LE(start + num, size());
1862
1863 if (num > 0) {
1864 // Save the values of the removed elements if requested.
1865 if (elements != NULL) {
1866 if (GetArenaNoVirtual() != NULL) {
1867 // If we're on an arena, we perform a copy for each element so that the
1868 // returned elements are heap-allocated.
1869 for (int i = 0; i < num; ++i) {
1870 Element* element = RepeatedPtrFieldBase::
1871 Mutable<TypeHandler>(i + start);
1872 typename TypeHandler::Type* new_value =
1873 TypeHandler::NewFromPrototype(element, NULL);
1874 TypeHandler::Merge(*element, new_value);
1875 elements[i] = new_value;
1876 }
1877 } else {
1878 for (int i = 0; i < num; ++i) {
1879 elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
1880 }
1881 }
1882 }
1883 CloseGap(start, num);
1884 }
1885}
1886
1887// ExtractSubrange() implementation for types that do not implement merge/copy
1888// behavior.
1889template<typename Element>
1890inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
1891 int start, int num, Element** elements, google::protobuf::internal::false_type) {
1892 // This case is identical to UnsafeArenaExtractSubrange(). However, since
1893 // ExtractSubrange() must return heap-allocated objects by contract, and we
1894 // cannot fulfill this contract if we are an on arena, we must GOOGLE_DCHECK() that
1895 // we are not on an arena.
1896 GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
1897 << "ExtractSubrange() when arena is non-NULL is only supported when "
1898 << "the Element type supplies a MergeFrom() operation to make copies.";
1899 UnsafeArenaExtractSubrange(start, num, elements);
1900}
1901
1902template <typename Element>
1903inline void RepeatedPtrField<Element>::UnsafeArenaExtractSubrange(
1904 int start, int num, Element** elements) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001905 GOOGLE_DCHECK_GE(start, 0);
1906 GOOGLE_DCHECK_GE(num, 0);
1907 GOOGLE_DCHECK_LE(start + num, size());
1908
1909 if (num > 0) {
1910 // Save the values of the removed elements if requested.
1911 if (elements != NULL) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001912 for (int i = 0; i < num; ++i) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001913 elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001914 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001915 }
1916 CloseGap(start, num);
1917 }
1918}
1919
1920template <typename Element>
kenton@google.com80b1d622009-07-29 01:13:20 +00001921inline void RepeatedPtrField<Element>::Clear() {
1922 RepeatedPtrFieldBase::Clear<TypeHandler>();
1923}
1924
1925template <typename Element>
1926inline void RepeatedPtrField<Element>::MergeFrom(
1927 const RepeatedPtrField& other) {
1928 RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
1929}
1930
1931template <typename Element>
liujisi@google.com33165fe2010-11-02 13:14:58 +00001932inline void RepeatedPtrField<Element>::CopyFrom(
1933 const RepeatedPtrField& other) {
1934 RepeatedPtrFieldBase::CopyFrom<TypeHandler>(other);
1935}
1936
1937template <typename Element>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001938inline typename RepeatedPtrField<Element>::iterator
1939RepeatedPtrField<Element>::erase(const_iterator position) {
1940 return erase(position, position + 1);
1941}
1942
1943template <typename Element>
1944inline typename RepeatedPtrField<Element>::iterator
1945RepeatedPtrField<Element>::erase(const_iterator first, const_iterator last) {
1946 size_type pos_offset = std::distance(cbegin(), first);
1947 size_type last_offset = std::distance(cbegin(), last);
1948 DeleteSubrange(pos_offset, last_offset - pos_offset);
1949 return begin() + pos_offset;
1950}
1951
1952template <typename Element>
kenton@google.com80b1d622009-07-29 01:13:20 +00001953inline Element** RepeatedPtrField<Element>::mutable_data() {
1954 return RepeatedPtrFieldBase::mutable_data<TypeHandler>();
1955}
1956
1957template <typename Element>
1958inline const Element* const* RepeatedPtrField<Element>::data() const {
1959 return RepeatedPtrFieldBase::data<TypeHandler>();
1960}
1961
1962template <typename Element>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001963inline void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
1964 if (this == other)
1965 return;
1966 RepeatedPtrFieldBase::Swap<TypeHandler>(other);
kenton@google.com80b1d622009-07-29 01:13:20 +00001967}
1968
1969template <typename Element>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001970inline void RepeatedPtrField<Element>::UnsafeArenaSwap(
1971 RepeatedPtrField* other) {
1972 GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
1973 if (this == other)
1974 return;
1975 RepeatedPtrFieldBase::InternalSwap(other);
1976}
1977
1978template <typename Element>
1979inline void RepeatedPtrField<Element>::SwapElements(int index1, int index2) {
kenton@google.com80b1d622009-07-29 01:13:20 +00001980 RepeatedPtrFieldBase::SwapElements(index1, index2);
1981}
1982
1983template <typename Element>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001984inline Arena* RepeatedPtrField<Element>::GetArenaNoVirtual() const {
1985 return RepeatedPtrFieldBase::GetArenaNoVirtual();
1986}
1987
1988template <typename Element>
kenton@google.com80b1d622009-07-29 01:13:20 +00001989inline int RepeatedPtrField<Element>::SpaceUsedExcludingSelf() const {
1990 return RepeatedPtrFieldBase::SpaceUsedExcludingSelf<TypeHandler>();
1991}
1992
1993template <typename Element>
1994inline void RepeatedPtrField<Element>::AddAllocated(Element* value) {
1995 RepeatedPtrFieldBase::AddAllocated<TypeHandler>(value);
1996}
1997
1998template <typename Element>
Feng Xiao6ef984a2014-11-10 17:34:54 -08001999inline void RepeatedPtrField<Element>::UnsafeArenaAddAllocated(Element* value) {
2000 RepeatedPtrFieldBase::UnsafeArenaAddAllocated<TypeHandler>(value);
2001}
2002
2003template <typename Element>
kenton@google.com80b1d622009-07-29 01:13:20 +00002004inline Element* RepeatedPtrField<Element>::ReleaseLast() {
2005 return RepeatedPtrFieldBase::ReleaseLast<TypeHandler>();
2006}
2007
Feng Xiao6ef984a2014-11-10 17:34:54 -08002008template <typename Element>
2009inline Element* RepeatedPtrField<Element>::UnsafeArenaReleaseLast() {
2010 return RepeatedPtrFieldBase::UnsafeArenaReleaseLast<TypeHandler>();
2011}
kenton@google.com80b1d622009-07-29 01:13:20 +00002012
2013template <typename Element>
kenton@google.comfccb1462009-12-18 02:11:36 +00002014inline int RepeatedPtrField<Element>::ClearedCount() const {
kenton@google.com80b1d622009-07-29 01:13:20 +00002015 return RepeatedPtrFieldBase::ClearedCount();
2016}
2017
2018template <typename Element>
2019inline void RepeatedPtrField<Element>::AddCleared(Element* value) {
2020 return RepeatedPtrFieldBase::AddCleared<TypeHandler>(value);
2021}
2022
2023template <typename Element>
2024inline Element* RepeatedPtrField<Element>::ReleaseCleared() {
2025 return RepeatedPtrFieldBase::ReleaseCleared<TypeHandler>();
2026}
2027
2028template <typename Element>
2029inline void RepeatedPtrField<Element>::Reserve(int new_size) {
2030 return RepeatedPtrFieldBase::Reserve(new_size);
temporal40ee5512008-07-10 02:12:20 +00002031}
2032
kenton@google.comfccb1462009-12-18 02:11:36 +00002033template <typename Element>
2034inline int RepeatedPtrField<Element>::Capacity() const {
2035 return RepeatedPtrFieldBase::Capacity();
2036}
2037
temporal40ee5512008-07-10 02:12:20 +00002038// -------------------------------------------------------------------
2039
2040namespace internal {
2041
2042// STL-like iterator implementation for RepeatedPtrField. You should not
2043// refer to this class directly; use RepeatedPtrField<T>::iterator instead.
2044//
kenton@google.com80b1d622009-07-29 01:13:20 +00002045// The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002046// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors.h,
kenton@google.com80b1d622009-07-29 01:13:20 +00002047// but adds random-access operators and is modified to wrap a void** base
2048// iterator (since RepeatedPtrField stores its array as a void* array and
2049// casting void** to T** would violate C++ aliasing rules).
temporal40ee5512008-07-10 02:12:20 +00002050//
kenton@google.com80b1d622009-07-29 01:13:20 +00002051// This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin
temporal40ee5512008-07-10 02:12:20 +00002052// (jyasskin@google.com).
kenton@google.com80b1d622009-07-29 01:13:20 +00002053template<typename Element>
temporal40ee5512008-07-10 02:12:20 +00002054class RepeatedPtrIterator
2055 : public std::iterator<
kenton@google.com80b1d622009-07-29 01:13:20 +00002056 std::random_access_iterator_tag, Element> {
temporal40ee5512008-07-10 02:12:20 +00002057 public:
kenton@google.com80b1d622009-07-29 01:13:20 +00002058 typedef RepeatedPtrIterator<Element> iterator;
kenton@google.coma2a32c22008-11-14 17:29:32 +00002059 typedef std::iterator<
kenton@google.com80b1d622009-07-29 01:13:20 +00002060 std::random_access_iterator_tag, Element> superclass;
kenton@google.coma2a32c22008-11-14 17:29:32 +00002061
jieluo@google.com4de8f552014-07-18 00:47:59 +00002062 // Shadow the value_type in std::iterator<> because const_iterator::value_type
2063 // needs to be T, not const T.
2064 typedef typename remove_const<Element>::type value_type;
2065
kenton@google.coma2a32c22008-11-14 17:29:32 +00002066 // Let the compiler know that these are type names, so we don't have to
2067 // write "typename" in front of them everywhere.
2068 typedef typename superclass::reference reference;
2069 typedef typename superclass::pointer pointer;
2070 typedef typename superclass::difference_type difference_type;
temporal40ee5512008-07-10 02:12:20 +00002071
2072 RepeatedPtrIterator() : it_(NULL) {}
kenton@google.com80b1d622009-07-29 01:13:20 +00002073 explicit RepeatedPtrIterator(void* const* it) : it_(it) {}
temporal40ee5512008-07-10 02:12:20 +00002074
2075 // Allow "upcasting" from RepeatedPtrIterator<T**> to
2076 // RepeatedPtrIterator<const T*const*>.
kenton@google.com80b1d622009-07-29 01:13:20 +00002077 template<typename OtherElement>
2078 RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement>& other)
2079 : it_(other.it_) {
liujisi@google.com33165fe2010-11-02 13:14:58 +00002080 // Force a compiler error if the other type is not convertible to ours.
kenton@google.com80b1d622009-07-29 01:13:20 +00002081 if (false) {
2082 implicit_cast<Element*, OtherElement*>(0);
2083 }
2084 }
temporal40ee5512008-07-10 02:12:20 +00002085
2086 // dereferenceable
kenton@google.com80b1d622009-07-29 01:13:20 +00002087 reference operator*() const { return *reinterpret_cast<Element*>(*it_); }
temporal40ee5512008-07-10 02:12:20 +00002088 pointer operator->() const { return &(operator*()); }
2089
2090 // {inc,dec}rementable
2091 iterator& operator++() { ++it_; return *this; }
2092 iterator operator++(int) { return iterator(it_++); }
2093 iterator& operator--() { --it_; return *this; }
2094 iterator operator--(int) { return iterator(it_--); }
2095
2096 // equality_comparable
2097 bool operator==(const iterator& x) const { return it_ == x.it_; }
2098 bool operator!=(const iterator& x) const { return it_ != x.it_; }
2099
2100 // less_than_comparable
2101 bool operator<(const iterator& x) const { return it_ < x.it_; }
2102 bool operator<=(const iterator& x) const { return it_ <= x.it_; }
2103 bool operator>(const iterator& x) const { return it_ > x.it_; }
2104 bool operator>=(const iterator& x) const { return it_ >= x.it_; }
2105
2106 // addable, subtractable
2107 iterator& operator+=(difference_type d) {
2108 it_ += d;
2109 return *this;
2110 }
Andrew Paprockiaf88ccb2014-10-31 16:44:04 -04002111 friend iterator operator+(iterator it, const difference_type d) {
temporal40ee5512008-07-10 02:12:20 +00002112 it += d;
2113 return it;
2114 }
Andrew Paprockiaf88ccb2014-10-31 16:44:04 -04002115 friend iterator operator+(const difference_type d, iterator it) {
temporal40ee5512008-07-10 02:12:20 +00002116 it += d;
2117 return it;
2118 }
2119 iterator& operator-=(difference_type d) {
2120 it_ -= d;
2121 return *this;
2122 }
2123 friend iterator operator-(iterator it, difference_type d) {
2124 it -= d;
2125 return it;
2126 }
2127
2128 // indexable
2129 reference operator[](difference_type d) const { return *(*this + d); }
2130
2131 // random access iterator
2132 difference_type operator-(const iterator& x) const { return it_ - x.it_; }
2133
2134 private:
kenton@google.com80b1d622009-07-29 01:13:20 +00002135 template<typename OtherElement>
2136 friend class RepeatedPtrIterator;
2137
temporal40ee5512008-07-10 02:12:20 +00002138 // The internal iterator.
kenton@google.com80b1d622009-07-29 01:13:20 +00002139 void* const* it_;
temporal40ee5512008-07-10 02:12:20 +00002140};
2141
kenton@google.comfccb1462009-12-18 02:11:36 +00002142// Provide an iterator that operates on pointers to the underlying objects
2143// rather than the objects themselves as RepeatedPtrIterator does.
2144// Consider using this when working with stl algorithms that change
2145// the array.
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002146// The VoidPtr template parameter holds the type-agnostic pointer value
2147// referenced by the iterator. It should either be "void *" for a mutable
2148// iterator, or "const void *" for a constant iterator.
2149template<typename Element, typename VoidPtr>
kenton@google.comfccb1462009-12-18 02:11:36 +00002150class RepeatedPtrOverPtrsIterator
2151 : public std::iterator<std::random_access_iterator_tag, Element*> {
2152 public:
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002153 typedef RepeatedPtrOverPtrsIterator<Element, VoidPtr> iterator;
kenton@google.comfccb1462009-12-18 02:11:36 +00002154 typedef std::iterator<
2155 std::random_access_iterator_tag, Element*> superclass;
2156
jieluo@google.com4de8f552014-07-18 00:47:59 +00002157 // Shadow the value_type in std::iterator<> because const_iterator::value_type
2158 // needs to be T, not const T.
2159 typedef typename remove_const<Element*>::type value_type;
2160
kenton@google.comfccb1462009-12-18 02:11:36 +00002161 // Let the compiler know that these are type names, so we don't have to
2162 // write "typename" in front of them everywhere.
2163 typedef typename superclass::reference reference;
2164 typedef typename superclass::pointer pointer;
2165 typedef typename superclass::difference_type difference_type;
2166
2167 RepeatedPtrOverPtrsIterator() : it_(NULL) {}
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002168 explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {}
kenton@google.comfccb1462009-12-18 02:11:36 +00002169
2170 // dereferenceable
2171 reference operator*() const { return *reinterpret_cast<Element**>(it_); }
2172 pointer operator->() const { return &(operator*()); }
2173
2174 // {inc,dec}rementable
2175 iterator& operator++() { ++it_; return *this; }
2176 iterator operator++(int) { return iterator(it_++); }
2177 iterator& operator--() { --it_; return *this; }
2178 iterator operator--(int) { return iterator(it_--); }
2179
2180 // equality_comparable
2181 bool operator==(const iterator& x) const { return it_ == x.it_; }
2182 bool operator!=(const iterator& x) const { return it_ != x.it_; }
2183
2184 // less_than_comparable
2185 bool operator<(const iterator& x) const { return it_ < x.it_; }
2186 bool operator<=(const iterator& x) const { return it_ <= x.it_; }
2187 bool operator>(const iterator& x) const { return it_ > x.it_; }
2188 bool operator>=(const iterator& x) const { return it_ >= x.it_; }
2189
2190 // addable, subtractable
2191 iterator& operator+=(difference_type d) {
2192 it_ += d;
2193 return *this;
2194 }
2195 friend iterator operator+(iterator it, difference_type d) {
2196 it += d;
2197 return it;
2198 }
2199 friend iterator operator+(difference_type d, iterator it) {
2200 it += d;
2201 return it;
2202 }
2203 iterator& operator-=(difference_type d) {
2204 it_ -= d;
2205 return *this;
2206 }
2207 friend iterator operator-(iterator it, difference_type d) {
2208 it -= d;
2209 return it;
2210 }
2211
2212 // indexable
2213 reference operator[](difference_type d) const { return *(*this + d); }
2214
2215 // random access iterator
2216 difference_type operator-(const iterator& x) const { return it_ - x.it_; }
2217
2218 private:
2219 template<typename OtherElement>
2220 friend class RepeatedPtrIterator;
2221
2222 // The internal iterator.
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002223 VoidPtr* it_;
kenton@google.comfccb1462009-12-18 02:11:36 +00002224};
2225
Feng Xiao6ef984a2014-11-10 17:34:54 -08002226void RepeatedPtrFieldBase::InternalSwap(RepeatedPtrFieldBase* other) {
2227 std::swap(rep_, other->rep_);
2228 std::swap(current_size_, other->current_size_);
2229 std::swap(total_size_, other->total_size_);
2230}
2231
temporal40ee5512008-07-10 02:12:20 +00002232} // namespace internal
2233
2234template <typename Element>
2235inline typename RepeatedPtrField<Element>::iterator
2236RepeatedPtrField<Element>::begin() {
kenton@google.com80b1d622009-07-29 01:13:20 +00002237 return iterator(raw_data());
temporal40ee5512008-07-10 02:12:20 +00002238}
2239template <typename Element>
2240inline typename RepeatedPtrField<Element>::const_iterator
2241RepeatedPtrField<Element>::begin() const {
kenton@google.com80b1d622009-07-29 01:13:20 +00002242 return iterator(raw_data());
temporal40ee5512008-07-10 02:12:20 +00002243}
2244template <typename Element>
Feng Xiao6ef984a2014-11-10 17:34:54 -08002245inline typename RepeatedPtrField<Element>::const_iterator
2246RepeatedPtrField<Element>::cbegin() const {
2247 return begin();
2248}
2249template <typename Element>
temporal40ee5512008-07-10 02:12:20 +00002250inline typename RepeatedPtrField<Element>::iterator
2251RepeatedPtrField<Element>::end() {
kenton@google.com80b1d622009-07-29 01:13:20 +00002252 return iterator(raw_data() + size());
temporal40ee5512008-07-10 02:12:20 +00002253}
2254template <typename Element>
2255inline typename RepeatedPtrField<Element>::const_iterator
2256RepeatedPtrField<Element>::end() const {
kenton@google.com80b1d622009-07-29 01:13:20 +00002257 return iterator(raw_data() + size());
temporal40ee5512008-07-10 02:12:20 +00002258}
Feng Xiao6ef984a2014-11-10 17:34:54 -08002259template <typename Element>
2260inline typename RepeatedPtrField<Element>::const_iterator
2261RepeatedPtrField<Element>::cend() const {
2262 return end();
2263}
temporal40ee5512008-07-10 02:12:20 +00002264
kenton@google.comfccb1462009-12-18 02:11:36 +00002265template <typename Element>
2266inline typename RepeatedPtrField<Element>::pointer_iterator
2267RepeatedPtrField<Element>::pointer_begin() {
2268 return pointer_iterator(raw_mutable_data());
2269}
2270template <typename Element>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002271inline typename RepeatedPtrField<Element>::const_pointer_iterator
2272RepeatedPtrField<Element>::pointer_begin() const {
2273 return const_pointer_iterator(const_cast<const void**>(raw_mutable_data()));
2274}
2275template <typename Element>
kenton@google.comfccb1462009-12-18 02:11:36 +00002276inline typename RepeatedPtrField<Element>::pointer_iterator
2277RepeatedPtrField<Element>::pointer_end() {
2278 return pointer_iterator(raw_mutable_data() + size());
2279}
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002280template <typename Element>
2281inline typename RepeatedPtrField<Element>::const_pointer_iterator
2282RepeatedPtrField<Element>::pointer_end() const {
2283 return const_pointer_iterator(
2284 const_cast<const void**>(raw_mutable_data() + size()));
2285}
kenton@google.comfccb1462009-12-18 02:11:36 +00002286
2287
kenton@google.comd37d46d2009-04-25 02:53:47 +00002288// Iterators and helper functions that follow the spirit of the STL
2289// std::back_insert_iterator and std::back_inserter but are tailor-made
Jisi Liu885b6122015-02-28 14:51:22 -08002290// for RepeatedField and RepeatedPtrField. Typical usage would be:
kenton@google.comd37d46d2009-04-25 02:53:47 +00002291//
2292// std::copy(some_sequence.begin(), some_sequence.end(),
2293// google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
2294//
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002295// Ported by johannes from util/gtl/proto-array-iterators.h
kenton@google.comd37d46d2009-04-25 02:53:47 +00002296
2297namespace internal {
2298// A back inserter for RepeatedField objects.
2299template<typename T> class RepeatedFieldBackInsertIterator
2300 : public std::iterator<std::output_iterator_tag, T> {
2301 public:
2302 explicit RepeatedFieldBackInsertIterator(
2303 RepeatedField<T>* const mutable_field)
2304 : field_(mutable_field) {
2305 }
2306 RepeatedFieldBackInsertIterator<T>& operator=(const T& value) {
2307 field_->Add(value);
2308 return *this;
2309 }
2310 RepeatedFieldBackInsertIterator<T>& operator*() {
2311 return *this;
2312 }
2313 RepeatedFieldBackInsertIterator<T>& operator++() {
2314 return *this;
2315 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002316 RepeatedFieldBackInsertIterator<T>& operator++(int /* unused */) {
kenton@google.comd37d46d2009-04-25 02:53:47 +00002317 return *this;
2318 }
2319
2320 private:
liujisi@google.com2726e7a2010-12-03 09:12:33 +00002321 RepeatedField<T>* field_;
kenton@google.comd37d46d2009-04-25 02:53:47 +00002322};
2323
2324// A back inserter for RepeatedPtrField objects.
2325template<typename T> class RepeatedPtrFieldBackInsertIterator
2326 : public std::iterator<std::output_iterator_tag, T> {
2327 public:
2328 RepeatedPtrFieldBackInsertIterator(
2329 RepeatedPtrField<T>* const mutable_field)
2330 : field_(mutable_field) {
2331 }
2332 RepeatedPtrFieldBackInsertIterator<T>& operator=(const T& value) {
2333 *field_->Add() = value;
2334 return *this;
2335 }
2336 RepeatedPtrFieldBackInsertIterator<T>& operator=(
2337 const T* const ptr_to_value) {
2338 *field_->Add() = *ptr_to_value;
2339 return *this;
2340 }
2341 RepeatedPtrFieldBackInsertIterator<T>& operator*() {
2342 return *this;
2343 }
2344 RepeatedPtrFieldBackInsertIterator<T>& operator++() {
2345 return *this;
2346 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002347 RepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) {
kenton@google.comd37d46d2009-04-25 02:53:47 +00002348 return *this;
2349 }
2350
2351 private:
liujisi@google.com2726e7a2010-12-03 09:12:33 +00002352 RepeatedPtrField<T>* field_;
kenton@google.comd37d46d2009-04-25 02:53:47 +00002353};
2354
2355// A back inserter for RepeatedPtrFields that inserts by transfering ownership
2356// of a pointer.
2357template<typename T> class AllocatedRepeatedPtrFieldBackInsertIterator
2358 : public std::iterator<std::output_iterator_tag, T> {
2359 public:
2360 explicit AllocatedRepeatedPtrFieldBackInsertIterator(
2361 RepeatedPtrField<T>* const mutable_field)
2362 : field_(mutable_field) {
2363 }
2364 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=(
2365 T* const ptr_to_value) {
2366 field_->AddAllocated(ptr_to_value);
2367 return *this;
2368 }
2369 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() {
2370 return *this;
2371 }
2372 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() {
2373 return *this;
2374 }
2375 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002376 int /* unused */) {
kenton@google.comd37d46d2009-04-25 02:53:47 +00002377 return *this;
2378 }
2379
2380 private:
liujisi@google.com2726e7a2010-12-03 09:12:33 +00002381 RepeatedPtrField<T>* field_;
kenton@google.comd37d46d2009-04-25 02:53:47 +00002382};
2383} // namespace internal
2384
2385// Provides a back insert iterator for RepeatedField instances,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002386// similar to std::back_inserter().
kenton@google.comd37d46d2009-04-25 02:53:47 +00002387template<typename T> internal::RepeatedFieldBackInsertIterator<T>
2388RepeatedFieldBackInserter(RepeatedField<T>* const mutable_field) {
2389 return internal::RepeatedFieldBackInsertIterator<T>(mutable_field);
2390}
2391
2392// Provides a back insert iterator for RepeatedPtrField instances,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00002393// similar to std::back_inserter().
2394template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
2395RepeatedPtrFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
2396 return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
2397}
2398
2399// Special back insert iterator for RepeatedPtrField instances, just in
2400// case someone wants to write generic template code that can access both
2401// RepeatedFields and RepeatedPtrFields using a common name.
kenton@google.comd37d46d2009-04-25 02:53:47 +00002402template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
2403RepeatedFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
2404 return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
2405}
2406
2407// Provides a back insert iterator for RepeatedPtrField instances
2408// similar to std::back_inserter() which transfers the ownership while
2409// copying elements.
2410template<typename T> internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>
2411AllocatedRepeatedPtrFieldBackInserter(
2412 RepeatedPtrField<T>* const mutable_field) {
2413 return internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>(
2414 mutable_field);
2415}
2416
temporal40ee5512008-07-10 02:12:20 +00002417} // namespace protobuf
2418
2419} // namespace google
2420#endif // GOOGLE_PROTOBUF_REPEATED_FIELD_H__