Coverage Report

Created: 2024-07-27 06:53

/src/LPM/external.protobuf/include/google/protobuf/repeated_field.h
Line
Count
Source (jump to first uncovered line)
1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc.  All rights reserved.
3
//
4
// Use of this source code is governed by a BSD-style
5
// license that can be found in the LICENSE file or at
6
// https://developers.google.com/open-source/licenses/bsd
7
8
// Author: kenton@google.com (Kenton Varda)
9
//  Based on original Protocol Buffers design by
10
//  Sanjay Ghemawat, Jeff Dean, and others.
11
//
12
// RepeatedField and RepeatedPtrField are used by generated protocol message
13
// classes to manipulate repeated fields.  These classes are very similar to
14
// STL's vector, but include a number of optimizations found to be useful
15
// specifically in the case of Protocol Buffers.  RepeatedPtrField is
16
// particularly different from STL vector as it manages ownership of the
17
// pointers that it contains.
18
//
19
// This header covers RepeatedField.
20
21
#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__
22
#define GOOGLE_PROTOBUF_REPEATED_FIELD_H__
23
24
#include <algorithm>
25
#include <cstddef>
26
#include <iterator>
27
#include <limits>
28
#include <memory>
29
#include <string>
30
#include <type_traits>
31
#include <utility>
32
33
#include "absl/base/attributes.h"
34
#include "absl/base/dynamic_annotations.h"
35
#include "absl/base/optimization.h"
36
#include "absl/log/absl_check.h"
37
#include "absl/log/absl_log.h"
38
#include "absl/meta/type_traits.h"
39
#include "absl/strings/cord.h"
40
#include "google/protobuf/arena.h"
41
#include "google/protobuf/generated_enum_util.h"
42
#include "google/protobuf/internal_visibility.h"
43
#include "google/protobuf/message_lite.h"
44
#include "google/protobuf/port.h"
45
#include "google/protobuf/repeated_ptr_field.h"
46
47
48
// Must be included last.
49
#include "google/protobuf/port_def.inc"
50
51
#ifdef SWIG
52
#error "You cannot SWIG proto headers"
53
#endif
54
55
namespace google {
56
namespace protobuf {
57
58
class Message;
59
60
namespace internal {
61
62
template <typename T, int kRepHeaderSize>
63
0
constexpr int RepeatedFieldLowerClampLimit() {
64
0
  // The header is padded to be at least `sizeof(T)` when it would be smaller
65
0
  // otherwise.
66
0
  static_assert(sizeof(T) <= kRepHeaderSize, "");
67
0
  // We want to pad the minimum size to be a power of two bytes, including the
68
0
  // header.
69
0
  // The first allocation is kRepHeaderSize bytes worth of elements for a total
70
0
  // of 2*kRepHeaderSize bytes.
71
0
  // For an 8-byte header, we allocate 8 bool, 2 ints, or 1 int64.
72
0
  return kRepHeaderSize / sizeof(T);
73
0
}
Unexecuted instantiation: int google::protobuf::internal::RepeatedFieldLowerClampLimit<unsigned int, 8>()
Unexecuted instantiation: int google::protobuf::internal::RepeatedFieldLowerClampLimit<unsigned long, 8>()
Unexecuted instantiation: int google::protobuf::internal::RepeatedFieldLowerClampLimit<long, 8>()
Unexecuted instantiation: int google::protobuf::internal::RepeatedFieldLowerClampLimit<float, 8>()
Unexecuted instantiation: int google::protobuf::internal::RepeatedFieldLowerClampLimit<double, 8>()
Unexecuted instantiation: int google::protobuf::internal::RepeatedFieldLowerClampLimit<int, 8>()
74
75
// kRepeatedFieldUpperClampLimit is the lowest signed integer value that
76
// overflows when multiplied by 2 (which is undefined behavior). Sizes above
77
// this will clamp to the maximum int value instead of following exponential
78
// growth when growing a repeated field.
79
constexpr int kRepeatedFieldUpperClampLimit =
80
    (std::numeric_limits<int>::max() / 2) + 1;
81
82
template <typename Element>
83
class RepeatedIterator;
84
85
// Sentinel base class.
86
struct RepeatedFieldBase {};
87
88
// We can't skip the destructor for, e.g., arena allocated RepeatedField<Cord>.
89
template <typename Element,
90
          bool Trivial = Arena::is_destructor_skippable<Element>::value>
91
struct RepeatedFieldDestructorSkippableBase : RepeatedFieldBase {};
92
93
template <typename Element>
94
struct RepeatedFieldDestructorSkippableBase<Element, true> : RepeatedFieldBase {
95
  using DestructorSkippable_ = void;
96
};
97
98
}  // namespace internal
99
100
// RepeatedField is used to represent repeated fields of a primitive type (in
101
// other words, everything except strings and nested Messages).  Most users will
102
// not ever use a RepeatedField directly; they will use the get-by-index,
103
// set-by-index, and add accessors that are generated for all repeated fields.
104
// Actually, in addition to primitive types, we use RepeatedField for repeated
105
// Cords, because the Cord class is in fact just a reference-counted pointer.
106
// We have to specialize several methods in the Cord case to get the memory
107
// management right; e.g. swapping when appropriate, etc.
108
template <typename Element>
109
class RepeatedField final
110
    : private internal::RepeatedFieldDestructorSkippableBase<Element> {
111
  static_assert(
112
      alignof(Arena) >= alignof(Element),
113
      "We only support types that have an alignment smaller than Arena");
114
  static_assert(!std::is_const<Element>::value,
115
                "We do not support const value types.");
116
  static_assert(!std::is_volatile<Element>::value,
117
                "We do not support volatile value types.");
118
  static_assert(!std::is_pointer<Element>::value,
119
                "We do not support pointer value types.");
120
  static_assert(!std::is_reference<Element>::value,
121
                "We do not support reference value types.");
122
  static constexpr PROTOBUF_ALWAYS_INLINE void StaticValidityCheck() {
123
    static_assert(
124
        absl::disjunction<internal::is_supported_integral_type<Element>,
125
                          internal::is_supported_floating_point_type<Element>,
126
                          std::is_same<absl::Cord, Element>,
127
                          is_proto_enum<Element>>::value,
128
        "We only support non-string scalars in RepeatedField.");
129
  }
130
131
 public:
132
  using value_type = Element;
133
  using size_type = int;
134
  using difference_type = ptrdiff_t;
135
  using reference = Element&;
136
  using const_reference = const Element&;
137
  using pointer = Element*;
138
  using const_pointer = const Element*;
139
  using iterator = internal::RepeatedIterator<Element>;
140
  using const_iterator = internal::RepeatedIterator<const Element>;
141
  using reverse_iterator = std::reverse_iterator<iterator>;
142
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
143
144
  constexpr RepeatedField();
145
  RepeatedField(const RepeatedField& rhs) : RepeatedField(nullptr, rhs) {}
146
147
  // TODO: make this constructor private
148
  explicit RepeatedField(Arena* arena);
149
150
  template <typename Iter,
151
            typename = typename std::enable_if<std::is_constructible<
152
                Element, decltype(*std::declval<Iter>())>::value>::type>
153
  RepeatedField(Iter begin, Iter end);
154
155
  // Arena enabled constructors: for internal use only.
156
  RepeatedField(internal::InternalVisibility, Arena* arena)
157
      : RepeatedField(arena) {}
158
  RepeatedField(internal::InternalVisibility, Arena* arena,
159
                const RepeatedField& rhs)
160
      : RepeatedField(arena, rhs) {}
161
162
  RepeatedField& operator=(const RepeatedField& other)
163
      ABSL_ATTRIBUTE_LIFETIME_BOUND;
164
165
  RepeatedField(RepeatedField&& rhs) noexcept
166
      : RepeatedField(nullptr, std::move(rhs)) {}
167
  RepeatedField& operator=(RepeatedField&& other) noexcept
168
      ABSL_ATTRIBUTE_LIFETIME_BOUND;
169
170
  ~RepeatedField();
171
172
  bool empty() const;
173
  int size() const;
174
175
  const_reference Get(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
176
  pointer Mutable(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND;
177
178
  const_reference operator[](int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
179
    return Get(index);
180
  }
181
  reference operator[](int index) ABSL_ATTRIBUTE_LIFETIME_BOUND {
182
    return *Mutable(index);
183
  }
184
185
  const_reference at(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
186
  reference at(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND;
187
188
  void Set(int index, const Element& value);
189
  void Add(Element value);
190
191
  // Appends a new element and returns a pointer to it.
192
  // The new element is uninitialized if |Element| is a POD type.
193
  pointer Add() ABSL_ATTRIBUTE_LIFETIME_BOUND;
194
  // Appends elements in the range [begin, end) after reserving
195
  // the appropriate number of elements.
196
  template <typename Iter>
197
  void Add(Iter begin, Iter end);
198
199
  // Removes the last element in the array.
200
  void RemoveLast();
201
202
  // Extracts elements with indices in "[start .. start+num-1]".
203
  // Copies them into "elements[0 .. num-1]" if "elements" is not nullptr.
204
  // Caution: also moves elements with indices [start+num ..].
205
  // Calling this routine inside a loop can cause quadratic behavior.
206
  void ExtractSubrange(int start, int num, Element* elements);
207
208
  ABSL_ATTRIBUTE_REINITIALIZES void Clear();
209
  void MergeFrom(const RepeatedField& other);
210
  ABSL_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedField& other);
211
212
  // Replaces the contents with RepeatedField(begin, end).
213
  template <typename Iter>
214
  ABSL_ATTRIBUTE_REINITIALIZES void Assign(Iter begin, Iter end);
215
216
  // Reserves space to expand the field to at least the given size.  If the
217
  // array is grown, it will always be at least doubled in size.
218
  void Reserve(int new_size);
219
220
  // Resizes the RepeatedField to a new, smaller size.  This is O(1).
221
  // Except for RepeatedField<Cord>, for which it is O(size-new_size).
222
  void Truncate(int new_size);
223
224
  void AddAlreadyReserved(Element value);
225
  int Capacity() const;
226
227
  // Adds `n` elements to this instance asserting there is enough capacity.
228
  // The added elements are uninitialized if `Element` is trivial.
229
  pointer AddAlreadyReserved() ABSL_ATTRIBUTE_LIFETIME_BOUND;
230
  pointer AddNAlreadyReserved(int n) ABSL_ATTRIBUTE_LIFETIME_BOUND;
231
232
  // Like STL resize.  Uses value to fill appended elements.
233
  // Like Truncate() if new_size <= size(), otherwise this is
234
  // O(new_size - size()).
235
  void Resize(size_type new_size, const Element& value);
236
237
  // Gets the underlying array.  This pointer is possibly invalidated by
238
  // any add or remove operation.
239
  pointer mutable_data() ABSL_ATTRIBUTE_LIFETIME_BOUND;
240
  const_pointer data() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
241
242
  // Swaps entire contents with "other". If they are separate arenas, then
243
  // copies data between each other.
244
  void Swap(RepeatedField* other);
245
246
  // Swaps two elements.
247
  void SwapElements(int index1, int index2);
248
249
  iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND;
250
  const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
251
  const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
252
  iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND;
253
  const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
254
  const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
255
256
  // Reverse iterator support
257
  reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
258
    return reverse_iterator(end());
259
  }
260
  const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
261
    return const_reverse_iterator(end());
262
  }
263
  reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND {
264
    return reverse_iterator(begin());
265
  }
266
  const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
267
    return const_reverse_iterator(begin());
268
  }
269
270
  // Returns the number of bytes used by the repeated field, excluding
271
  // sizeof(*this)
272
  size_t SpaceUsedExcludingSelfLong() const;
273
274
  int SpaceUsedExcludingSelf() const {
275
    return internal::ToIntSize(SpaceUsedExcludingSelfLong());
276
  }
277
278
  // Removes the element referenced by position.
279
  //
280
  // Returns an iterator to the element immediately following the removed
281
  // element.
282
  //
283
  // Invalidates all iterators at or after the removed element, including end().
284
  iterator erase(const_iterator position) ABSL_ATTRIBUTE_LIFETIME_BOUND;
285
286
  // Removes the elements in the range [first, last).
287
  //
288
  // Returns an iterator to the element immediately following the removed range.
289
  //
290
  // Invalidates all iterators at or after the removed range, including end().
291
  iterator erase(const_iterator first,
292
                 const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND;
293
294
  // Gets the Arena on which this RepeatedField stores its elements.
295
  // Note: this can be inaccurate for split default fields so we make this
296
  // function non-const.
297
0
  inline Arena* GetArena() {
298
0
    return (total_size_ == 0) ? static_cast<Arena*>(arena_or_elements_)
299
0
                              : rep()->arena;
300
0
  }
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::GetArena()
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::GetArena()
Unexecuted instantiation: google::protobuf::RepeatedField<long>::GetArena()
Unexecuted instantiation: google::protobuf::RepeatedField<float>::GetArena()
Unexecuted instantiation: google::protobuf::RepeatedField<double>::GetArena()
Unexecuted instantiation: google::protobuf::RepeatedField<int>::GetArena()
301
302
  // For internal use only.
303
  //
304
  // This is public due to it being called by generated code.
305
  inline void InternalSwap(RepeatedField* other);
306
307
 private:
308
  using InternalArenaConstructable_ = void;
309
310
  template <typename T>
311
  friend class Arena::InternalHelper;
312
313
  friend class Arena;
314
315
  // Pad the rep to being max(Arena*, Element) with a minimum align
316
  // of 8 as sanitizers are picky on the alignment of containers to
317
  // start at 8 byte offsets even when compiling for 32 bit platforms.
318
  struct Rep {
319
    union {
320
      alignas(8) Arena* arena;
321
      Element unused;
322
    };
323
0
    Element* elements() { return reinterpret_cast<Element*>(this + 1); }
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::Rep::elements()
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::Rep::elements()
Unexecuted instantiation: google::protobuf::RepeatedField<long>::Rep::elements()
Unexecuted instantiation: google::protobuf::RepeatedField<float>::Rep::elements()
Unexecuted instantiation: google::protobuf::RepeatedField<double>::Rep::elements()
Unexecuted instantiation: google::protobuf::RepeatedField<int>::Rep::elements()
324
325
    // Avoid 'implicitly deleted dtor' warnings on certain compilers.
326
    ~Rep() = delete;
327
  };
328
329
  static constexpr int kInitialSize = 0;
330
  static PROTOBUF_CONSTEXPR const size_t kRepHeaderSize = sizeof(Rep);
331
332
  RepeatedField(Arena* arena, const RepeatedField& rhs);
333
  RepeatedField(Arena* arena, RepeatedField&& rhs);
334
335
336
  // Swaps entire contents with "other". Should be called only if the caller can
337
  // guarantee that both repeated fields are on the same arena or are on the
338
  // heap. Swapping between different arenas is disallowed and caught by a
339
  // ABSL_DCHECK (see API docs for details).
340
  void UnsafeArenaSwap(RepeatedField* other);
341
342
  // Copy constructs `n` instances in place into the array `dst`.
343
  // This function is identical to `std::uninitialized_copy_n(src, n, dst)`
344
  // except that we explicit declare the memory to not be aliased, which will
345
  // result in `memcpy` code generation instead of `memmove` for trivial types.
346
  static inline void UninitializedCopyN(const Element* PROTOBUF_RESTRICT src,
347
                                        int n, Element* PROTOBUF_RESTRICT dst) {
348
    std::uninitialized_copy_n(src, n, dst);
349
  }
350
351
  // Copy constructs `[begin, end)` instances in place into the array `dst`.
352
  // See above `UninitializedCopyN()` function comments for more information.
353
  template <typename Iter>
354
  static inline void UninitializedCopy(Iter begin, Iter end,
355
                                       Element* PROTOBUF_RESTRICT dst) {
356
    std::uninitialized_copy(begin, end, dst);
357
  }
358
359
  // Destroys all elements in [begin, end).
360
  // This function does nothing if `Element` is trivial.
361
0
  static void Destroy(const Element* begin, const Element* end) {
362
0
    if (!std::is_trivial<Element>::value) {
363
0
      std::for_each(begin, end, [&](const Element& e) { e.~Element(); });
364
0
    }
365
0
  }
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::Destroy(unsigned int const*, unsigned int const*)
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::Destroy(unsigned long const*, unsigned long const*)
Unexecuted instantiation: google::protobuf::RepeatedField<int>::Destroy(int const*, int const*)
Unexecuted instantiation: google::protobuf::RepeatedField<long>::Destroy(long const*, long const*)
Unexecuted instantiation: google::protobuf::RepeatedField<float>::Destroy(float const*, float const*)
Unexecuted instantiation: google::protobuf::RepeatedField<double>::Destroy(double const*, double const*)
366
367
  template <typename Iter>
368
  void AddForwardIterator(Iter begin, Iter end);
369
370
  template <typename Iter>
371
  void AddInputIterator(Iter begin, Iter end);
372
373
  // Reserves space to expand the field to at least the given size.
374
  // If the array is grown, it will always be at least doubled in size.
375
  // If `annotate_size` is true (the default), then this function will annotate
376
  // the old container from `current_size` to `total_size_` (unpoison memory)
377
  // directly before it is being released, and annotate the new container from
378
  // `total_size_` to `current_size` (poison unused memory).
379
  void Grow(int current_size, int new_size);
380
  void GrowNoAnnotate(int current_size, int new_size);
381
382
  // Annotates a change in size of this instance. This function should be called
383
  // with (total_size, current_size) after new memory has been allocated and
384
  // filled from previous memory), and called with (current_size, total_size)
385
  // right before (previously annotated) memory is released.
386
0
  void AnnotateSize(int old_size, int new_size) const {
387
0
    if (old_size != new_size) {
388
0
      ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(
389
0
          unsafe_elements(), unsafe_elements() + total_size_,
390
0
          unsafe_elements() + old_size, unsafe_elements() + new_size);
391
0
      if (new_size < old_size) {
392
0
        ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(
393
0
            unsafe_elements() + new_size,
394
0
            (old_size - new_size) * sizeof(Element));
395
0
      }
396
0
    }
397
0
  }
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::AnnotateSize(int, int) const
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::AnnotateSize(int, int) const
Unexecuted instantiation: google::protobuf::RepeatedField<int>::AnnotateSize(int, int) const
Unexecuted instantiation: google::protobuf::RepeatedField<long>::AnnotateSize(int, int) const
Unexecuted instantiation: google::protobuf::RepeatedField<float>::AnnotateSize(int, int) const
Unexecuted instantiation: google::protobuf::RepeatedField<double>::AnnotateSize(int, int) const
398
399
  // Replaces current_size_ with new_size and returns the previous value of
400
  // current_size_. This function is intended to be the only place where
401
  // current_size_ is modified, with the exception of `AddInputIterator()`
402
  // where the size of added items is not known in advance.
403
0
  inline int ExchangeCurrentSize(int new_size) {
404
0
    const int prev_size = current_size_;
405
0
    AnnotateSize(prev_size, new_size);
406
0
    current_size_ = new_size;
407
0
    return prev_size;
408
0
  }
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::ExchangeCurrentSize(int)
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::ExchangeCurrentSize(int)
Unexecuted instantiation: google::protobuf::RepeatedField<int>::ExchangeCurrentSize(int)
Unexecuted instantiation: google::protobuf::RepeatedField<long>::ExchangeCurrentSize(int)
Unexecuted instantiation: google::protobuf::RepeatedField<float>::ExchangeCurrentSize(int)
Unexecuted instantiation: google::protobuf::RepeatedField<double>::ExchangeCurrentSize(int)
409
410
  // Returns a pointer to elements array.
411
  // pre-condition: the array must have been allocated.
412
0
  Element* elements() const {
413
0
    ABSL_DCHECK_GT(total_size_, 0);
414
0
    // Because of above pre-condition this cast is safe.
415
0
    return unsafe_elements();
416
0
  }
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<int>::elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<long>::elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<float>::elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<double>::elements() const
417
418
  // Returns a pointer to elements array if it exists; otherwise either null or
419
  // an invalid pointer is returned. This only happens for empty repeated
420
  // fields, where you can't dereference this pointer anyway (it's empty).
421
0
  Element* unsafe_elements() const {
422
0
    return static_cast<Element*>(arena_or_elements_);
423
0
  }
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::unsafe_elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::unsafe_elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<int>::unsafe_elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<long>::unsafe_elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<float>::unsafe_elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<double>::unsafe_elements() const
Unexecuted instantiation: google::protobuf::RepeatedField<bool>::unsafe_elements() const
424
425
  // Returns a pointer to the Rep struct.
426
  // pre-condition: the Rep must have been allocated, ie elements() is safe.
427
0
  Rep* rep() const {
428
0
    return reinterpret_cast<Rep*>(reinterpret_cast<char*>(elements()) -
429
0
                                  kRepHeaderSize);
430
0
  }
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::rep() const
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::rep() const
Unexecuted instantiation: google::protobuf::RepeatedField<long>::rep() const
Unexecuted instantiation: google::protobuf::RepeatedField<float>::rep() const
Unexecuted instantiation: google::protobuf::RepeatedField<double>::rep() const
Unexecuted instantiation: google::protobuf::RepeatedField<int>::rep() const
431
432
  // Internal helper to delete all elements and deallocate the storage.
433
  template <bool in_destructor = false>
434
0
  void InternalDeallocate() {
435
0
    const size_t bytes = total_size_ * sizeof(Element) + kRepHeaderSize;
436
0
    if (rep()->arena == nullptr) {
437
0
      internal::SizedDelete(rep(), bytes);
438
0
    } else if (!in_destructor) {
439
0
      // If we are in the destructor, we might be being destroyed as part of
440
0
      // the arena teardown. We can't try and return blocks to the arena then.
441
0
      rep()->arena->ReturnArrayMemory(rep(), bytes);
442
0
    }
443
0
  }
Unexecuted instantiation: void google::protobuf::RepeatedField<unsigned int>::InternalDeallocate<false>()
Unexecuted instantiation: void google::protobuf::RepeatedField<unsigned long>::InternalDeallocate<false>()
Unexecuted instantiation: void google::protobuf::RepeatedField<long>::InternalDeallocate<false>()
Unexecuted instantiation: void google::protobuf::RepeatedField<float>::InternalDeallocate<false>()
Unexecuted instantiation: void google::protobuf::RepeatedField<double>::InternalDeallocate<false>()
Unexecuted instantiation: void google::protobuf::RepeatedField<int>::InternalDeallocate<false>()
444
445
  // A note on the representation here (see also comment below for
446
  // RepeatedPtrFieldBase's struct Rep):
447
  //
448
  // We maintain the same sizeof(RepeatedField) as before we added arena support
449
  // so that we do not degrade performance by bloating memory usage. Directly
450
  // adding an arena_ element to RepeatedField is quite costly. By using
451
  // indirection in this way, we keep the same size when the RepeatedField is
452
  // empty (common case), and add only an 8-byte header to the elements array
453
  // when non-empty. We make sure to place the size fields directly in the
454
  // RepeatedField class to avoid costly cache misses due to the indirection.
455
  int current_size_;
456
  int total_size_;
457
  // If total_size_ == 0 this points to an Arena otherwise it points to the
458
  // elements member of a Rep struct. Using this invariant allows the storage of
459
  // the arena pointer without an extra allocation in the constructor.
460
  void* arena_or_elements_;
461
};
462
463
// implementation ====================================================
464
465
template <typename Element>
466
constexpr RepeatedField<Element>::RepeatedField()
467
    : current_size_(0), total_size_(0), arena_or_elements_(nullptr) {
468
  StaticValidityCheck();
469
}
470
471
template <typename Element>
472
inline RepeatedField<Element>::RepeatedField(Arena* arena)
473
    : current_size_(0), total_size_(0), arena_or_elements_(arena) {
474
  StaticValidityCheck();
475
}
476
477
template <typename Element>
478
inline RepeatedField<Element>::RepeatedField(Arena* arena,
479
                                             const RepeatedField& rhs)
480
    : current_size_(0), total_size_(0), arena_or_elements_(arena) {
481
  StaticValidityCheck();
482
  if (auto size = rhs.current_size_) {
483
    Grow(0, size);
484
    ExchangeCurrentSize(size);
485
    UninitializedCopyN(rhs.elements(), size, unsafe_elements());
486
  }
487
}
488
489
template <typename Element>
490
template <typename Iter, typename>
491
RepeatedField<Element>::RepeatedField(Iter begin, Iter end)
492
    : current_size_(0), total_size_(0), arena_or_elements_(nullptr) {
493
  StaticValidityCheck();
494
  Add(begin, end);
495
}
496
497
template <typename Element>
498
RepeatedField<Element>::~RepeatedField() {
499
  StaticValidityCheck();
500
#ifndef NDEBUG
501
  // Try to trigger segfault / asan failure in non-opt builds if arena_
502
  // lifetime has ended before the destructor.
503
  auto arena = GetArena();
504
  if (arena) (void)arena->SpaceAllocated();
505
#endif
506
  if (total_size_ > 0) {
507
    Destroy(unsafe_elements(), unsafe_elements() + current_size_);
508
    InternalDeallocate<true>();
509
  }
510
}
511
512
template <typename Element>
513
inline RepeatedField<Element>& RepeatedField<Element>::operator=(
514
    const RepeatedField& other) ABSL_ATTRIBUTE_LIFETIME_BOUND {
515
  if (this != &other) CopyFrom(other);
516
  return *this;
517
}
518
519
template <typename Element>
520
inline RepeatedField<Element>::RepeatedField(Arena* arena, RepeatedField&& rhs)
521
    : RepeatedField(arena) {
522
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
523
  CopyFrom(rhs);
524
#else   // PROTOBUF_FORCE_COPY_IN_MOVE
525
  // We don't just call Swap(&rhs) here because it would perform 3 copies if rhs
526
  // is on a different arena.
527
  if (arena != rhs.GetArena()) {
528
    CopyFrom(rhs);
529
  } else {
530
    InternalSwap(&rhs);
531
  }
532
#endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
533
}
534
535
template <typename Element>
536
inline RepeatedField<Element>& RepeatedField<Element>::operator=(
537
    RepeatedField&& other) noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
538
  // We don't just call Swap(&other) here because it would perform 3 copies if
539
  // the two fields are on different arenas.
540
  if (this != &other) {
541
    if (GetArena() != other.GetArena()
542
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
543
        || GetArena() == nullptr
544
#endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
545
    ) {
546
      CopyFrom(other);
547
    } else {
548
      InternalSwap(&other);
549
    }
550
  }
551
  return *this;
552
}
553
554
template <typename Element>
555
inline bool RepeatedField<Element>::empty() const {
556
  return current_size_ == 0;
557
}
558
559
template <typename Element>
560
0
inline int RepeatedField<Element>::size() const {
561
0
  return current_size_;
562
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::size() const
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::size() const
Unexecuted instantiation: google::protobuf::RepeatedField<long>::size() const
Unexecuted instantiation: google::protobuf::RepeatedField<float>::size() const
Unexecuted instantiation: google::protobuf::RepeatedField<double>::size() const
Unexecuted instantiation: google::protobuf::RepeatedField<bool>::size() const
Unexecuted instantiation: google::protobuf::RepeatedField<int>::size() const
563
564
template <typename Element>
565
0
inline int RepeatedField<Element>::Capacity() const {
566
0
  return total_size_;
567
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::Capacity() const
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::Capacity() const
Unexecuted instantiation: google::protobuf::RepeatedField<int>::Capacity() const
Unexecuted instantiation: google::protobuf::RepeatedField<long>::Capacity() const
Unexecuted instantiation: google::protobuf::RepeatedField<float>::Capacity() const
Unexecuted instantiation: google::protobuf::RepeatedField<double>::Capacity() const
568
569
template <typename Element>
570
0
inline void RepeatedField<Element>::AddAlreadyReserved(Element value) {
571
0
  ABSL_DCHECK_LT(current_size_, total_size_);
572
0
  void* p = elements() + ExchangeCurrentSize(current_size_ + 1);
573
0
  ::new (p) Element(std::move(value));
574
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::AddAlreadyReserved(unsigned int)
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::AddAlreadyReserved(unsigned long)
Unexecuted instantiation: google::protobuf::RepeatedField<int>::AddAlreadyReserved(int)
Unexecuted instantiation: google::protobuf::RepeatedField<long>::AddAlreadyReserved(long)
Unexecuted instantiation: google::protobuf::RepeatedField<float>::AddAlreadyReserved(float)
Unexecuted instantiation: google::protobuf::RepeatedField<double>::AddAlreadyReserved(double)
575
576
template <typename Element>
577
inline Element* RepeatedField<Element>::AddAlreadyReserved()
578
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
579
  ABSL_DCHECK_LT(current_size_, total_size_);
580
  // new (p) <TrivialType> compiles into nothing: this is intentional as this
581
  // function is documented to return uninitialized data for trivial types.
582
  void* p = elements() + ExchangeCurrentSize(current_size_ + 1);
583
  return ::new (p) Element;
584
}
585
586
template <typename Element>
587
inline Element* RepeatedField<Element>::AddNAlreadyReserved(int n)
588
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
589
  ABSL_DCHECK_GE(total_size_ - current_size_, n)
590
      << total_size_ << ", " << current_size_;
591
  Element* p = unsafe_elements() + ExchangeCurrentSize(current_size_ + n);
592
  for (Element *begin = p, *end = p + n; begin != end; ++begin) {
593
    new (static_cast<void*>(begin)) Element;
594
  }
595
  return p;
596
}
597
598
template <typename Element>
599
0
inline void RepeatedField<Element>::Resize(int new_size, const Element& value) {
600
0
  ABSL_DCHECK_GE(new_size, 0);
601
0
  if (new_size > current_size_) {
602
0
    if (new_size > total_size_) Grow(current_size_, new_size);
603
0
    Element* first = elements() + ExchangeCurrentSize(new_size);
604
0
    std::uninitialized_fill(first, elements() + current_size_, value);
605
0
  } else if (new_size < current_size_) {
606
0
    Destroy(unsafe_elements() + new_size, unsafe_elements() + current_size_);
607
0
    ExchangeCurrentSize(new_size);
608
0
  }
609
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::Resize(int, unsigned int const&)
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::Resize(int, unsigned long const&)
Unexecuted instantiation: google::protobuf::RepeatedField<int>::Resize(int, int const&)
Unexecuted instantiation: google::protobuf::RepeatedField<long>::Resize(int, long const&)
Unexecuted instantiation: google::protobuf::RepeatedField<float>::Resize(int, float const&)
Unexecuted instantiation: google::protobuf::RepeatedField<double>::Resize(int, double const&)
610
611
template <typename Element>
612
inline const Element& RepeatedField<Element>::Get(int index) const
613
0
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
614
0
  ABSL_DCHECK_GE(index, 0);
615
0
  ABSL_DCHECK_LT(index, current_size_);
616
0
  return elements()[index];
617
0
}
618
619
template <typename Element>
620
inline const Element& RepeatedField<Element>::at(int index) const
621
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
622
  ABSL_CHECK_GE(index, 0);
623
  ABSL_CHECK_LT(index, current_size_);
624
  return elements()[index];
625
}
626
627
template <typename Element>
628
inline Element& RepeatedField<Element>::at(int index)
629
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
630
  ABSL_CHECK_GE(index, 0);
631
  ABSL_CHECK_LT(index, current_size_);
632
  return elements()[index];
633
}
634
635
template <typename Element>
636
inline Element* RepeatedField<Element>::Mutable(int index)
637
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
638
  ABSL_DCHECK_GE(index, 0);
639
  ABSL_DCHECK_LT(index, current_size_);
640
  return &elements()[index];
641
}
642
643
template <typename Element>
644
0
inline void RepeatedField<Element>::Set(int index, const Element& value) {
645
0
  ABSL_DCHECK_GE(index, 0);
646
0
  ABSL_DCHECK_LT(index, current_size_);
647
0
  elements()[index] = value;
648
0
}
649
650
template <typename Element>
651
0
inline void RepeatedField<Element>::Add(Element value) {
652
0
  int total_size = total_size_;
653
0
  Element* elem = unsafe_elements();
654
0
  if (ABSL_PREDICT_FALSE(current_size_ == total_size)) {
655
0
    Grow(current_size_, current_size_ + 1);
656
0
    total_size = total_size_;
657
0
    elem = unsafe_elements();
658
0
  }
659
0
  int new_size = current_size_ + 1;
660
0
  void* p = elem + ExchangeCurrentSize(new_size);
661
0
  ::new (p) Element(std::move(value));
662
0
663
0
  // The below helps the compiler optimize dense loops.
664
0
  ABSL_ASSUME(new_size == current_size_);
665
0
  ABSL_ASSUME(elem == arena_or_elements_);
666
0
  ABSL_ASSUME(total_size == total_size_);
667
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::Add(unsigned int)
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::Add(unsigned long)
Unexecuted instantiation: google::protobuf::RepeatedField<long>::Add(long)
Unexecuted instantiation: google::protobuf::RepeatedField<float>::Add(float)
Unexecuted instantiation: google::protobuf::RepeatedField<double>::Add(double)
Unexecuted instantiation: google::protobuf::RepeatedField<int>::Add(int)
668
669
template <typename Element>
670
inline Element* RepeatedField<Element>::Add() ABSL_ATTRIBUTE_LIFETIME_BOUND {
671
  if (ABSL_PREDICT_FALSE(current_size_ == total_size_)) {
672
    Grow(current_size_, current_size_ + 1);
673
  }
674
  void* p = unsafe_elements() + ExchangeCurrentSize(current_size_ + 1);
675
  return ::new (p) Element;
676
}
677
678
template <typename Element>
679
template <typename Iter>
680
inline void RepeatedField<Element>::AddForwardIterator(Iter begin, Iter end) {
681
  int total_size = total_size_;
682
  Element* elem = unsafe_elements();
683
  int new_size = current_size_ + static_cast<int>(std::distance(begin, end));
684
  if (ABSL_PREDICT_FALSE(new_size > total_size)) {
685
    Grow(current_size_, new_size);
686
    elem = unsafe_elements();
687
    total_size = total_size_;
688
  }
689
  UninitializedCopy(begin, end, elem + ExchangeCurrentSize(new_size));
690
691
  // The below helps the compiler optimize dense loops.
692
  ABSL_ASSUME(new_size == current_size_);
693
  ABSL_ASSUME(elem == arena_or_elements_);
694
  ABSL_ASSUME(total_size == total_size_);
695
}
696
697
template <typename Element>
698
template <typename Iter>
699
inline void RepeatedField<Element>::AddInputIterator(Iter begin, Iter end) {
700
  Element* first = unsafe_elements() + current_size_;
701
  Element* last = unsafe_elements() + total_size_;
702
  AnnotateSize(current_size_, total_size_);
703
704
  while (begin != end) {
705
    if (ABSL_PREDICT_FALSE(first == last)) {
706
      int current_size = first - unsafe_elements();
707
      GrowNoAnnotate(current_size, current_size + 1);
708
      first = unsafe_elements() + current_size;
709
      last = unsafe_elements() + total_size_;
710
    }
711
    ::new (static_cast<void*>(first)) Element(*begin);
712
    ++begin;
713
    ++first;
714
  }
715
716
  current_size_ = first - unsafe_elements();
717
  AnnotateSize(total_size_, current_size_);
718
}
719
720
template <typename Element>
721
template <typename Iter>
722
inline void RepeatedField<Element>::Add(Iter begin, Iter end) {
723
  if (std::is_base_of<
724
          std::forward_iterator_tag,
725
          typename std::iterator_traits<Iter>::iterator_category>::value) {
726
    AddForwardIterator(begin, end);
727
  } else {
728
    AddInputIterator(begin, end);
729
  }
730
}
731
732
template <typename Element>
733
inline void RepeatedField<Element>::RemoveLast() {
734
  ABSL_DCHECK_GT(current_size_, 0);
735
  elements()[current_size_ - 1].~Element();
736
  ExchangeCurrentSize(current_size_ - 1);
737
}
738
739
template <typename Element>
740
void RepeatedField<Element>::ExtractSubrange(int start, int num,
741
                                             Element* elements) {
742
  ABSL_DCHECK_GE(start, 0);
743
  ABSL_DCHECK_GE(num, 0);
744
  ABSL_DCHECK_LE(start + num, this->current_size_);
745
746
  // Save the values of the removed elements if requested.
747
  if (elements != nullptr) {
748
    for (int i = 0; i < num; ++i) elements[i] = this->Get(i + start);
749
  }
750
751
  // Slide remaining elements down to fill the gap.
752
  if (num > 0) {
753
    for (int i = start + num; i < this->current_size_; ++i)
754
      this->Set(i - num, this->Get(i));
755
    this->Truncate(this->current_size_ - num);
756
  }
757
}
758
759
template <typename Element>
760
0
inline void RepeatedField<Element>::Clear() {
761
0
  Destroy(unsafe_elements(), unsafe_elements() + current_size_);
762
0
  ExchangeCurrentSize(0);
763
0
}
764
765
template <typename Element>
766
inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
767
  ABSL_DCHECK_NE(&other, this);
768
  if (auto size = other.current_size_) {
769
    Reserve(current_size_ + size);
770
    Element* dst = elements() + ExchangeCurrentSize(current_size_ + size);
771
    UninitializedCopyN(other.elements(), size, dst);
772
  }
773
}
774
775
template <typename Element>
776
inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) {
777
  if (&other == this) return;
778
  Clear();
779
  MergeFrom(other);
780
}
781
782
template <typename Element>
783
template <typename Iter>
784
inline void RepeatedField<Element>::Assign(Iter begin, Iter end) {
785
  Clear();
786
  Add(begin, end);
787
}
788
789
template <typename Element>
790
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
791
    const_iterator position) ABSL_ATTRIBUTE_LIFETIME_BOUND {
792
  return erase(position, position + 1);
793
}
794
795
template <typename Element>
796
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
797
    const_iterator first, const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
