• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // This file contains miscellaneous helper code used by generated code --
13 // including lite types -- but which should not be used directly by users.
14 
15 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
16 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
17 
18 #include <assert.h>
19 
20 #include <algorithm>
21 #include <atomic>
22 #include <climits>
23 #include <cstddef>
24 #include <initializer_list>
25 #include <memory>
26 #include <string>
27 #include <type_traits>
28 #include <utility>
29 #include <vector>
30 
31 #include "google/protobuf/stubs/common.h"
32 #include "absl/base/call_once.h"
33 #include "absl/base/casts.h"
34 #include "absl/strings/string_view.h"
35 #include "absl/types/optional.h"
36 #include "google/protobuf/any.h"
37 #include "google/protobuf/has_bits.h"
38 #include "google/protobuf/implicit_weak_message.h"
39 #include "google/protobuf/message_lite.h"
40 #include "google/protobuf/port.h"
41 #include "google/protobuf/repeated_field.h"
42 #include "google/protobuf/repeated_ptr_field.h"
43 #include "google/protobuf/wire_format_lite.h"
44 
45 
46 // Must be included last.
47 #include "google/protobuf/port_def.inc"
48 
49 #ifdef SWIG
50 #error "You cannot SWIG proto headers"
51 #endif
52 
53 namespace google {
54 namespace protobuf {
55 
56 class Arena;
57 class Message;
58 
59 namespace io {
60 class CodedInputStream;
61 }
62 
63 namespace internal {
64 
65 
66 // This fastpath inlines a single branch instead of having to make the
67 // InitProtobufDefaults function call.
68 // It also generates less inlined code than a function-scope static initializer.
69 PROTOBUF_EXPORT extern std::atomic<bool> init_protobuf_defaults_state;
70 PROTOBUF_EXPORT void InitProtobufDefaultsSlow();
InitProtobufDefaults()71 PROTOBUF_EXPORT inline void InitProtobufDefaults() {
72   if (PROTOBUF_PREDICT_FALSE(
73           !init_protobuf_defaults_state.load(std::memory_order_acquire))) {
74     InitProtobufDefaultsSlow();
75   }
76 }
77 
78 // This used by proto1
GetEmptyString()79 PROTOBUF_EXPORT inline const std::string& GetEmptyString() {
80   InitProtobufDefaults();
81   return GetEmptyStringAlreadyInited();
82 }
83 
84 // Default empty Cord object. Don't use directly. Instead, call
85 // GetEmptyCordAlreadyInited() to get the reference.
86 union EmptyCord {
EmptyCord()87   constexpr EmptyCord() : value() {}
~EmptyCord()88   ~EmptyCord() {}
89   ::absl::Cord value;
90 };
91 PROTOBUF_EXPORT extern const EmptyCord empty_cord_;
92 
GetEmptyCordAlreadyInited()93 constexpr const ::absl::Cord& GetEmptyCordAlreadyInited() {
94   return empty_cord_.value;
95 }
96 
97 // True if IsInitialized() is true for all elements of t.  Type is expected
98 // to be a RepeatedPtrField<some message type>.  It's useful to have this
99 // helper here to keep the protobuf compiler from ever having to emit loops in
100 // IsInitialized() methods.  We want the C++ compiler to inline this or not
101 // as it sees fit.
102 template <typename Msg>
AllAreInitialized(const RepeatedPtrField<Msg> & t)103 bool AllAreInitialized(const RepeatedPtrField<Msg>& t) {
104   for (int i = t.size(); --i >= 0;) {
105     if (!t.Get(i).IsInitialized()) return false;
106   }
107   return true;
108 }
109 
110 // "Weak" variant of AllAreInitialized, used to implement implicit weak fields.
111 // This version operates on MessageLite to avoid introducing a dependency on the
112 // concrete message type.
113 template <class T>
AllAreInitializedWeak(const RepeatedPtrField<T> & t)114 bool AllAreInitializedWeak(const RepeatedPtrField<T>& t) {
115   for (int i = t.size(); --i >= 0;) {
116     if (!reinterpret_cast<const RepeatedPtrFieldBase&>(t)
117              .Get<ImplicitWeakTypeHandler<T> >(i)
118              .IsInitialized()) {
119       return false;
120     }
121   }
122   return true;
123 }
124 
IsPresent(const void * base,uint32_t hasbit)125 inline bool IsPresent(const void* base, uint32_t hasbit) {
126   const uint32_t* has_bits_array = static_cast<const uint32_t*>(base);
127   return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0;
128 }
129 
IsOneofPresent(const void * base,uint32_t offset,uint32_t tag)130 inline bool IsOneofPresent(const void* base, uint32_t offset, uint32_t tag) {
131   const uint32_t* oneof = reinterpret_cast<const uint32_t*>(
132       static_cast<const uint8_t*>(base) + offset);
133   return *oneof == tag >> 3;
134 }
135 
136 typedef void (*SpecialSerializer)(const uint8_t* base, uint32_t offset,
137                                   uint32_t tag, uint32_t has_offset,
138                                   io::CodedOutputStream* output);
139 
140 PROTOBUF_EXPORT void ExtensionSerializer(const MessageLite* extendee,
141                                          const uint8_t* ptr, uint32_t offset,
142                                          uint32_t tag, uint32_t has_offset,
143                                          io::CodedOutputStream* output);
144 PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8_t* base,
145                                                 uint32_t offset, uint32_t tag,
146                                                 uint32_t has_offset,
147                                                 io::CodedOutputStream* output);
148 
149 PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message);
150 PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena,
151                                                      MessageLite* submessage,
152                                                      Arena* submessage_arena);
153 PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2);
154 // We specialize GenericSwap for non-lite messages to benefit from reflection.
155 PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2);
156 
157 template <typename T>
DuplicateIfNonNull(T * message)158 T* DuplicateIfNonNull(T* message) {
159   // The casts must be reinterpret_cast<> because T might be a forward-declared
160   // type that the compiler doesn't know is related to MessageLite.
161   return reinterpret_cast<T*>(
162       DuplicateIfNonNullInternal(reinterpret_cast<MessageLite*>(message)));
163 }
164 
165 template <typename T>
GetOwnedMessage(Arena * message_arena,T * submessage,Arena * submessage_arena)166 T* GetOwnedMessage(Arena* message_arena, T* submessage,
167                    Arena* submessage_arena) {
168   // The casts must be reinterpret_cast<> because T might be a forward-declared
169   // type that the compiler doesn't know is related to MessageLite.
170   return reinterpret_cast<T*>(GetOwnedMessageInternal(
171       message_arena, reinterpret_cast<MessageLite*>(submessage),
172       submessage_arena));
173 }
174 
175 PROTOBUF_EXPORT void DestroyMessage(const void* message);
176 PROTOBUF_EXPORT void DestroyString(const void* s);
177 // Destroy (not delete) the message
OnShutdownDestroyMessage(const void * ptr)178 inline void OnShutdownDestroyMessage(const void* ptr) {
179   OnShutdownRun(DestroyMessage, ptr);
180 }
181 // Destroy the string (call std::string destructor)
OnShutdownDestroyString(const std::string * ptr)182 inline void OnShutdownDestroyString(const std::string* ptr) {
183   OnShutdownRun(DestroyString, ptr);
184 }
185 
186 // Helpers for deterministic serialization =============================
187 
188 // Iterator base for MapSorterFlat and MapSorterPtr.
189 template <typename storage_type>
190 struct MapSorterIt {
191   storage_type* ptr;
MapSorterItMapSorterIt192   MapSorterIt(storage_type* ptr) : ptr(ptr) {}
193   bool operator==(const MapSorterIt& other) const { return ptr == other.ptr; }
194   bool operator!=(const MapSorterIt& other) const { return !(*this == other); }
195   MapSorterIt& operator++() {
196     ++ptr;
197     return *this;
198   }
199   MapSorterIt operator++(int) {
200     auto other = *this;
201     ++ptr;
202     return other;
203   }
204   MapSorterIt operator+(int v) { return MapSorterIt{ptr + v}; }
205 };
206 
207 // Defined outside of MapSorterFlat to only be templatized on the key.
208 template <typename KeyT>
209 struct MapSorterLessThan {
210   using storage_type = std::pair<KeyT, const void*>;
operatorMapSorterLessThan211   bool operator()(const storage_type& a, const storage_type& b) const {
212     return a.first < b.first;
213   }
214 };
215 
216 // MapSorterFlat stores keys inline with pointers to map entries, so that
217 // keys can be compared without indirection. This type is used for maps with
218 // keys that are not strings.
219 template <typename MapT>
220 class MapSorterFlat {
221  public:
222   using value_type = typename MapT::value_type;
223   // To avoid code bloat we don't put `value_type` in `storage_type`. It is not
224   // necessary for the call to sort, and avoiding it prevents unnecessary
225   // separate instantiations of sort.
226   using storage_type = std::pair<typename MapT::key_type, const void*>;
227 
228   // This const_iterator dereferenes to the map entry stored in the sorting
229   // array pairs. This is the same interface as the Map::const_iterator type,
230   // and allows generated code to use the same loop body with either form:
231   //   for (const auto& entry : map) { ... }
232   //   for (const auto& entry : MapSorterFlat(map)) { ... }
233   struct const_iterator : public MapSorterIt<storage_type> {
234     using pointer = const typename MapT::value_type*;
235     using reference = const typename MapT::value_type&;
236     using MapSorterIt<storage_type>::MapSorterIt;
237 
238     pointer operator->() const {
239       return static_cast<const value_type*>(this->ptr->second);
240     }
241     reference operator*() const { return *this->operator->(); }
242   };
243 
MapSorterFlat(const MapT & m)244   explicit MapSorterFlat(const MapT& m)
245       : size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
246     if (!size_) return;
247     storage_type* it = &items_[0];
248     for (const auto& entry : m) {
249       *it++ = {entry.first, &entry};
250     }
251     std::sort(&items_[0], &items_[size_],
252               MapSorterLessThan<typename MapT::key_type>{});
253   }
size()254   size_t size() const { return size_; }
begin()255   const_iterator begin() const { return {items_.get()}; }
end()256   const_iterator end() const { return {items_.get() + size_}; }
257 
258  private:
259   size_t size_;
260   std::unique_ptr<storage_type[]> items_;
261 };
262 
263 // Defined outside of MapSorterPtr to only be templatized on the key.
264 template <typename KeyT>
265 struct MapSorterPtrLessThan {
operatorMapSorterPtrLessThan266   bool operator()(const void* a, const void* b) const {
267     // The pointers point to the `std::pair<const Key, Value>` object.
268     // We cast directly to the key to read it.
269     return *reinterpret_cast<const KeyT*>(a) <
270            *reinterpret_cast<const KeyT*>(b);
271   }
272 };
273 
274 // MapSorterPtr stores and sorts pointers to map entries. This type is used for
275 // maps with keys that are strings.
276 template <typename MapT>
277 class MapSorterPtr {
278  public:
279   using value_type = typename MapT::value_type;
280   // To avoid code bloat we don't put `value_type` in `storage_type`. It is not
281   // necessary for the call to sort, and avoiding it prevents unnecessary
282   // separate instantiations of sort.
283   using storage_type = const void*;
284 
285   // This const_iterator dereferenes the map entry pointer stored in the sorting
286   // array. This is the same interface as the Map::const_iterator type, and
287   // allows generated code to use the same loop body with either form:
288   //   for (const auto& entry : map) { ... }
289   //   for (const auto& entry : MapSorterPtr(map)) { ... }
290   struct const_iterator : public MapSorterIt<storage_type> {
291     using pointer = const typename MapT::value_type*;
292     using reference = const typename MapT::value_type&;
293     using MapSorterIt<storage_type>::MapSorterIt;
294 
295     pointer operator->() const {
296       return static_cast<const value_type*>(*this->ptr);
297     }
298     reference operator*() const { return *this->operator->(); }
299   };
300 
MapSorterPtr(const MapT & m)301   explicit MapSorterPtr(const MapT& m)
302       : size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
303     if (!size_) return;
304     storage_type* it = &items_[0];
305     for (const auto& entry : m) {
306       *it++ = &entry;
307     }
308     static_assert(PROTOBUF_FIELD_OFFSET(typename MapT::value_type, first) == 0,
309                   "Must hold for MapSorterPtrLessThan to work.");
310     std::sort(&items_[0], &items_[size_],
311               MapSorterPtrLessThan<typename MapT::key_type>{});
312   }
size()313   size_t size() const { return size_; }
begin()314   const_iterator begin() const { return {items_.get()}; }
end()315   const_iterator end() const { return {items_.get() + size_}; }
316 
317  private:
318   size_t size_;
319   std::unique_ptr<storage_type[]> items_;
320 };
321 
322 struct WeakDescriptorDefaultTail {
323   const Message** target;
324   size_t size;
325 };
326 
327 // Tag to distinguish overloads below:
328 //  - if last argument is `BytesTag tag = BytesTag{}` then the overload is
329 //    available to both string and byte fields.
330 //  - if last argument is `BytesTag tag` then the overload is only available to
331 //    byte fields.
332 //  - if there is no BytesTag argument, then the overload is only available to
333 //    string fields.
334 struct BytesTag {
335   explicit BytesTag() = default;
336 };
337 
338 // Assigns to `dest` the content of `value`, optionally bounded by `size`.
339 // This overload set is used to implement `set_xxx()` methods for repeated
340 // string fields in generated code.
341 inline void AssignToString(std::string& dest, const std::string& value,
342                            BytesTag tag = BytesTag{}) {
343   dest.assign(value);
344 }
345 inline void AssignToString(std::string& dest, std::string&& value,
346                            BytesTag tag = BytesTag{}) {
347   dest.assign(std::move(value));
348 }
349 inline void AssignToString(std::string& dest, const char* value,
350                            BytesTag tag = BytesTag{}) {
351   dest.assign(value);
352 }
AssignToString(std::string & dest,const char * value,std::size_t size)353 inline void AssignToString(std::string& dest, const char* value,
354                            std::size_t size) {
355   dest.assign(value, size);
356 }
AssignToString(std::string & dest,const void * value,std::size_t size,BytesTag tag)357 inline void AssignToString(std::string& dest, const void* value,
358                            std::size_t size, BytesTag tag) {
359   dest.assign(reinterpret_cast<const char*>(value), size);
360 }
361 inline void AssignToString(std::string& dest, absl::string_view value,
362                            BytesTag tag = BytesTag{}) {
363   dest.assign(value.data(), value.size());
364 }
365 
366 // Adds `value`, optionally bounded by `size`, as the last element of `dest`.
367 // This overload set is used to implement `add_xxx()` methods for repeated
368 // string fields in generated code.
369 template <typename Arg, typename... Args>
AddToRepeatedPtrField(google::protobuf::RepeatedPtrField<std::string> & dest,Arg && value,Args...args)370 void AddToRepeatedPtrField(google::protobuf::RepeatedPtrField<std::string>& dest,
371                            Arg&& value, Args... args) {
372   AssignToString(*dest.Add(), std::forward<Arg>(value), args...);
373 }
374 inline void AddToRepeatedPtrField(google::protobuf::RepeatedPtrField<std::string>& dest,
375                                   std::string&& value,
376                                   BytesTag tag = BytesTag{}) {
377   dest.Add(std::move(value));
378 }
379 
EncodePlacementArenaOffsets(std::initializer_list<size_t> offsets)380 constexpr absl::optional<uintptr_t> EncodePlacementArenaOffsets(
381     std::initializer_list<size_t> offsets) {
382   uintptr_t arena_bits = 0;
383   for (size_t offset : offsets) {
384     offset /= sizeof(Arena*);
385     if (offset >= sizeof(arena_bits) * 8) {
386       return absl::nullopt;
387     }
388     arena_bits |= uintptr_t{1} << offset;
389   }
390   return arena_bits;
391 }
392 
393 }  // namespace internal
394 }  // namespace protobuf
395 }  // namespace google
396 
397 #include "google/protobuf/port_undef.inc"
398 
399 #endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
400