1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34//
35// RepeatedField and RepeatedPtrField are used by generated protocol message
36// classes to manipulate repeated fields. These classes are very similar to
37// STL's vector, but include a number of optimizations found to be useful
38// specifically in the case of Protocol Buffers. RepeatedPtrField is
39// particularly different from STL vector as it manages ownership of the
40// pointers that it contains.
41//
42// This header covers RepeatedPtrField.
43
44// IWYU pragma: private, include "net/proto2/public/repeated_field.h"
45
46#ifndef GOOGLE_PROTOBUF_REPEATED_PTR_FIELD_H__
47#define GOOGLE_PROTOBUF_REPEATED_PTR_FIELD_H__
48
49#include <utility>
50
51#ifdef _MSC_VER
52// This is required for min/max on VS2013 only.
53#include <algorithm>
54#endif
55
56#include <iterator>
57#include <limits>
58#include <string>
59#include <type_traits>
60
61#include <google/protobuf/stubs/logging.h>
62#include <google/protobuf/stubs/common.h>
63#include <google/protobuf/arena.h>
64#include <google/protobuf/port.h>
65#include <google/protobuf/message_lite.h>
66
67
68// Must be included last.
69#include <google/protobuf/port_def.inc>
70
71#ifdef SWIG
72#error "You cannot SWIG proto headers"
73#endif
74
75namespace google {
76namespace protobuf {
77
78class Message;
79class Reflection;
80
81template <typename T>
82struct WeakRepeatedPtrField;
83
84namespace internal {
85
86class MergePartialFromCodedStreamHelper;
87class SwapFieldHelper;
88
89
90} // namespace internal
91
92namespace internal {
93template <typename It>
94class RepeatedPtrIterator;
95template <typename It, typename VoidPtr>
96class RepeatedPtrOverPtrsIterator;
97} // namespace internal
98
99namespace internal {
100
101// type-traits helper for RepeatedPtrFieldBase: we only want to invoke
102// arena-related "copy if on different arena" behavior if the necessary methods
103// exist on the contained type. In particular, we rely on MergeFrom() existing
104// as a general proxy for the fact that a copy will work, and we also provide a
105// specific override for std::string*.
106template <typename T>
107struct TypeImplementsMergeBehaviorProbeForMergeFrom {
108 typedef char HasMerge;
109 typedef long HasNoMerge;
110
111 // We accept either of:
112 // - void MergeFrom(const T& other)
113 // - bool MergeFrom(const T& other)
114 //
115 // We mangle these names a bit to avoid compatibility issues in 'unclean'
116 // include environments that may have, e.g., "#define test ..." (yes, this
117 // exists).
118 template <typename U, typename RetType, RetType (U::*)(const U& arg)>
119 struct CheckType;
120 template <typename U>
121 static HasMerge Check(CheckType<U, void, &U::MergeFrom>*);
122 template <typename U>
123 static HasMerge Check(CheckType<U, bool, &U::MergeFrom>*);
124 template <typename U>
125 static HasNoMerge Check(...);
126
127 // Resolves to either std::true_type or std::false_type.
128 typedef std::integral_constant<bool,
129 (sizeof(Check<T>(0)) == sizeof(HasMerge))>
130 type;
131};
132
133template <typename T, typename = void>
134struct TypeImplementsMergeBehavior
135 : TypeImplementsMergeBehaviorProbeForMergeFrom<T> {};
136
137
138template <>
139struct TypeImplementsMergeBehavior<std::string> {
140 typedef std::true_type type;
141};
142
143template <typename T>
144struct IsMovable
145 : std::integral_constant<bool, std::is_move_constructible<T>::value &&
146 std::is_move_assignable<T>::value> {};
147
148// This is the common base class for RepeatedPtrFields. It deals only in void*
149// pointers. Users should not use this interface directly.
150//
151// The methods of this interface correspond to the methods of RepeatedPtrField,
152// but may have a template argument called TypeHandler. Its signature is:
153// class TypeHandler {
154// public:
155// typedef MyType Type;
156// static Type* New();
157// static Type* NewFromPrototype(const Type* prototype,
158// Arena* arena);
159// static void Delete(Type*);
160// static void Clear(Type*);
161// static void Merge(const Type& from, Type* to);
162//
163// // Only needs to be implemented if SpaceUsedExcludingSelf() is called.
164// static int SpaceUsedLong(const Type&);
165// };
166class PROTOBUF_EXPORT RepeatedPtrFieldBase {
167 protected:
168 constexpr RepeatedPtrFieldBase()
169 : arena_(nullptr), current_size_(0), total_size_(0), rep_(nullptr) {}
170 explicit RepeatedPtrFieldBase(Arena* arena)
171 : arena_(arena), current_size_(0), total_size_(0), rep_(nullptr) {}
172
173 RepeatedPtrFieldBase(const RepeatedPtrFieldBase&) = delete;
174 RepeatedPtrFieldBase& operator=(const RepeatedPtrFieldBase&) = delete;
175
176 ~RepeatedPtrFieldBase() {
177#ifndef NDEBUG
178 // Try to trigger segfault / asan failure in non-opt builds. If arena_
179 // lifetime has ended before the destructor.
180 if (arena_) (void)arena_->SpaceAllocated();
181#endif
182 }
183
184 bool empty() const { return current_size_ == 0; }
185 int size() const { return current_size_; }
186 int Capacity() const { return total_size_; }
187
188 template <typename TypeHandler>
189 const typename TypeHandler::Type& at(int index) const {
190 GOOGLE_CHECK_GE(index, 0);
191 GOOGLE_CHECK_LT(index, current_size_);
192 return *cast<TypeHandler>(rep_->elements[index]);
193 }
194
195 template <typename TypeHandler>
196 typename TypeHandler::Type& at(int index) {
197 GOOGLE_CHECK_GE(index, 0);
198 GOOGLE_CHECK_LT(index, current_size_);
199 return *cast<TypeHandler>(rep_->elements[index]);
200 }
201
202 template <typename TypeHandler>
203 typename TypeHandler::Type* Mutable(int index) {
204 GOOGLE_DCHECK_GE(index, 0);
205 GOOGLE_DCHECK_LT(index, current_size_);
206 return cast<TypeHandler>(rep_->elements[index]);
207 }
208
209 template <typename TypeHandler>
210 typename TypeHandler::Type* Add(
211 const typename TypeHandler::Type* prototype = nullptr) {
212 if (rep_ != nullptr && current_size_ < rep_->allocated_size) {
213 return cast<TypeHandler>(rep_->elements[current_size_++]);
214 }
215 typename TypeHandler::Type* result =
216 TypeHandler::NewFromPrototype(prototype, arena_);
217 return reinterpret_cast<typename TypeHandler::Type*>(
218 AddOutOfLineHelper(obj: result));
219 }
220
221 template <
222 typename TypeHandler,
223 typename std::enable_if<TypeHandler::Movable::value>::type* = nullptr>
224 inline void Add(typename TypeHandler::Type&& value) {
225 if (rep_ != nullptr && current_size_ < rep_->allocated_size) {
226 *cast<TypeHandler>(rep_->elements[current_size_++]) = std::move(value);
227 return;
228 }
229 if (!rep_ || rep_->allocated_size == total_size_) {
230 Reserve(new_size: total_size_ + 1);
231 }
232 ++rep_->allocated_size;
233 typename TypeHandler::Type* result =
234 TypeHandler::New(arena_, std::move(value));
235 rep_->elements[current_size_++] = result;
236 }
237
238 template <typename TypeHandler>
239 void Delete(int index) {
240 GOOGLE_DCHECK_GE(index, 0);
241 GOOGLE_DCHECK_LT(index, current_size_);
242 TypeHandler::Delete(cast<TypeHandler>(rep_->elements[index]), arena_);
243 }
244
245 // Must be called from destructor.
246 template <typename TypeHandler>
247 void Destroy() {
248 if (rep_ != nullptr && arena_ == nullptr) {
249 int n = rep_->allocated_size;
250 void* const* elements = rep_->elements;
251 for (int i = 0; i < n; i++) {
252 TypeHandler::Delete(cast<TypeHandler>(elements[i]), nullptr);
253 }
254 const size_t size = total_size_ * sizeof(elements[0]) + kRepHeaderSize;
255 internal::SizedDelete(p: rep_, size);
256 }
257 rep_ = nullptr;
258 }
259
260 bool NeedsDestroy() const { return rep_ != nullptr && arena_ == nullptr; }
261 void DestroyProtos(); // implemented in the cc file
262
263 public:
264 // The next few methods are public so that they can be called from generated
265 // code when implicit weak fields are used, but they should never be called by
266 // application code.
267
268 template <typename TypeHandler>
269 const typename TypeHandler::Type& Get(int index) const {
270 GOOGLE_DCHECK_GE(index, 0);
271 GOOGLE_DCHECK_LT(index, current_size_);
272 return *cast<TypeHandler>(rep_->elements[index]);
273 }
274
275 // Creates and adds an element using the given prototype, without introducing
276 // a link-time dependency on the concrete message type. This method is used to
277 // implement implicit weak fields. The prototype may be nullptr, in which case
278 // an ImplicitWeakMessage will be used as a placeholder.
279 MessageLite* AddWeak(const MessageLite* prototype);
280
281 template <typename TypeHandler>
282 void Clear() {
283 const int n = current_size_;
284 GOOGLE_DCHECK_GE(n, 0);
285 if (n > 0) {
286 void* const* elements = rep_->elements;
287 int i = 0;
288 do {
289 TypeHandler::Clear(cast<TypeHandler>(elements[i++]));
290 } while (i < n);
291 current_size_ = 0;
292 }
293 }
294
295 template <typename TypeHandler>
296 void MergeFrom(const RepeatedPtrFieldBase& other) {
297 // To avoid unnecessary code duplication and reduce binary size, we use a
298 // layered approach to implementing MergeFrom(). The toplevel method is
299 // templated, so we get a small thunk per concrete message type in the
300 // binary. This calls a shared implementation with most of the logic,
301 // passing a function pointer to another type-specific piece of code that
302 // calls the object-allocate and merge handlers.
303 GOOGLE_DCHECK_NE(&other, this);
304 if (other.current_size_ == 0) return;
305 MergeFromInternal(other,
306 inner_loop: &RepeatedPtrFieldBase::MergeFromInnerLoop<TypeHandler>);
307 }
308
309 inline void InternalSwap(RepeatedPtrFieldBase* rhs) {
310 GOOGLE_DCHECK(this != rhs);
311
312 // Swap all fields at once.
313 auto temp = std::make_tuple(args&: rhs->arena_, args&: rhs->current_size_,
314 args&: rhs->total_size_, args&: rhs->rep_);
315 std::tie(args&: rhs->arena_, args&: rhs->current_size_, args&: rhs->total_size_, args&: rhs->rep_) =
316 std::make_tuple(args&: arena_, args&: current_size_, args&: total_size_, args&: rep_);
317 std::tie(args&: arena_, args&: current_size_, args&: total_size_, args&: rep_) = temp;
318 }
319
320 protected:
321 template <typename TypeHandler>
322 void RemoveLast() {
323 GOOGLE_DCHECK_GT(current_size_, 0);
324 TypeHandler::Clear(cast<TypeHandler>(rep_->elements[--current_size_]));
325 }
326
327 template <typename TypeHandler>
328 void CopyFrom(const RepeatedPtrFieldBase& other) {
329 if (&other == this) return;
330 RepeatedPtrFieldBase::Clear<TypeHandler>();
331 RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
332 }
333
334 void CloseGap(int start, int num); // implemented in the cc file
335
336 void Reserve(int new_size); // implemented in the cc file
337
338 template <typename TypeHandler>
339 static inline typename TypeHandler::Type* copy(
340 typename TypeHandler::Type* value) {
341 auto* new_value = TypeHandler::NewFromPrototype(value, nullptr);
342 TypeHandler::Merge(*value, new_value);
343 return new_value;
344 }
345
346 // Used for constructing iterators.
347 void* const* raw_data() const { return rep_ ? rep_->elements : nullptr; }
348 void** raw_mutable_data() const {
349 return rep_ ? const_cast<void**>(rep_->elements) : nullptr;
350 }
351
352 template <typename TypeHandler>
353 typename TypeHandler::Type** mutable_data() {
354 // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
355 // method entirely.
356 return reinterpret_cast<typename TypeHandler::Type**>(raw_mutable_data());
357 }
358
359 template <typename TypeHandler>
360 const typename TypeHandler::Type* const* data() const {
361 // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
362 // method entirely.
363 return reinterpret_cast<const typename TypeHandler::Type* const*>(
364 raw_data());
365 }
366
367 template <typename TypeHandler>
368 PROTOBUF_NDEBUG_INLINE void Swap(RepeatedPtrFieldBase* other) {
369#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
370 if (GetOwningArena() != nullptr &&
371 GetOwningArena() == other->GetOwningArena())
372#else // PROTOBUF_FORCE_COPY_IN_SWAP
373 if (GetOwningArena() == other->GetOwningArena())
374#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
375 {
376 InternalSwap(rhs: other);
377 } else {
378 SwapFallback<TypeHandler>(other);
379 }
380 }
381
382 void SwapElements(int index1, int index2) {
383 using std::swap; // enable ADL with fallback
384 swap(a&: rep_->elements[index1], b&: rep_->elements[index2]);
385 }
386
387 template <typename TypeHandler>
388 size_t SpaceUsedExcludingSelfLong() const {
389 size_t allocated_bytes = static_cast<size_t>(total_size_) * sizeof(void*);
390 if (rep_ != nullptr) {
391 for (int i = 0; i < rep_->allocated_size; ++i) {
392 allocated_bytes +=
393 TypeHandler::SpaceUsedLong(*cast<TypeHandler>(rep_->elements[i]));
394 }
395 allocated_bytes += kRepHeaderSize;
396 }
397 return allocated_bytes;
398 }
399
400 // Advanced memory management --------------------------------------
401
402 // Like Add(), but if there are no cleared objects to use, returns nullptr.
403 template <typename TypeHandler>
404 typename TypeHandler::Type* AddFromCleared() {
405 if (rep_ != nullptr && current_size_ < rep_->allocated_size) {
406 return cast<TypeHandler>(rep_->elements[current_size_++]);
407 } else {
408 return nullptr;
409 }
410 }
411
412 template <typename TypeHandler>
413 void AddAllocated(typename TypeHandler::Type* value) {
414 typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
415 AddAllocatedInternal<TypeHandler>(value, t);
416 }
417
418 template <typename TypeHandler>
419 void UnsafeArenaAddAllocated(typename TypeHandler::Type* value) {
420 // Make room for the new pointer.
421 if (!rep_ || current_size_ == total_size_) {
422 // The array is completely full with no cleared objects, so grow it.
423 Reserve(new_size: total_size_ + 1);
424 ++rep_->allocated_size;
425 } else if (rep_->allocated_size == total_size_) {
426 // There is no more space in the pointer array because it contains some
427 // cleared objects awaiting reuse. We don't want to grow the array in
428 // this case because otherwise a loop calling AddAllocated() followed by
429 // Clear() would leak memory.
430 TypeHandler::Delete(cast<TypeHandler>(rep_->elements[current_size_]),
431 arena_);
432 } else if (current_size_ < rep_->allocated_size) {
433 // We have some cleared objects. We don't care about their order, so we
434 // can just move the first one to the end to make space.
435 rep_->elements[rep_->allocated_size] = rep_->elements[current_size_];
436 ++rep_->allocated_size;
437 } else {
438 // There are no cleared objects.
439 ++rep_->allocated_size;
440 }
441
442 rep_->elements[current_size_++] = value;
443 }
444
445 template <typename TypeHandler>
446 PROTOBUF_NODISCARD typename TypeHandler::Type* ReleaseLast() {
447 typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
448 return ReleaseLastInternal<TypeHandler>(t);
449 }
450
451 // Releases and returns the last element, but does not do out-of-arena copy.
452 // Instead, just returns the raw pointer to the contained element in the
453 // arena.
454 template <typename TypeHandler>
455 typename TypeHandler::Type* UnsafeArenaReleaseLast() {
456 GOOGLE_DCHECK_GT(current_size_, 0);
457 typename TypeHandler::Type* result =
458 cast<TypeHandler>(rep_->elements[--current_size_]);
459 --rep_->allocated_size;
460 if (current_size_ < rep_->allocated_size) {
461 // There are cleared elements on the end; replace the removed element
462 // with the last allocated element.
463 rep_->elements[current_size_] = rep_->elements[rep_->allocated_size];
464 }
465 return result;
466 }
467
468 int ClearedCount() const {
469 return rep_ ? (rep_->allocated_size - current_size_) : 0;
470 }
471
472 template <typename TypeHandler>
473 void AddCleared(typename TypeHandler::Type* value) {
474 GOOGLE_DCHECK(GetOwningArena() == nullptr) << "AddCleared() can only be used on a "
475 "RepeatedPtrField not on an arena.";
476 GOOGLE_DCHECK(TypeHandler::GetOwningArena(value) == nullptr)
477 << "AddCleared() can only accept values not on an arena.";
478 if (!rep_ || rep_->allocated_size == total_size_) {
479 Reserve(new_size: total_size_ + 1);
480 }
481 rep_->elements[rep_->allocated_size++] = value;
482 }
483
484 template <typename TypeHandler>
485 PROTOBUF_NODISCARD typename TypeHandler::Type* ReleaseCleared() {
486 GOOGLE_DCHECK(GetOwningArena() == nullptr)
487 << "ReleaseCleared() can only be used on a RepeatedPtrField not on "
488 << "an arena.";
489 GOOGLE_DCHECK(GetOwningArena() == nullptr);
490 GOOGLE_DCHECK(rep_ != nullptr);
491 GOOGLE_DCHECK_GT(rep_->allocated_size, current_size_);
492 return cast<TypeHandler>(rep_->elements[--rep_->allocated_size]);
493 }
494
495 template <typename TypeHandler>
496 void AddAllocatedInternal(typename TypeHandler::Type* value, std::true_type) {
497 // AddAllocated version that implements arena-safe copying behavior.
498 Arena* element_arena =
499 reinterpret_cast<Arena*>(TypeHandler::GetOwningArena(value));
500 Arena* arena = GetOwningArena();
501 if (arena == element_arena && rep_ && rep_->allocated_size < total_size_) {
502 // Fast path: underlying arena representation (tagged pointer) is equal to
503 // our arena pointer, and we can add to array without resizing it (at
504 // least one slot that is not allocated).
505 void** elems = rep_->elements;
506 if (current_size_ < rep_->allocated_size) {
507 // Make space at [current] by moving first allocated element to end of
508 // allocated list.
509 elems[rep_->allocated_size] = elems[current_size_];
510 }
511 elems[current_size_] = value;
512 current_size_ = current_size_ + 1;
513 rep_->allocated_size = rep_->allocated_size + 1;
514 } else {
515 AddAllocatedSlowWithCopy<TypeHandler>(value, element_arena, arena);
516 }
517 }
518
519 template <typename TypeHandler>
520 void AddAllocatedInternal(
521 // AddAllocated version that does not implement arena-safe copying
522 // behavior.
523 typename TypeHandler::Type* value, std::false_type) {
524 if (rep_ && rep_->allocated_size < total_size_) {
525 // Fast path: underlying arena representation (tagged pointer) is equal to
526 // our arena pointer, and we can add to array without resizing it (at
527 // least one slot that is not allocated).
528 void** elems = rep_->elements;
529 if (current_size_ < rep_->allocated_size) {
530 // Make space at [current] by moving first allocated element to end of
531 // allocated list.
532 elems[rep_->allocated_size] = elems[current_size_];
533 }
534 elems[current_size_] = value;
535 current_size_ = current_size_ + 1;
536 ++rep_->allocated_size;
537 } else {
538 UnsafeArenaAddAllocated<TypeHandler>(value);
539 }
540 }
541
542 // Slowpath handles all cases, copying if necessary.
543 template <typename TypeHandler>
544 PROTOBUF_NOINLINE void AddAllocatedSlowWithCopy(
545 // Pass value_arena and my_arena to avoid duplicate virtual call (value)
546 // or load (mine).
547 typename TypeHandler::Type* value, Arena* value_arena, Arena* my_arena) {
548 // Ensure that either the value is in the same arena, or if not, we do the
549 // appropriate thing: Own() it (if it's on heap and we're in an arena) or
550 // copy it to our arena/heap (otherwise).
551 if (my_arena != nullptr && value_arena == nullptr) {
552 my_arena->Own(value);
553 } else if (my_arena != value_arena) {
554 typename TypeHandler::Type* new_value =
555 TypeHandler::NewFromPrototype(value, my_arena);
556 TypeHandler::Merge(*value, new_value);
557 TypeHandler::Delete(value, value_arena);
558 value = new_value;
559 }
560
561 UnsafeArenaAddAllocated<TypeHandler>(value);
562 }
563
564 template <typename TypeHandler>
565 typename TypeHandler::Type* ReleaseLastInternal(std::true_type) {
566 // ReleaseLast() for types that implement merge/copy behavior.
567 // First, release an element.
568 typename TypeHandler::Type* result = UnsafeArenaReleaseLast<TypeHandler>();
569 // Now perform a copy if we're on an arena.
570 Arena* arena = GetOwningArena();
571
572 typename TypeHandler::Type* new_result;
573#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
574 new_result = copy<TypeHandler>(result);
575 if (arena == nullptr) delete result;
576#else // PROTOBUF_FORCE_COPY_IN_RELEASE
577 new_result = (arena == nullptr) ? result : copy<TypeHandler>(result);
578#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE
579 return new_result;
580 }
581
582 template <typename TypeHandler>
583 typename TypeHandler::Type* ReleaseLastInternal(std::false_type) {
584 // ReleaseLast() for types that *do not* implement merge/copy behavior --
585 // this is the same as UnsafeArenaReleaseLast(). Note that we GOOGLE_DCHECK-fail if
586 // we're on an arena, since the user really should implement the copy
587 // operation in this case.
588 GOOGLE_DCHECK(GetOwningArena() == nullptr)
589 << "ReleaseLast() called on a RepeatedPtrField that is on an arena, "
590 << "with a type that does not implement MergeFrom. This is unsafe; "
591 << "please implement MergeFrom for your type.";
592 return UnsafeArenaReleaseLast<TypeHandler>();
593 }
594
595 template <typename TypeHandler>
596 PROTOBUF_NOINLINE void SwapFallback(RepeatedPtrFieldBase* other) {
597#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
598 GOOGLE_DCHECK(GetOwningArena() == nullptr ||
599 other->GetOwningArena() != GetOwningArena());
600#else // PROTOBUF_FORCE_COPY_IN_SWAP
601 GOOGLE_DCHECK(other->GetOwningArena() != GetOwningArena());
602#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
603
604 // Copy semantics in this case. We try to improve efficiency by placing the
605 // temporary on |other|'s arena so that messages are copied twice rather
606 // than three times.
607 RepeatedPtrFieldBase temp(other->GetOwningArena());
608 temp.MergeFrom<TypeHandler>(*this);
609 this->Clear<TypeHandler>();
610 this->MergeFrom<TypeHandler>(*other);
611 other->InternalSwap(rhs: &temp);
612 temp.Destroy<TypeHandler>(); // Frees rep_ if `other` had no arena.
613 }
614
615 inline Arena* GetArena() const { return arena_; }
616
617 protected:
618 inline Arena* GetOwningArena() const { return arena_; }
619
620 private:
621 template <typename T> friend class Arena::InternalHelper;
622
623 static constexpr int kInitialSize = 0;
624 // A few notes on internal representation:
625 //
626 // We use an indirected approach, with struct Rep, to keep
627 // sizeof(RepeatedPtrFieldBase) equivalent to what it was before arena support
628 // was added; namely, 3 8-byte machine words on x86-64. An instance of Rep is
629 // allocated only when the repeated field is non-empty, and it is a
630 // dynamically-sized struct (the header is directly followed by elements[]).
631 // We place arena_ and current_size_ directly in the object to avoid cache
632 // misses due to the indirection, because these fields are checked frequently.
633 // Placing all fields directly in the RepeatedPtrFieldBase instance would cost
634 // significant performance for memory-sensitive workloads.
635 Arena* arena_;
636 int current_size_;
637 int total_size_;
638 struct Rep {
639 int allocated_size;
640 // Here we declare a huge array as a way of approximating C's "flexible
641 // array member" feature without relying on undefined behavior.
642 void* elements[(std::numeric_limits<int>::max() - 2 * sizeof(int)) /
643 sizeof(void*)];
644 };
645 static constexpr size_t kRepHeaderSize = offsetof(Rep, elements);
646 Rep* rep_;
647
648 template <typename TypeHandler>
649 static inline typename TypeHandler::Type* cast(void* element) {
650 return reinterpret_cast<typename TypeHandler::Type*>(element);
651 }
652 template <typename TypeHandler>
653 static inline const typename TypeHandler::Type* cast(const void* element) {
654 return reinterpret_cast<const typename TypeHandler::Type*>(element);
655 }
656
657 // Non-templated inner function to avoid code duplication. Takes a function
658 // pointer to the type-specific (templated) inner allocate/merge loop.
659 void MergeFromInternal(const RepeatedPtrFieldBase& other,
660 void (RepeatedPtrFieldBase::*inner_loop)(void**,
661 void**, int,
662 int)) {
663 // Note: wrapper has already guaranteed that other.rep_ != nullptr here.
664 int other_size = other.current_size_;
665 void** other_elements = other.rep_->elements;
666 void** new_elements = InternalExtend(extend_amount: other_size);
667 int allocated_elems = rep_->allocated_size - current_size_;
668 (this->*inner_loop)(new_elements, other_elements, other_size,
669 allocated_elems);
670 current_size_ += other_size;
671 if (rep_->allocated_size < current_size_) {
672 rep_->allocated_size = current_size_;
673 }
674 }
675
676 // Merges other_elems to our_elems.
677 template <typename TypeHandler>
678 PROTOBUF_NOINLINE void MergeFromInnerLoop(void** our_elems,
679 void** other_elems, int length,
680 int already_allocated) {
681 if (already_allocated < length) {
682 Arena* arena = GetOwningArena();
683 typename TypeHandler::Type* elem_prototype =
684 reinterpret_cast<typename TypeHandler::Type*>(other_elems[0]);
685 for (int i = already_allocated; i < length; i++) {
686 // Allocate a new empty element that we'll merge into below
687 typename TypeHandler::Type* new_elem =
688 TypeHandler::NewFromPrototype(elem_prototype, arena);
689 our_elems[i] = new_elem;
690 }
691 }
692 // Main loop that does the actual merging
693 for (int i = 0; i < length; i++) {
694 // Already allocated: use existing element.
695 typename TypeHandler::Type* other_elem =
696 reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
697 typename TypeHandler::Type* new_elem =
698 reinterpret_cast<typename TypeHandler::Type*>(our_elems[i]);
699 TypeHandler::Merge(*other_elem, new_elem);
700 }
701 }
702
703 // Internal helper: extends array space if necessary to contain
704 // |extend_amount| more elements, and returns a pointer to the element
705 // immediately following the old list of elements. This interface factors out
706 // common behavior from Reserve() and MergeFrom() to reduce code size.
707 // |extend_amount| must be > 0.
708 void** InternalExtend(int extend_amount);
709
710 // Internal helper for Add: adds "obj" as the next element in the
711 // array, including potentially resizing the array with Reserve if
712 // needed
713 void* AddOutOfLineHelper(void* obj);
714
715 // The reflection implementation needs to call protected methods directly,
716 // reinterpreting pointers as being to Message instead of a specific Message
717 // subclass.
718 friend class ::PROTOBUF_NAMESPACE_ID::Reflection;
719 friend class ::PROTOBUF_NAMESPACE_ID::internal::SwapFieldHelper;
720
721 // ExtensionSet stores repeated message extensions as
722 // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to implement
723 // SpaceUsedLong(), and thus need to call SpaceUsedExcludingSelfLong()
724 // reinterpreting MessageLite as Message. ExtensionSet also needs to make use
725 // of AddFromCleared(), which is not part of the public interface.
726 friend class ExtensionSet;
727
728 // The MapFieldBase implementation needs to call protected methods directly,
729 // reinterpreting pointers as being to Message instead of a specific Message
730 // subclass.
731 friend class MapFieldBase;
732 friend class MapFieldBaseStub;
733
734 // The table-driven MergePartialFromCodedStream implementation needs to
735 // operate on RepeatedPtrField<MessageLite>.
736 friend class MergePartialFromCodedStreamHelper;
737 friend class AccessorHelper;
738 template <typename T>
739 friend struct google::protobuf::WeakRepeatedPtrField;
740 friend class internal::TcParser; // TODO(jorg): Remove this friend.
741};
742
743template <typename GenericType>
744class GenericTypeHandler {
745 public:
746 typedef GenericType Type;
747 using Movable = IsMovable<GenericType>;
748
749 static inline GenericType* New(Arena* arena) {
750 return Arena::CreateMaybeMessage<Type>(arena);
751 }
752 static inline GenericType* New(Arena* arena, GenericType&& value) {
753 return Arena::Create<GenericType>(arena, std::move(value));
754 }
755 static inline GenericType* NewFromPrototype(const GenericType* /*prototype*/,
756 Arena* arena = nullptr) {
757 return New(arena);
758 }
759 static inline void Delete(GenericType* value, Arena* arena) {
760 if (arena == nullptr) {
761 delete value;
762 }
763 }
764 static inline Arena* GetOwningArena(GenericType* value) {
765 return Arena::GetOwningArena<Type>(value);
766 }
767
768 static inline void Clear(GenericType* value) { value->Clear(); }
769 static void Merge(const GenericType& from, GenericType* to);
770 static inline size_t SpaceUsedLong(const GenericType& value) {
771 return value.SpaceUsedLong();
772 }
773};
774
775// NewFromPrototypeHelper() is not defined inline here, as we will need to do a
776// virtual function dispatch anyways to go from Message* to call New/Merge. (The
777// additional helper is needed as a workaround for MSVC.)
778MessageLite* NewFromPrototypeHelper(const MessageLite* prototype, Arena* arena);
779
780template <>
781inline MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
782 const MessageLite* prototype, Arena* arena) {
783 return NewFromPrototypeHelper(prototype, arena);
784}
785template <>
786inline Arena* GenericTypeHandler<MessageLite>::GetOwningArena(
787 MessageLite* value) {
788 return value->GetOwningArena();
789}
790
791template <typename GenericType>
792PROTOBUF_NOINLINE inline void GenericTypeHandler<GenericType>::Merge(
793 const GenericType& from, GenericType* to) {
794 to->MergeFrom(from);
795}
796template <>
797void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
798 MessageLite* to);
799
800template <>
801inline void GenericTypeHandler<std::string>::Clear(std::string* value) {
802 value->clear();
803}
804template <>
805void GenericTypeHandler<std::string>::Merge(const std::string& from,
806 std::string* to);
807
808// Message specialization bodies defined in message.cc. This split is necessary
809// to allow proto2-lite (which includes this header) to be independent of
810// Message.
811template <>
812PROTOBUF_EXPORT Message* GenericTypeHandler<Message>::NewFromPrototype(
813 const Message* prototype, Arena* arena);
814template <>
815PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetOwningArena(
816 Message* value);
817
818class StringTypeHandler {
819 public:
820 typedef std::string Type;
821 using Movable = IsMovable<Type>;
822
823 static inline std::string* New(Arena* arena) {
824 return Arena::Create<std::string>(arena);
825 }
826 static inline std::string* New(Arena* arena, std::string&& value) {
827 return Arena::Create<std::string>(arena, args: std::move(value));
828 }
829 static inline std::string* NewFromPrototype(const std::string*,
830 Arena* arena) {
831 return New(arena);
832 }
833 static inline Arena* GetOwningArena(std::string*) { return nullptr; }
834 static inline void Delete(std::string* value, Arena* arena) {
835 if (arena == nullptr) {
836 delete value;
837 }
838 }
839 static inline void Clear(std::string* value) { value->clear(); }
840 static inline void Merge(const std::string& from, std::string* to) {
841 *to = from;
842 }
843 static size_t SpaceUsedLong(const std::string& value) {
844 return sizeof(value) + StringSpaceUsedExcludingSelfLong(str: value);
845 }
846};
847
848} // namespace internal
849
850// RepeatedPtrField is like RepeatedField, but used for repeated strings or
851// Messages.
852template <typename Element>
853class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
854
855 public:
856 constexpr RepeatedPtrField();
857 explicit RepeatedPtrField(Arena* arena);
858
859 RepeatedPtrField(const RepeatedPtrField& other);
860
861 template <typename Iter,
862 typename = typename std::enable_if<std::is_constructible<
863 Element, decltype(*std::declval<Iter>())>::value>::type>
864 RepeatedPtrField(Iter begin, Iter end);
865
866 ~RepeatedPtrField();
867
868 RepeatedPtrField& operator=(const RepeatedPtrField& other);
869
870 RepeatedPtrField(RepeatedPtrField&& other) noexcept;
871 RepeatedPtrField& operator=(RepeatedPtrField&& other) noexcept;
872
873 bool empty() const;
874 int size() const;
875
876 const Element& Get(int index) const;
877 Element* Mutable(int index);
878
879 // Unlike std::vector, adding an element to a RepeatedPtrField doesn't always
880 // make a new element; it might re-use an element left over from when the
881 // field was Clear()'d or reize()'d smaller. For this reason, Add() is the
882 // fastest API for adding a new element.
883 Element* Add();
884
885 // `Add(std::move(value));` is equivalent to `*Add() = std::move(value);`
886 // It will either move-construct to the end of this field, or swap value
887 // with the new-or-recycled element at the end of this field. Note that
888 // this operation is very slow if this RepeatedPtrField is not on the
889 // same Arena, if any, as `value`.
890 void Add(Element&& value);
891
892 // Copying to the end of this RepeatedPtrField is slowest of all; it can't
893 // reliably copy-construct to the last element of this RepeatedPtrField, for
894 // example (unlike std::vector).
895 // We currently block this API. The right way to add to the end is to call
896 // Add() and modify the element it points to.
897 // If you must add an existing value, call `*Add() = value;`
898 void Add(const Element& value) = delete;
899
900 // Append elements in the range [begin, end) after reserving
901 // the appropriate number of elements.
902 template <typename Iter>
903 void Add(Iter begin, Iter end);
904
905 const Element& operator[](int index) const { return Get(index); }
906 Element& operator[](int index) { return *Mutable(index); }
907
908 const Element& at(int index) const;
909 Element& at(int index);
910
911 // Removes the last element in the array.
912 // Ownership of the element is retained by the array.
913 void RemoveLast();
914
915 // Deletes elements with indices in the range [start .. start+num-1].
916 // Caution: moves all elements with indices [start+num .. ].
917 // Calling this routine inside a loop can cause quadratic behavior.
918 void DeleteSubrange(int start, int num);
919
920 PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear();
921 void MergeFrom(const RepeatedPtrField& other);
922 PROTOBUF_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedPtrField& other);
923
924 // Replaces the contents with RepeatedPtrField(begin, end).
925 template <typename Iter>
926 PROTOBUF_ATTRIBUTE_REINITIALIZES void Assign(Iter begin, Iter end);
927
928 // Reserves space to expand the field to at least the given size. This only
929 // resizes the pointer array; it doesn't allocate any objects. If the
930 // array is grown, it will always be at least doubled in size.
931 void Reserve(int new_size);
932
933 int Capacity() const;
934
935 // Gets the underlying array. This pointer is possibly invalidated by
936 // any add or remove operation.
937 //
938 // This API is deprecated. Instead of directly working with element array,
939 // use APIs in repeated_field_util.h; e.g. sorting, etc.
940 PROTOBUF_DEPRECATED_MSG("Use APIs in repeated_field_util.h")
941 Element** mutable_data();
942 const Element* const* data() const;
943
944 // Swaps entire contents with "other". If they are on separate arenas, then
945 // copies data.
946 void Swap(RepeatedPtrField* other);
947
948 // Swaps entire contents with "other". Caller should guarantee that either
949 // both fields are on the same arena or both are on the heap. Swapping between
950 // different arenas with this function is disallowed and is caught via
951 // GOOGLE_DCHECK.
952 void UnsafeArenaSwap(RepeatedPtrField* other);
953
954 // Swaps two elements.
955 void SwapElements(int index1, int index2);
956
957 // STL-like iterator support
958 typedef internal::RepeatedPtrIterator<Element> iterator;
959 typedef internal::RepeatedPtrIterator<const Element> const_iterator;
960 typedef Element value_type;
961 typedef value_type& reference;
962 typedef const value_type& const_reference;
963 typedef value_type* pointer;
964 typedef const value_type* const_pointer;
965 typedef int size_type;
966 typedef ptrdiff_t difference_type;
967
968 iterator begin();
969 const_iterator begin() const;
970 const_iterator cbegin() const;
971 iterator end();
972 const_iterator end() const;
973 const_iterator cend() const;
974
975 // Reverse iterator support
976 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
977 typedef std::reverse_iterator<iterator> reverse_iterator;
978 reverse_iterator rbegin() { return reverse_iterator(end()); }
979 const_reverse_iterator rbegin() const {
980 return const_reverse_iterator(end());
981 }
982 reverse_iterator rend() { return reverse_iterator(begin()); }
983 const_reverse_iterator rend() const {
984 return const_reverse_iterator(begin());
985 }
986
987 // Custom STL-like iterator that iterates over and returns the underlying
988 // pointers to Element rather than Element itself.
989 typedef internal::RepeatedPtrOverPtrsIterator<Element*, void*>
990 pointer_iterator;
991 typedef internal::RepeatedPtrOverPtrsIterator<const Element* const,
992 const void* const>
993 const_pointer_iterator;
994 pointer_iterator pointer_begin();
995 const_pointer_iterator pointer_begin() const;
996 pointer_iterator pointer_end();
997 const_pointer_iterator pointer_end() const;
998
999 // Returns (an estimate of) the number of bytes used by the repeated field,
1000 // excluding sizeof(*this).
1001 size_t SpaceUsedExcludingSelfLong() const;
1002
1003 int SpaceUsedExcludingSelf() const {
1004 return internal::ToIntSize(size: SpaceUsedExcludingSelfLong());
1005 }
1006
1007 // Advanced memory management --------------------------------------
1008 // When hardcore memory management becomes necessary -- as it sometimes
1009 // does here at Google -- the following methods may be useful.
1010
1011 // Adds an already-allocated object, passing ownership to the
1012 // RepeatedPtrField.
1013 //
1014 // Note that some special behavior occurs with respect to arenas:
1015 //
1016 // (i) if this field holds submessages, the new submessage will be copied if
1017 // the original is in an arena and this RepeatedPtrField is either in a
1018 // different arena, or on the heap.
1019 // (ii) if this field holds strings, the passed-in string *must* be
1020 // heap-allocated, not arena-allocated. There is no way to dynamically check
1021 // this at runtime, so User Beware.
1022 void AddAllocated(Element* value);
1023
1024 // Removes and returns the last element, passing ownership to the caller.
1025 // Requires: size() > 0
1026 //
1027 // If this RepeatedPtrField is on an arena, an object copy is required to pass
1028 // ownership back to the user (for compatible semantics). Use
1029 // UnsafeArenaReleaseLast() if this behavior is undesired.
1030 PROTOBUF_NODISCARD Element* ReleaseLast();
1031
1032 // Adds an already-allocated object, skipping arena-ownership checks. The user
1033 // must guarantee that the given object is in the same arena as this
1034 // RepeatedPtrField.
1035 // It is also useful in legacy code that uses temporary ownership to avoid
1036 // copies. Example:
1037 // RepeatedPtrField<T> temp_field;
1038 // temp_field.UnsafeArenaAddAllocated(new T);
1039 // ... // Do something with temp_field
1040 // temp_field.UnsafeArenaExtractSubrange(0, temp_field.size(), nullptr);
1041 // If you put temp_field on the arena this fails, because the ownership
1042 // transfers to the arena at the "AddAllocated" call and is not released
1043 // anymore, causing a double delete. UnsafeArenaAddAllocated prevents this.
1044 void UnsafeArenaAddAllocated(Element* value);
1045
1046 // Removes and returns the last element. Unlike ReleaseLast, the returned
1047 // pointer is always to the original object. This may be in an arena, in
1048 // which case it would have the arena's lifetime.
1049 // Requires: current_size_ > 0
1050 Element* UnsafeArenaReleaseLast();
1051
1052 // Extracts elements with indices in the range "[start .. start+num-1]".
1053 // The caller assumes ownership of the extracted elements and is responsible
1054 // for deleting them when they are no longer needed.
1055 // If "elements" is non-nullptr, then pointers to the extracted elements
1056 // are stored in "elements[0 .. num-1]" for the convenience of the caller.
1057 // If "elements" is nullptr, then the caller must use some other mechanism
1058 // to perform any further operations (like deletion) on these elements.
1059 // Caution: implementation also moves elements with indices [start+num ..].
1060 // Calling this routine inside a loop can cause quadratic behavior.
1061 //
1062 // Memory copying behavior is identical to ReleaseLast(), described above: if
1063 // this RepeatedPtrField is on an arena, an object copy is performed for each
1064 // returned element, so that all returned element pointers are to
1065 // heap-allocated copies. If this copy is not desired, the user should call
1066 // UnsafeArenaExtractSubrange().
1067 void ExtractSubrange(int start, int num, Element** elements);
1068
1069 // Identical to ExtractSubrange() described above, except that no object
1070 // copies are ever performed. Instead, the raw object pointers are returned.
1071 // Thus, if on an arena, the returned objects must not be freed, because they
1072 // will not be heap-allocated objects.
1073 void UnsafeArenaExtractSubrange(int start, int num, Element** elements);
1074
1075 // When elements are removed by calls to RemoveLast() or Clear(), they
1076 // are not actually freed. Instead, they are cleared and kept so that
1077 // they can be reused later. This can save lots of CPU time when
1078 // repeatedly reusing a protocol message for similar purposes.
1079 //
1080 // Hardcore programs may choose to manipulate these cleared objects
1081 // to better optimize memory management using the following routines.
1082
1083 // Gets the number of cleared objects that are currently being kept
1084 // around for reuse.
1085 int ClearedCount() const;
1086#ifndef PROTOBUF_FUTURE_BREAKING_CHANGES
1087 // Adds an element to the pool of cleared objects, passing ownership to
1088 // the RepeatedPtrField. The element must be cleared prior to calling
1089 // this method.
1090 //
1091 // This method cannot be called when either the repeated field or |value| is
1092 // on an arena; both cases will trigger a GOOGLE_DCHECK-failure.
1093 void AddCleared(Element* value);
1094 // Removes and returns a single element from the cleared pool, passing
1095 // ownership to the caller. The element is guaranteed to be cleared.
1096 // Requires: ClearedCount() > 0
1097 //
1098 // This method cannot be called when the repeated field is on an arena; doing
1099 // so will trigger a GOOGLE_DCHECK-failure.
1100 PROTOBUF_NODISCARD Element* ReleaseCleared();
1101#endif // !PROTOBUF_FUTURE_BREAKING_CHANGES
1102
1103 // Removes the element referenced by position.
1104 //
1105 // Returns an iterator to the element immediately following the removed
1106 // element.
1107 //
1108 // Invalidates all iterators at or after the removed element, including end().
1109 iterator erase(const_iterator position);
1110
1111 // Removes the elements in the range [first, last).
1112 //
1113 // Returns an iterator to the element immediately following the removed range.
1114 //
1115 // Invalidates all iterators at or after the removed range, including end().
1116 iterator erase(const_iterator first, const_iterator last);
1117
1118 // Gets the arena on which this RepeatedPtrField stores its elements.
1119 inline Arena* GetArena() const;
1120
1121 // For internal use only.
1122 //
1123 // This is public due to it being called by generated code.
1124 void InternalSwap(RepeatedPtrField* other) {
1125 internal::RepeatedPtrFieldBase::InternalSwap(rhs: other);
1126 }
1127
1128 private:
1129 // Note: RepeatedPtrField SHOULD NOT be subclassed by users.
1130 class TypeHandler;
1131
1132 // Internal version of GetArena().
1133 inline Arena* GetOwningArena() const;
1134
1135 // Implementations for ExtractSubrange(). The copying behavior must be
1136 // included only if the type supports the necessary operations (e.g.,
1137 // MergeFrom()), so we must resolve this at compile time. ExtractSubrange()
1138 // uses SFINAE to choose one of the below implementations.
1139 void ExtractSubrangeInternal(int start, int num, Element** elements,
1140 std::true_type);
1141 void ExtractSubrangeInternal(int start, int num, Element** elements,
1142 std::false_type);
1143
1144 friend class Arena;
1145
1146 template <typename T>
1147 friend struct WeakRepeatedPtrField;
1148
1149 typedef void InternalArenaConstructable_;
1150
1151};
1152
1153// -------------------------------------------------------------------
1154
1155template <typename Element>
1156class RepeatedPtrField<Element>::TypeHandler
1157 : public internal::GenericTypeHandler<Element> {};
1158
1159template <>
1160class RepeatedPtrField<std::string>::TypeHandler
1161 : public internal::StringTypeHandler {};
1162
1163template <typename Element>
1164constexpr RepeatedPtrField<Element>::RepeatedPtrField()
1165 : RepeatedPtrFieldBase() {}
1166
1167template <typename Element>
1168inline RepeatedPtrField<Element>::RepeatedPtrField(Arena* arena)
1169 : RepeatedPtrFieldBase(arena) {}
1170
1171template <typename Element>
1172inline RepeatedPtrField<Element>::RepeatedPtrField(
1173 const RepeatedPtrField& other)
1174 : RepeatedPtrFieldBase() {
1175 MergeFrom(other);
1176}
1177
1178template <typename Element>
1179template <typename Iter, typename>
1180inline RepeatedPtrField<Element>::RepeatedPtrField(Iter begin, Iter end) {
1181 Add(begin, end);
1182}
1183
1184template <typename Element>
1185RepeatedPtrField<Element>::~RepeatedPtrField() {
1186#ifdef __cpp_if_constexpr
1187 if constexpr (std::is_base_of<MessageLite, Element>::value) {
1188#else
1189 if (std::is_base_of<MessageLite, Element>::value) {
1190#endif
1191 if (NeedsDestroy()) DestroyProtos();
1192 } else {
1193 Destroy<TypeHandler>();
1194 }
1195}
1196
1197template <typename Element>
1198inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
1199 const RepeatedPtrField& other) {
1200 if (this != &other) CopyFrom(other);
1201 return *this;
1202}
1203
1204template <typename Element>
1205inline RepeatedPtrField<Element>::RepeatedPtrField(
1206 RepeatedPtrField&& other) noexcept
1207 : RepeatedPtrField() {
1208#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
1209 CopyFrom(other);
1210#else // PROTOBUF_FORCE_COPY_IN_MOVE
1211 // We don't just call Swap(&other) here because it would perform 3 copies if
1212 // other is on an arena. This field can't be on an arena because arena
1213 // construction always uses the Arena* accepting constructor.
1214 if (other.GetOwningArena()) {
1215 CopyFrom(other);
1216 } else {
1217 InternalSwap(other: &other);
1218 }
1219#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
1220}
1221
1222template <typename Element>
1223inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
1224 RepeatedPtrField&& other) noexcept {
1225 // We don't just call Swap(&other) here because it would perform 3 copies if
1226 // the two fields are on different arenas.
1227 if (this != &other) {
1228 if (GetOwningArena() != other.GetOwningArena()
1229#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
1230 || GetOwningArena() == nullptr
1231#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
1232 ) {
1233 CopyFrom(other);
1234 } else {
1235 InternalSwap(other: &other);
1236 }
1237 }
1238 return *this;
1239}
1240
1241template <typename Element>
1242inline bool RepeatedPtrField<Element>::empty() const {
1243 return RepeatedPtrFieldBase::empty();
1244}
1245
1246template <typename Element>
1247inline int RepeatedPtrField<Element>::size() const {
1248 return RepeatedPtrFieldBase::size();
1249}
1250
1251template <typename Element>
1252inline const Element& RepeatedPtrField<Element>::Get(int index) const {
1253 return RepeatedPtrFieldBase::Get<TypeHandler>(index);
1254}
1255
1256template <typename Element>
1257inline const Element& RepeatedPtrField<Element>::at(int index) const {
1258 return RepeatedPtrFieldBase::at<TypeHandler>(index);
1259}
1260
1261template <typename Element>
1262inline Element& RepeatedPtrField<Element>::at(int index) {
1263 return RepeatedPtrFieldBase::at<TypeHandler>(index);
1264}
1265
1266
1267template <typename Element>
1268inline Element* RepeatedPtrField<Element>::Mutable(int index) {
1269 return RepeatedPtrFieldBase::Mutable<TypeHandler>(index);
1270}
1271
1272template <typename Element>
1273inline Element* RepeatedPtrField<Element>::Add() {
1274 return RepeatedPtrFieldBase::Add<TypeHandler>();
1275}
1276
1277template <typename Element>
1278inline void RepeatedPtrField<Element>::Add(Element&& value) {
1279 RepeatedPtrFieldBase::Add<TypeHandler>(std::move(value));
1280}
1281
1282template <typename Element>
1283template <typename Iter>
1284inline void RepeatedPtrField<Element>::Add(Iter begin, Iter end) {
1285 if (std::is_base_of<
1286 std::forward_iterator_tag,
1287 typename std::iterator_traits<Iter>::iterator_category>::value) {
1288 int reserve = std::distance(begin, end);
1289 Reserve(new_size: size() + reserve);
1290 }
1291 for (; begin != end; ++begin) {
1292 *Add() = *begin;
1293 }
1294}
1295
1296template <typename Element>
1297inline void RepeatedPtrField<Element>::RemoveLast() {
1298 RepeatedPtrFieldBase::RemoveLast<TypeHandler>();
1299}
1300
1301template <typename Element>
1302inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) {
1303 GOOGLE_DCHECK_GE(start, 0);
1304 GOOGLE_DCHECK_GE(num, 0);
1305 GOOGLE_DCHECK_LE(start + num, size());
1306 for (int i = 0; i < num; ++i) {
1307 RepeatedPtrFieldBase::Delete<TypeHandler>(start + i);
1308 }
1309 UnsafeArenaExtractSubrange(start, num, elements: nullptr);
1310}
1311
1312template <typename Element>
1313inline void RepeatedPtrField<Element>::ExtractSubrange(int start, int num,
1314 Element** elements) {
1315 typename internal::TypeImplementsMergeBehavior<
1316 typename TypeHandler::Type>::type t;
1317 ExtractSubrangeInternal(start, num, elements, t);
1318}
1319
1320// ExtractSubrange() implementation for types that implement merge/copy
1321// behavior.
1322template <typename Element>
1323inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
1324 int start, int num, Element** elements, std::true_type) {
1325 GOOGLE_DCHECK_GE(start, 0);
1326 GOOGLE_DCHECK_GE(num, 0);
1327 GOOGLE_DCHECK_LE(start + num, size());
1328
1329 if (num == 0) return;
1330
1331 GOOGLE_DCHECK_NE(elements, nullptr)
1332 << "Releasing elements without transferring ownership is an unsafe "
1333 "operation. Use UnsafeArenaExtractSubrange.";
1334 if (elements == nullptr) {
1335 CloseGap(start, num);
1336 return;
1337 }
1338
1339 Arena* arena = GetOwningArena();
1340#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
1341 // Always copy.
1342 for (int i = 0; i < num; ++i) {
1343 elements[i] = copy<TypeHandler>(
1344 RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start));
1345 }
1346 if (arena == nullptr) {
1347 for (int i = 0; i < num; ++i) {
1348 delete RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
1349 }
1350 }
1351#else // PROTOBUF_FORCE_COPY_IN_RELEASE
1352 // If we're on an arena, we perform a copy for each element so that the
1353 // returned elements are heap-allocated. Otherwise, just forward it.
1354 if (arena != nullptr) {
1355 for (int i = 0; i < num; ++i) {
1356 elements[i] = copy<TypeHandler>(
1357 RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start));
1358 }
1359 } else {
1360 for (int i = 0; i < num; ++i) {
1361 elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
1362 }
1363 }
1364#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE
1365 CloseGap(start, num);
1366}
1367
1368// ExtractSubrange() implementation for types that do not implement merge/copy
1369// behavior.
1370template <typename Element>
1371inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
1372 int start, int num, Element** elements, std::false_type) {
1373 // This case is identical to UnsafeArenaExtractSubrange(). However, since
1374 // ExtractSubrange() must return heap-allocated objects by contract, and we
1375 // cannot fulfill this contract if we are an on arena, we must GOOGLE_DCHECK() that
1376 // we are not on an arena.
1377 GOOGLE_DCHECK(GetOwningArena() == nullptr)
1378 << "ExtractSubrange() when arena is non-nullptr is only supported when "
1379 << "the Element type supplies a MergeFrom() operation to make copies.";
1380 UnsafeArenaExtractSubrange(start, num, elements);
1381}
1382
1383template <typename Element>
1384inline void RepeatedPtrField<Element>::UnsafeArenaExtractSubrange(
1385 int start, int num, Element** elements) {
1386 GOOGLE_DCHECK_GE(start, 0);
1387 GOOGLE_DCHECK_GE(num, 0);
1388 GOOGLE_DCHECK_LE(start + num, size());
1389
1390 if (num > 0) {
1391 // Save the values of the removed elements if requested.
1392 if (elements != nullptr) {
1393 for (int i = 0; i < num; ++i) {
1394 elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
1395 }
1396 }
1397 CloseGap(start, num);
1398 }
1399}
1400
1401template <typename Element>
1402inline void RepeatedPtrField<Element>::Clear() {
1403 RepeatedPtrFieldBase::Clear<TypeHandler>();
1404}
1405
1406template <typename Element>
1407inline void RepeatedPtrField<Element>::MergeFrom(
1408 const RepeatedPtrField& other) {
1409 RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
1410}
1411
1412template <typename Element>
1413inline void RepeatedPtrField<Element>::CopyFrom(const RepeatedPtrField& other) {
1414 RepeatedPtrFieldBase::CopyFrom<TypeHandler>(other);
1415}
1416
1417template <typename Element>
1418template <typename Iter>
1419inline void RepeatedPtrField<Element>::Assign(Iter begin, Iter end) {
1420 Clear();
1421 Add(begin, end);
1422}
1423
1424template <typename Element>
1425inline typename RepeatedPtrField<Element>::iterator
1426RepeatedPtrField<Element>::erase(const_iterator position) {
1427 return erase(position, position + 1);
1428}
1429
1430template <typename Element>
1431inline typename RepeatedPtrField<Element>::iterator
1432RepeatedPtrField<Element>::erase(const_iterator first, const_iterator last) {
1433 size_type pos_offset = std::distance(cbegin(), first);
1434 size_type last_offset = std::distance(cbegin(), last);
1435 DeleteSubrange(start: pos_offset, num: last_offset - pos_offset);
1436 return begin() + pos_offset;
1437}
1438
1439template <typename Element>
1440inline Element** RepeatedPtrField<Element>::mutable_data() {
1441 return RepeatedPtrFieldBase::mutable_data<TypeHandler>();
1442}
1443
1444template <typename Element>
1445inline const Element* const* RepeatedPtrField<Element>::data() const {
1446 return RepeatedPtrFieldBase::data<TypeHandler>();
1447}
1448
1449template <typename Element>
1450inline void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
1451 if (this == other) return;
1452 RepeatedPtrFieldBase::Swap<TypeHandler>(other);
1453}
1454
1455template <typename Element>
1456inline void RepeatedPtrField<Element>::UnsafeArenaSwap(
1457 RepeatedPtrField* other) {
1458 if (this == other) return;
1459 GOOGLE_DCHECK_EQ(GetOwningArena(), other->GetOwningArena());
1460 RepeatedPtrFieldBase::InternalSwap(rhs: other);
1461}
1462
1463template <typename Element>
1464inline void RepeatedPtrField<Element>::SwapElements(int index1, int index2) {
1465 RepeatedPtrFieldBase::SwapElements(index1, index2);
1466}
1467
1468template <typename Element>
1469inline Arena* RepeatedPtrField<Element>::GetArena() const {
1470 return RepeatedPtrFieldBase::GetArena();
1471}
1472
1473template <typename Element>
1474inline Arena* RepeatedPtrField<Element>::GetOwningArena() const {
1475 return RepeatedPtrFieldBase::GetOwningArena();
1476}
1477
1478template <typename Element>
1479inline size_t RepeatedPtrField<Element>::SpaceUsedExcludingSelfLong() const {
1480 return RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong<TypeHandler>();
1481}
1482
1483template <typename Element>
1484inline void RepeatedPtrField<Element>::AddAllocated(Element* value) {
1485 RepeatedPtrFieldBase::AddAllocated<TypeHandler>(value);
1486}
1487
1488template <typename Element>
1489inline void RepeatedPtrField<Element>::UnsafeArenaAddAllocated(Element* value) {
1490 RepeatedPtrFieldBase::UnsafeArenaAddAllocated<TypeHandler>(value);
1491}
1492
1493template <typename Element>
1494inline Element* RepeatedPtrField<Element>::ReleaseLast() {
1495 return RepeatedPtrFieldBase::ReleaseLast<TypeHandler>();
1496}
1497
1498template <typename Element>
1499inline Element* RepeatedPtrField<Element>::UnsafeArenaReleaseLast() {
1500 return RepeatedPtrFieldBase::UnsafeArenaReleaseLast<TypeHandler>();
1501}
1502
1503template <typename Element>
1504inline int RepeatedPtrField<Element>::ClearedCount() const {
1505 return RepeatedPtrFieldBase::ClearedCount();
1506}
1507
1508#ifndef PROTOBUF_FUTURE_BREAKING_CHANGES
1509template <typename Element>
1510inline void RepeatedPtrField<Element>::AddCleared(Element* value) {
1511 return RepeatedPtrFieldBase::AddCleared<TypeHandler>(value);
1512}
1513
1514template <typename Element>
1515inline Element* RepeatedPtrField<Element>::ReleaseCleared() {
1516 return RepeatedPtrFieldBase::ReleaseCleared<TypeHandler>();
1517}
1518#endif // !PROTOBUF_FUTURE_BREAKING_CHANGES
1519
1520template <typename Element>
1521inline void RepeatedPtrField<Element>::Reserve(int new_size) {
1522 return RepeatedPtrFieldBase::Reserve(new_size);
1523}
1524
1525template <typename Element>
1526inline int RepeatedPtrField<Element>::Capacity() const {
1527 return RepeatedPtrFieldBase::Capacity();
1528}
1529
1530// -------------------------------------------------------------------
1531
1532namespace internal {
1533
1534// STL-like iterator implementation for RepeatedPtrField. You should not
1535// refer to this class directly; use RepeatedPtrField<T>::iterator instead.
1536//
1537// The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is
1538// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors.h,
1539// but adds random-access operators and is modified to wrap a void** base
1540// iterator (since RepeatedPtrField stores its array as a void* array and
1541// casting void** to T** would violate C++ aliasing rules).
1542//
1543// This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin
1544// (jyasskin@google.com).
1545template <typename Element>
1546class RepeatedPtrIterator {
1547 public:
1548 using iterator = RepeatedPtrIterator<Element>;
1549 using iterator_category = std::random_access_iterator_tag;
1550 using value_type = typename std::remove_const<Element>::type;
1551 using difference_type = std::ptrdiff_t;
1552 using pointer = Element*;
1553 using reference = Element&;
1554
1555 RepeatedPtrIterator() : it_(nullptr) {}
1556 explicit RepeatedPtrIterator(void* const* it) : it_(it) {}
1557
1558 // Allows "upcasting" from RepeatedPtrIterator<T**> to
1559 // RepeatedPtrIterator<const T*const*>.
1560 template <typename OtherElement,
1561 typename std::enable_if<std::is_convertible<
1562 OtherElement*, pointer>::value>::type* = nullptr>
1563 RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement>& other)
1564 : it_(other.it_) {}
1565
1566 // dereferenceable
1567 reference operator*() const { return *reinterpret_cast<Element*>(*it_); }
1568 pointer operator->() const { return &(operator*()); }
1569
1570 // {inc,dec}rementable
1571 iterator& operator++() {
1572 ++it_;
1573 return *this;
1574 }
1575 iterator operator++(int) { return iterator(it_++); }
1576 iterator& operator--() {
1577 --it_;
1578 return *this;
1579 }
1580 iterator operator--(int) { return iterator(it_--); }
1581
1582 // equality_comparable
1583 friend bool operator==(const iterator& x, const iterator& y) {
1584 return x.it_ == y.it_;
1585 }
1586 friend bool operator!=(const iterator& x, const iterator& y) {
1587 return x.it_ != y.it_;
1588 }
1589
1590 // less_than_comparable
1591 friend bool operator<(const iterator& x, const iterator& y) {
1592 return x.it_ < y.it_;
1593 }
1594 friend bool operator<=(const iterator& x, const iterator& y) {
1595 return x.it_ <= y.it_;
1596 }
1597 friend bool operator>(const iterator& x, const iterator& y) {
1598 return x.it_ > y.it_;
1599 }
1600 friend bool operator>=(const iterator& x, const iterator& y) {
1601 return x.it_ >= y.it_;
1602 }
1603
1604 // addable, subtractable
1605 iterator& operator+=(difference_type d) {
1606 it_ += d;
1607 return *this;
1608 }
1609 friend iterator operator+(iterator it, const difference_type d) {
1610 it += d;
1611 return it;
1612 }
1613 friend iterator operator+(const difference_type d, iterator it) {
1614 it += d;
1615 return it;
1616 }
1617 iterator& operator-=(difference_type d) {
1618 it_ -= d;
1619 return *this;
1620 }
1621 friend iterator operator-(iterator it, difference_type d) {
1622 it -= d;
1623 return it;
1624 }
1625
1626 // indexable
1627 reference operator[](difference_type d) const { return *(*this + d); }
1628
1629 // random access iterator
1630 friend difference_type operator-(iterator it1, iterator it2) {
1631 return it1.it_ - it2.it_;
1632 }
1633
1634 private:
1635 template <typename OtherElement>
1636 friend class RepeatedPtrIterator;
1637
1638 // The internal iterator.
1639 void* const* it_;
1640};
1641
1642// Provides an iterator that operates on pointers to the underlying objects
1643// rather than the objects themselves as RepeatedPtrIterator does.
1644// Consider using this when working with stl algorithms that change
1645// the array.
1646// The VoidPtr template parameter holds the type-agnostic pointer value
1647// referenced by the iterator. It should either be "void *" for a mutable
1648// iterator, or "const void* const" for a constant iterator.
1649template <typename Element, typename VoidPtr>
1650class RepeatedPtrOverPtrsIterator {
1651 public:
1652 using iterator = RepeatedPtrOverPtrsIterator<Element, VoidPtr>;
1653 using iterator_category = std::random_access_iterator_tag;
1654 using value_type = typename std::remove_const<Element>::type;
1655 using difference_type = std::ptrdiff_t;
1656 using pointer = Element*;
1657 using reference = Element&;
1658
1659 RepeatedPtrOverPtrsIterator() : it_(nullptr) {}
1660 explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {}
1661
1662 // Allows "upcasting" from RepeatedPtrOverPtrsIterator<T**> to
1663 // RepeatedPtrOverPtrsIterator<const T*const*>.
1664 template <
1665 typename OtherElement, typename OtherVoidPtr,
1666 typename std::enable_if<
1667 std::is_convertible<OtherElement*, pointer>::value &&
1668 std::is_convertible<OtherVoidPtr*, VoidPtr>::value>::type* = nullptr>
1669 RepeatedPtrOverPtrsIterator(
1670 const RepeatedPtrOverPtrsIterator<OtherElement, OtherVoidPtr>& other)
1671 : it_(other.it_) {}
1672
1673 // dereferenceable
1674 reference operator*() const { return *reinterpret_cast<Element*>(it_); }
1675 pointer operator->() const { return &(operator*()); }
1676
1677 // {inc,dec}rementable
1678 iterator& operator++() {
1679 ++it_;
1680 return *this;
1681 }
1682 iterator operator++(int) { return iterator(it_++); }
1683 iterator& operator--() {
1684 --it_;
1685 return *this;
1686 }
1687 iterator operator--(int) { return iterator(it_--); }
1688
1689 // equality_comparable
1690 friend bool operator==(const iterator& x, const iterator& y) {
1691 return x.it_ == y.it_;
1692 }
1693 friend bool operator!=(const iterator& x, const iterator& y) {
1694 return x.it_ != y.it_;
1695 }
1696
1697 // less_than_comparable
1698 friend bool operator<(const iterator& x, const iterator& y) {
1699 return x.it_ < y.it_;
1700 }
1701 friend bool operator<=(const iterator& x, const iterator& y) {
1702 return x.it_ <= y.it_;
1703 }
1704 friend bool operator>(const iterator& x, const iterator& y) {
1705 return x.it_ > y.it_;
1706 }
1707 friend bool operator>=(const iterator& x, const iterator& y) {
1708 return x.it_ >= y.it_;
1709 }
1710
1711 // addable, subtractable
1712 iterator& operator+=(difference_type d) {
1713 it_ += d;
1714 return *this;
1715 }
1716 friend iterator operator+(iterator it, difference_type d) {
1717 it += d;
1718 return it;
1719 }
1720 friend iterator operator+(difference_type d, iterator it) {
1721 it += d;
1722 return it;
1723 }
1724 iterator& operator-=(difference_type d) {
1725 it_ -= d;
1726 return *this;
1727 }
1728 friend iterator operator-(iterator it, difference_type d) {
1729 it -= d;
1730 return it;
1731 }
1732
1733 // indexable
1734 reference operator[](difference_type d) const { return *(*this + d); }
1735
1736 // random access iterator
1737 friend difference_type operator-(iterator it1, iterator it2) {
1738 return it1.it_ - it2.it_;
1739 }
1740
1741 private:
1742 template <typename OtherElement, typename OtherVoidPtr>
1743 friend class RepeatedPtrOverPtrsIterator;
1744
1745 // The internal iterator.
1746 VoidPtr* it_;
1747};
1748
1749} // namespace internal
1750
1751template <typename Element>
1752inline typename RepeatedPtrField<Element>::iterator
1753RepeatedPtrField<Element>::begin() {
1754 return iterator(raw_data());
1755}
1756template <typename Element>
1757inline typename RepeatedPtrField<Element>::const_iterator
1758RepeatedPtrField<Element>::begin() const {
1759 return iterator(raw_data());
1760}
1761template <typename Element>
1762inline typename RepeatedPtrField<Element>::const_iterator
1763RepeatedPtrField<Element>::cbegin() const {
1764 return begin();
1765}
1766template <typename Element>
1767inline typename RepeatedPtrField<Element>::iterator
1768RepeatedPtrField<Element>::end() {
1769 return iterator(raw_data() + size());
1770}
1771template <typename Element>
1772inline typename RepeatedPtrField<Element>::const_iterator
1773RepeatedPtrField<Element>::end() const {
1774 return iterator(raw_data() + size());
1775}
1776template <typename Element>
1777inline typename RepeatedPtrField<Element>::const_iterator
1778RepeatedPtrField<Element>::cend() const {
1779 return end();
1780}
1781
1782template <typename Element>
1783inline typename RepeatedPtrField<Element>::pointer_iterator
1784RepeatedPtrField<Element>::pointer_begin() {
1785 return pointer_iterator(raw_mutable_data());
1786}
1787template <typename Element>
1788inline typename RepeatedPtrField<Element>::const_pointer_iterator
1789RepeatedPtrField<Element>::pointer_begin() const {
1790 return const_pointer_iterator(const_cast<const void* const*>(raw_data()));
1791}
1792template <typename Element>
1793inline typename RepeatedPtrField<Element>::pointer_iterator
1794RepeatedPtrField<Element>::pointer_end() {
1795 return pointer_iterator(raw_mutable_data() + size());
1796}
1797template <typename Element>
1798inline typename RepeatedPtrField<Element>::const_pointer_iterator
1799RepeatedPtrField<Element>::pointer_end() const {
1800 return const_pointer_iterator(
1801 const_cast<const void* const*>(raw_data() + size()));
1802}
1803
1804// Iterators and helper functions that follow the spirit of the STL
1805// std::back_insert_iterator and std::back_inserter but are tailor-made
1806// for RepeatedField and RepeatedPtrField. Typical usage would be:
1807//
1808// std::copy(some_sequence.begin(), some_sequence.end(),
1809// RepeatedFieldBackInserter(proto.mutable_sequence()));
1810//
1811// Ported by johannes from util/gtl/proto-array-iterators.h
1812
1813namespace internal {
1814
1815// A back inserter for RepeatedPtrField objects.
1816template <typename T>
1817class RepeatedPtrFieldBackInsertIterator {
1818 public:
1819 using iterator_category = std::output_iterator_tag;
1820 using value_type = T;
1821 using pointer = void;
1822 using reference = void;
1823 using difference_type = std::ptrdiff_t;
1824
1825 RepeatedPtrFieldBackInsertIterator(RepeatedPtrField<T>* const mutable_field)
1826 : field_(mutable_field) {}
1827 RepeatedPtrFieldBackInsertIterator<T>& operator=(const T& value) {
1828 *field_->Add() = value;
1829 return *this;
1830 }
1831 RepeatedPtrFieldBackInsertIterator<T>& operator=(
1832 const T* const ptr_to_value) {
1833 *field_->Add() = *ptr_to_value;
1834 return *this;
1835 }
1836 RepeatedPtrFieldBackInsertIterator<T>& operator=(T&& value) {
1837 *field_->Add() = std::move(value);
1838 return *this;
1839 }
1840 RepeatedPtrFieldBackInsertIterator<T>& operator*() { return *this; }
1841 RepeatedPtrFieldBackInsertIterator<T>& operator++() { return *this; }
1842 RepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) {
1843 return *this;
1844 }
1845
1846 private:
1847 RepeatedPtrField<T>* field_;
1848};
1849
1850// A back inserter for RepeatedPtrFields that inserts by transferring ownership
1851// of a pointer.
1852template <typename T>
1853class AllocatedRepeatedPtrFieldBackInsertIterator {
1854 public:
1855 using iterator_category = std::output_iterator_tag;
1856 using value_type = T;
1857 using pointer = void;
1858 using reference = void;
1859 using difference_type = std::ptrdiff_t;
1860
1861 explicit AllocatedRepeatedPtrFieldBackInsertIterator(
1862 RepeatedPtrField<T>* const mutable_field)
1863 : field_(mutable_field) {}
1864 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=(
1865 T* const ptr_to_value) {
1866 field_->AddAllocated(ptr_to_value);
1867 return *this;
1868 }
1869 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() { return *this; }
1870 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() { return *this; }
1871 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) {
1872 return *this;
1873 }
1874
1875 private:
1876 RepeatedPtrField<T>* field_;
1877};
1878
1879// Almost identical to AllocatedRepeatedPtrFieldBackInsertIterator. This one
1880// uses the UnsafeArenaAddAllocated instead.
1881template <typename T>
1882class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator {
1883 public:
1884 using iterator_category = std::output_iterator_tag;
1885 using value_type = T;
1886 using pointer = void;
1887 using reference = void;
1888 using difference_type = std::ptrdiff_t;
1889
1890 explicit UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator(
1891 RepeatedPtrField<T>* const mutable_field)
1892 : field_(mutable_field) {}
1893 UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=(
1894 T const* const ptr_to_value) {
1895 field_->UnsafeArenaAddAllocated(const_cast<T*>(ptr_to_value));
1896 return *this;
1897 }
1898 UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() {
1899 return *this;
1900 }
1901 UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() {
1902 return *this;
1903 }
1904 UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
1905 int /* unused */) {
1906 return *this;
1907 }
1908
1909 private:
1910 RepeatedPtrField<T>* field_;
1911};
1912
1913} // namespace internal
1914
1915// Provides a back insert iterator for RepeatedPtrField instances,
1916// similar to std::back_inserter().
1917template <typename T>
1918internal::RepeatedPtrFieldBackInsertIterator<T> RepeatedPtrFieldBackInserter(
1919 RepeatedPtrField<T>* const mutable_field) {
1920 return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
1921}
1922
1923// Special back insert iterator for RepeatedPtrField instances, just in
1924// case someone wants to write generic template code that can access both
1925// RepeatedFields and RepeatedPtrFields using a common name.
1926template <typename T>
1927internal::RepeatedPtrFieldBackInsertIterator<T> RepeatedFieldBackInserter(
1928 RepeatedPtrField<T>* const mutable_field) {
1929 return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
1930}
1931
1932// Provides a back insert iterator for RepeatedPtrField instances
1933// similar to std::back_inserter() which transfers the ownership while
1934// copying elements.
1935template <typename T>
1936internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>
1937AllocatedRepeatedPtrFieldBackInserter(
1938 RepeatedPtrField<T>* const mutable_field) {
1939 return internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>(
1940 mutable_field);
1941}
1942
1943// Similar to AllocatedRepeatedPtrFieldBackInserter, using
1944// UnsafeArenaAddAllocated instead of AddAllocated.
1945// This is slightly faster if that matters. It is also useful in legacy code
1946// that uses temporary ownership to avoid copies. Example:
1947// RepeatedPtrField<T> temp_field;
1948// temp_field.UnsafeArenaAddAllocated(new T);
1949// ... // Do something with temp_field
1950// temp_field.UnsafeArenaExtractSubrange(0, temp_field.size(), nullptr);
1951// Putting temp_field on the arena fails because the ownership transfers to the
1952// arena at the "AddAllocated" call and is not released anymore causing a
1953// double delete. This function uses UnsafeArenaAddAllocated to prevent this.
1954template <typename T>
1955internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>
1956UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
1957 RepeatedPtrField<T>* const mutable_field) {
1958 return internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>(
1959 mutable_field);
1960}
1961
1962extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE
1963 RepeatedPtrField<std::string>;
1964
1965} // namespace protobuf
1966} // namespace google
1967
1968#include <google/protobuf/port_undef.inc>
1969
1970#endif // GOOGLE_PROTOBUF_REPEATED_PTR_FIELD_H__
1971