798
  size_type first_offset = first - cbegin();
799
  if (first != last) {
800
    Truncate(std::copy(last, cend(), begin() + first_offset) - cbegin());
801
  }
802
  return begin() + first_offset;
803
}
804
805
template <typename Element>
806
inline Element* RepeatedField<Element>::mutable_data()
807
0
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
808
0
  return unsafe_elements();
809
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::mutable_data()
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::mutable_data()
Unexecuted instantiation: google::protobuf::RepeatedField<int>::mutable_data()
Unexecuted instantiation: google::protobuf::RepeatedField<long>::mutable_data()
Unexecuted instantiation: google::protobuf::RepeatedField<float>::mutable_data()
Unexecuted instantiation: google::protobuf::RepeatedField<double>::mutable_data()
810
811
template <typename Element>
812
inline const Element* RepeatedField<Element>::data() const
813
0
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
814
0
  return unsafe_elements();
815
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<int>::data() const
Unexecuted instantiation: google::protobuf::RepeatedField<long>::data() const
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::data() const
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::data() const
Unexecuted instantiation: google::protobuf::RepeatedField<float>::data() const
Unexecuted instantiation: google::protobuf::RepeatedField<double>::data() const
Unexecuted instantiation: google::protobuf::RepeatedField<bool>::data() const
816
817
template <typename Element>
818
inline void RepeatedField<Element>::InternalSwap(
819
    RepeatedField* PROTOBUF_RESTRICT other) {
820
  ABSL_DCHECK(this != other);
821
822
  // Swap all fields at once.
823
  static_assert(std::is_standard_layout<RepeatedField<Element>>::value,
824
                "offsetof() requires standard layout before c++17");
825
  static constexpr size_t kOffset = offsetof(RepeatedField, current_size_);
826
  internal::memswap<offsetof(RepeatedField, arena_or_elements_) +
827
                    sizeof(this->arena_or_elements_) - kOffset>(
828
      reinterpret_cast<char*>(this) + kOffset,
829
      reinterpret_cast<char*>(other) + kOffset);
830
}
831
832
template <typename Element>
833
void RepeatedField<Element>::Swap(RepeatedField* other) {
834
  if (this == other) return;
835
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
836
  if (GetArena() != nullptr && GetArena() == other->GetArena()) {
837
#else   // PROTOBUF_FORCE_COPY_IN_SWAP
838
  if (GetArena() == other->GetArena()) {
839
#endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
840
    InternalSwap(other);
841
  } else {
842
    RepeatedField<Element> temp(other->GetArena());
843
    temp.MergeFrom(*this);
844
    CopyFrom(*other);
845
    other->UnsafeArenaSwap(&temp);
846
  }
847
}
848
849
template <typename Element>
850
void RepeatedField<Element>::UnsafeArenaSwap(RepeatedField* other) {
851
  if (this == other) return;
852
  ABSL_DCHECK_EQ(GetArena(), other->GetArena());
853
  InternalSwap(other);
854
}
855
856
template <typename Element>
857
void RepeatedField<Element>::SwapElements(int index1, int index2) {
858
  using std::swap;  // enable ADL with fallback
859
  swap(elements()[index1], elements()[index2]);
860
}
861
862
template <typename Element>
863
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::begin()
864
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
865
  return iterator(unsafe_elements());
866
}
867
template <typename Element>
868
inline typename RepeatedField<Element>::const_iterator
869
RepeatedField<Element>::begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
870
  return const_iterator(unsafe_elements());
