/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__ |