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