871
}
872
template <typename Element>
873
inline typename RepeatedField<Element>::const_iterator
874
RepeatedField<Element>::cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
875
  return const_iterator(unsafe_elements());
876
}
877
template <typename Element>
878
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::end()
879
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
880
  return iterator(unsafe_elements() + current_size_);
881
}
882
template <typename Element>
883
inline typename RepeatedField<Element>::const_iterator
884
RepeatedField<Element>::end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
885
  return const_iterator(unsafe_elements() + current_size_);
886
}
887
template <typename Element>
888
inline typename RepeatedField<Element>::const_iterator
889
RepeatedField<Element>::cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
890
  return const_iterator(unsafe_elements() + current_size_);
891
}
892
893
template <typename Element>
894
inline size_t RepeatedField<Element>::SpaceUsedExcludingSelfLong() const {
895
  return total_size_ > 0 ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0;
896
}
897
898
namespace internal {
899
// Returns the new size for a reserved field based on its 'total_size' and the
900
// requested 'new_size'. The result is clamped to the closed interval:
901
//   [internal::kMinRepeatedFieldAllocationSize,
902
//    std::numeric_limits<int>::max()]
903
// Requires:
904
//     new_size > total_size &&
905
//     (total_size == 0 ||
906
//      total_size >= kRepeatedFieldLowerClampLimit)
907
template <typename T, int kRepHeaderSize>
908
0
inline int CalculateReserveSize(int total_size, int new_size) {
909
0
  constexpr int lower_limit = RepeatedFieldLowerClampLimit<T, kRepHeaderSize>();
910
0
  if (new_size < lower_limit) {
911
0
    // Clamp to smallest allowed size.
912
0
    return lower_limit;
913
0
  }
914
0
  constexpr int kMaxSizeBeforeClamp =
915
0
      (std::numeric_limits<int>::max() - kRepHeaderSize) / 2;
916
0
  if (PROTOBUF_PREDICT_FALSE(total_size > kMaxSizeBeforeClamp)) {
917
0
    return std::numeric_limits<int>::max();
918
0
  }
919
0
  // We want to double the number of bytes, not the number of elements, to try
920
0
  // to stay within power-of-two allocations.
921
0
  // The allocation has kRepHeaderSize + sizeof(T) * capacity.
922
0
  int doubled_size = 2 * total_size + kRepHeaderSize / sizeof(T);
923
0
  return std::max(doubled_size, new_size);
924
0
}
Unexecuted instantiation: int google::protobuf::internal::CalculateReserveSize<unsigned int, 8>(int, int)
Unexecuted instantiation: int google::protobuf::internal::CalculateReserveSize<unsigned long, 8>(int, int)
Unexecuted instantiation: int google::protobuf::internal::CalculateReserveSize<long, 8>(int, int)
Unexecuted instantiation: int google::protobuf::internal::CalculateReserveSize<float, 8>(int, int)
Unexecuted instantiation: int google::protobuf::internal::CalculateReserveSize<double, 8>(int, int)
Unexecuted instantiation: int google::protobuf::internal::CalculateReserveSize<int, 8>(int, int)
925
}  // namespace internal
926
927
template <typename Element>
928
void RepeatedField<Element>::Reserve(int new_size) {
929
  if (ABSL_PREDICT_FALSE(new_size > total_size_)) {
930
    Grow(current_size_, new_size);
931
  }
932
}
933
934
// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant
935
// amount of code bloat.
936
template <typename Element>
937
PROTOBUF_NOINLINE void RepeatedField<Element>::GrowNoAnnotate(int current_size,
938
0
                                                              int new_size) {
939
0
  ABSL_DCHECK_GT(new_size, total_size_);
940
0
  Rep* new_rep;
941
0
  Arena* arena = GetArena();
942
0
943
0
  new_size = internal::CalculateReserveSize<Element, kRepHeaderSize>(
944
0
      total_size_, new_size);
945
0
946
0
  ABSL_DCHECK_LE(
947
0
      static_cast<size_t>(new_size),
948
0
      (std::numeric_limits<size_t>::max() - kRepHeaderSize) / sizeof(Element))
949
0
      << "Requested size is too large to fit into size_t.";
950
0
  size_t bytes =
951
0
      kRepHeaderSize + sizeof(Element) * static_cast<size_t>(new_size);
952
0
  if (arena == nullptr) {
953
0
    ABSL_DCHECK_LE((bytes - kRepHeaderSize) / sizeof(Element),
954
0
                   static_cast<size_t>(std::numeric_limits<int>::max()))
955
0
        << "Requested size is too large to fit element count into int.";
956
0
    internal::SizedPtr res = internal::AllocateAtLeast(bytes);
957
0
    size_t num_available =
958
0
        std::min((res.n - kRepHeaderSize) / sizeof(Element),
959
0
                 static_cast<size_t>(std::numeric_limits<int>::max()));
960
0
    new_size = static_cast<int>(num_available);
961
0
    new_rep = static_cast<Rep*>(res.p);
962
0
  } else {
963
0
    new_rep = reinterpret_cast<Rep*>(Arena::CreateArray<char>(arena, bytes));
964
0
  }
965
0
  new_rep->arena = arena;
966
0
967
0
  if (total_size_ > 0) {
968
0
    if (current_size > 0) {
969
0
      Element* pnew = new_rep->elements();
970
0
      Element* pold = elements();
971
0
      // TODO: add absl::is_trivially_relocatable<Element>
972
0
      if (std::is_trivial<Element>::value) {
973
0
        memcpy(static_cast<void*>(pnew), pold, current_size * sizeof(Element));
974
0
      } else {
975
0
        for (Element* end = pnew + current_size; pnew != end; ++pnew, ++pold) {
976
0
          ::new (static_cast<void*>(pnew)) Element(std::move(*pold));
977
0
          pold->~Element();
978
0
        }
979
0
      }
980
0
    }
981
0
    InternalDeallocate();
982
0
  }
983
0
984
0
  total_size_ = new_size;
985
0
  arena_or_elements_ = new_rep->elements();
986
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::GrowNoAnnotate(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::GrowNoAnnotate(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<long>::GrowNoAnnotate(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<float>::GrowNoAnnotate(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<double>::GrowNoAnnotate(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<int>::GrowNoAnnotate(int, int)
987
988
// Ideally we would be able to use:
989
//   template <bool annotate_size = true>
990
//   void Grow();
991
// However, as explained in b/266411038#comment9, this causes issues
992
// in shared libraries for Youtube (and possibly elsewhere).
993
template <typename Element>
994
PROTOBUF_NOINLINE void RepeatedField<Element>::Grow(int current_size,
995
0
                                                    int new_size) {
996
0
  AnnotateSize(current_size, total_size_);
997
0
  GrowNoAnnotate(current_size, new_size);
998
0
  AnnotateSize(total_size_, current_size);
999
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::Grow(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::Grow(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<long>::Grow(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<float>::Grow(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<double>::Grow(int, int)
Unexecuted instantiation: google::protobuf::RepeatedField<int>::Grow(int, int)
1000
1001
template <typename Element>
1002
0
inline void RepeatedField<Element>::Truncate(int new_size) {
1003
0
  ABSL_DCHECK_LE(new_size, current_size_);
1004
0
  if (new_size < current_size_) {
1005
0
    Destroy(unsafe_elements() + new_size, unsafe_elements() + current_size_);
1006
0
    ExchangeCurrentSize(new_size);
1007
0
  }
1008
0
}
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned int>::Truncate(int)
Unexecuted instantiation: google::protobuf::RepeatedField<unsigned long>::Truncate(int)
Unexecuted instantiation: google::protobuf::RepeatedField<int>::Truncate(int)
Unexecuted instantiation: google::protobuf::RepeatedField<long>::Truncate(int)
Unexecuted instantiation: google::protobuf::RepeatedField<float>::Truncate(int)
Unexecuted instantiation: google::protobuf::RepeatedField<double>::Truncate(int)
1009
1010
template <>
1011
PROTOBUF_EXPORT size_t
1012
RepeatedField<absl::Cord>::SpaceUsedExcludingSelfLong() const;
1013
1014
1015
// -------------------------------------------------------------------
1016
1017
// Iterators and helper functions that follow the spirit of the STL
1018
// std::back_insert_iterator and std::back_inserter but are tailor-made
1019
// for RepeatedField and RepeatedPtrField. Typical usage would be:
1020
//
1021
//   std::copy(some_sequence.begin(), some_sequence.end(),
1022
//             RepeatedFieldBackInserter(proto.mutable_sequence()));
1023
//
1024
// Ported by johannes from util/gtl/proto-array-iterators.h
1025
1026
namespace internal {
1027
1028
// STL-like iterator implementation for RepeatedField.  You should not
1029
// refer to this class directly; use RepeatedField<T>::iterator instead.
1030
//
1031
// Note: All of the iterator operators *must* be inlined to avoid performance
1032
// regressions.  This is caused by the extern template declarations below (which
1033
// are required because of the RepeatedField extern template declarations).  If
1034
// any of these functions aren't explicitly inlined (e.g. defined in the class),
1035
// the compiler isn't allowed to inline them.
1036
template <typename Element>
1037
class RepeatedIterator {
1038
 private:
1039
  using traits =
1040
      std::iterator_traits<typename std::remove_const<Element>::type*>;
1041
1042
 public:
1043
  // Note: value_type is never cv-qualified.
1044
  using value_type = typename traits::value_type;
1045
  using difference_type = typename traits::difference_type;
1046
  using pointer = Element*;
1047
  using reference = Element&;
1048
  using iterator_category = typename traits::iterator_category;
1049
  using iterator_concept = typename IteratorConceptSupport<traits>::tag;
1050
1051
  constexpr RepeatedIterator() noexcept : it_(nullptr) {}
1052
1053
  // Allows "upcasting" from RepeatedIterator<T**> to
1054
  // RepeatedIterator<const T*const*>.
1055
  template <typename OtherElement,
1056
            typename std::enable_if<std::is_convertible<
1057
                OtherElement*, pointer>::value>::type* = nullptr>
1058
  constexpr RepeatedIterator(
1059
      const RepeatedIterator<OtherElement>& other) noexcept
1060
      : it_(other.it_) {}
1061
1062
  // dereferenceable
1063
  constexpr reference operator*() const noexcept { return *it_; }
1064
  constexpr pointer operator->() const noexcept { return it_; }
1065
1066
 private:
1067
  // Helper alias to hide the internal type.
1068
  using iterator = RepeatedIterator<Element>;
1069
1070
 public:
1071
  // {inc,dec}rementable
1072
  iterator& operator++() noexcept {
1073
    ++it_;
1074
    return *this;
1075
  }
1076
  iterator operator++(int) noexcept { return iterator(it_++); }
1077
  iterator& operator--() noexcept {
1078
    --it_;
1079
    return *this;
1080
  }
1081
  iterator operator--(int) noexcept { return iterator(it_--); }
1082
1083
  // equality_comparable
1084
  friend constexpr bool operator==(const iterator& x,
1085
                                   const iterator& y) noexcept {
1086
    return x.it_ == y.it_;
1087
  }
1088
  friend constexpr bool operator!=(const iterator& x,
1089
                                   const iterator& y) noexcept {
1090
    return x.it_ != y.it_;
1091
  }
1092
1093
  // less_than_comparable
1094
  friend constexpr bool operator<(const iterator& x,
1095
                                  const iterator& y) noexcept {
1096
    return x.it_ < y.it_;
1097
  }
1098
  friend constexpr bool operator<=(const iterator& x,
1099
                                   const iterator& y) noexcept {
1100
    return x.it_ <= y.it_;
1101
  }
1102
  friend constexpr bool operator>(const iterator& x,
1103
                                  const iterator& y) noexcept {
1104
    return x.it_ > y.it_;
1105
  }
1106
  friend constexpr bool operator>=(const iterator& x,
1107
                                   const iterator& y) noexcept {
1108
    return x.it_ >= y.it_;
1109
  }
1110
1111
  // addable, subtractable
1112
  iterator& operator+=(difference_type d) noexcept {
1113
    it_ += d;
1114
    return *this;
1115
  }
1116
  constexpr iterator operator+(difference_type d) const noexcept {
1117
    return iterator(it_ + d);
1118
  }
1119
  friend constexpr iterator operator+(const difference_type d,
1120
                                      iterator it) noexcept {
1121
    return it + d;
1122
  }
1123
1124
  iterator& operator-=(difference_type d) noexcept {
1125
    it_ -= d;
1126
    return *this;
1127
  }
1128
  iterator constexpr operator-(difference_type d) const noexcept {
1129
    return iterator(it_ - d);
1130
  }
1131
1132
  // indexable
1133
  constexpr reference operator[](difference_type d) const noexcept {
1134
    return it_[d];
1135
  }
1136
1137
  // random access iterator
1138
  friend constexpr difference_type operator-(iterator it1,
1139
                                             iterator it2) noexcept {
1140
    return it1.it_ - it2.it_;
1141
  }
1142
1143
 private:
1144
  template <typename OtherElement>
1145
  friend class RepeatedIterator;
1146
1147
  // Allow construction from RepeatedField.
1148
  friend class RepeatedField<value_type>;
1149
  explicit RepeatedIterator(pointer it) noexcept : it_(it) {}
1150
1151
  // The internal iterator.
1152
  pointer it_;
1153
};
1154
1155
// A back inserter for RepeatedField objects.
1156
template <typename T>
1157
class RepeatedFieldBackInsertIterator {
1158
 public:
1159
  using iterator_category = std::output_iterator_tag;
1160
  using value_type = T;
1161
  using pointer = void;
1162
  using reference = void;
1163
  using difference_type = std::ptrdiff_t;
1164
1165
  explicit RepeatedFieldBackInsertIterator(
1166
      RepeatedField<T>* const mutable_field)
1167
      : field_(mutable_field) {}
1168
  RepeatedFieldBackInsertIterator<T>& operator=(const T& value) {
1169
    field_->Add(value);
1170
    return *this;
1171
  }
1172
  RepeatedFieldBackInsertIterator<T>& operator*() { return *this; }
1173
  RepeatedFieldBackInsertIterator<T>& operator++() { return *this; }
1174
  RepeatedFieldBackInsertIterator<T>& operator++(int /* unused */) {
1175
    return *this;
1176
  }
1177
1178
 private:
1179
  RepeatedField<T>* field_;
1180
};
1181
1182
}  // namespace internal
1183
1184
// Provides a back insert iterator for RepeatedField instances,
1185
// similar to std::back_inserter().
1186
template <typename T>
1187
internal::RepeatedFieldBackInsertIterator<T> RepeatedFieldBackInserter(
1188
    RepeatedField<T>* const mutable_field) {
1189
  return internal::RepeatedFieldBackInsertIterator<T>(mutable_field);
1190
}
1191
1192
1193
}  // namespace protobuf
1194
}  // namespace google
1195
1196
#include "google/protobuf/port_undef.inc"
1197
1198
#endif  // GOOGLE_PROTOBUF_REPEATED_FIELD_H__