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 | // This file contains miscellaneous helper code used by generated code -- |
36 | // including lite types -- but which should not be used directly by users. |
37 | |
38 | #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ |
39 | #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ |
40 | |
41 | #include <assert.h> |
42 | |
43 | #include <atomic> |
44 | #include <climits> |
45 | #include <string> |
46 | #include <vector> |
47 | |
48 | #include <google/protobuf/stubs/common.h> |
49 | #include <google/protobuf/any.h> |
50 | #include <google/protobuf/has_bits.h> |
51 | #include <google/protobuf/implicit_weak_message.h> |
52 | #include <google/protobuf/message_lite.h> |
53 | #include <google/protobuf/stubs/once.h> // Add direct dep on port for pb.cc |
54 | #include <google/protobuf/port.h> |
55 | #include <google/protobuf/repeated_field.h> |
56 | #include <google/protobuf/wire_format_lite.h> |
57 | #include <google/protobuf/stubs/strutil.h> |
58 | #include <google/protobuf/stubs/casts.h> |
59 | |
60 | #include <google/protobuf/port_def.inc> |
61 | |
62 | #ifdef SWIG |
63 | #error "You cannot SWIG proto headers" |
64 | #endif |
65 | |
66 | namespace google { |
67 | namespace protobuf { |
68 | |
69 | class Arena; |
70 | class Message; |
71 | |
72 | namespace io { |
73 | class CodedInputStream; |
74 | } |
75 | |
76 | namespace internal { |
77 | |
78 | template <typename To, typename From> |
79 | inline To DownCast(From* f) { |
80 | return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f); |
81 | } |
82 | template <typename To, typename From> |
83 | inline To DownCast(From& f) { |
84 | return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f); |
85 | } |
86 | |
87 | |
88 | PROTOBUF_EXPORT void InitProtobufDefaults(); |
89 | |
90 | // This used by proto1 |
91 | PROTOBUF_EXPORT inline const std::string& GetEmptyString() { |
92 | InitProtobufDefaults(); |
93 | return GetEmptyStringAlreadyInited(); |
94 | } |
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> |
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> |
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 | |
125 | inline bool IsPresent(const void* base, uint32 hasbit) { |
126 | const uint32* has_bits_array = static_cast<const uint32*>(base); |
127 | return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0; |
128 | } |
129 | |
130 | inline bool IsOneofPresent(const void* base, uint32 offset, uint32 tag) { |
131 | const uint32* oneof = |
132 | reinterpret_cast<const uint32*>(static_cast<const uint8*>(base) + offset); |
133 | return *oneof == tag >> 3; |
134 | } |
135 | |
136 | typedef void (*SpecialSerializer)(const uint8* base, uint32 offset, uint32 tag, |
137 | uint32 has_offset, |
138 | io::CodedOutputStream* output); |
139 | |
140 | PROTOBUF_EXPORT void ExtensionSerializer(const uint8* base, uint32 offset, |
141 | uint32 tag, uint32 has_offset, |
142 | io::CodedOutputStream* output); |
143 | PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8* base, |
144 | uint32 offset, uint32 tag, |
145 | uint32 has_offset, |
146 | io::CodedOutputStream* output); |
147 | |
148 | PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message); |
149 | PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena, |
150 | MessageLite* submessage, |
151 | Arena* submessage_arena); |
152 | PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2); |
153 | // We specialize GenericSwap for non-lite messages to benefit from reflection. |
154 | PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2); |
155 | |
156 | template <typename T> |
157 | T* DuplicateIfNonNull(T* message) { |
158 | // The casts must be reinterpret_cast<> because T might be a forward-declared |
159 | // type that the compiler doesn't know is related to MessageLite. |
160 | return reinterpret_cast<T*>( |
161 | DuplicateIfNonNullInternal(message: reinterpret_cast<MessageLite*>(message))); |
162 | } |
163 | |
164 | template <typename T> |
165 | T* GetOwnedMessage(Arena* message_arena, T* submessage, |
166 | Arena* submessage_arena) { |
167 | // The casts must be reinterpret_cast<> because T might be a forward-declared |
168 | // type that the compiler doesn't know is related to MessageLite. |
169 | return reinterpret_cast<T*>(GetOwnedMessageInternal( |
170 | message_arena, submessage: reinterpret_cast<MessageLite*>(submessage), |
171 | submessage_arena)); |
172 | } |
173 | |
174 | // Hide atomic from the public header and allow easy change to regular int |
175 | // on platforms where the atomic might have a perf impact. |
176 | class PROTOBUF_EXPORT CachedSize { |
177 | public: |
178 | int Get() const { return size_.load(m: std::memory_order_relaxed); } |
179 | void Set(int size) { size_.store(i: size, m: std::memory_order_relaxed); } |
180 | |
181 | private: |
182 | std::atomic<int> size_{0}; |
183 | }; |
184 | |
185 | // SCCInfo represents information of a strongly connected component of |
186 | // mutual dependent messages. |
187 | struct PROTOBUF_EXPORT SCCInfoBase { |
188 | // We use 0 for the Initialized state, because test eax,eax, jnz is smaller |
189 | // and is subject to macro fusion. |
190 | enum { |
191 | kInitialized = 0, // final state |
192 | kRunning = 1, |
193 | kUninitialized = -1, // initial state |
194 | }; |
195 | #if defined(_MSC_VER) && !defined(__clang__) |
196 | // MSVC doesn't make std::atomic constant initialized. This union trick |
197 | // makes it so. |
198 | union { |
199 | int visit_status_to_make_linker_init; |
200 | std::atomic<int> visit_status; |
201 | }; |
202 | #else |
203 | std::atomic<int> visit_status; |
204 | #endif |
205 | int num_deps; |
206 | int num_implicit_weak_deps; |
207 | void (*init_func)(); |
208 | // This is followed by an array of num_deps |
209 | // const SCCInfoBase* deps[]; |
210 | }; |
211 | |
212 | // Zero-length arrays are a language extension available in GCC and Clang but |
213 | // not MSVC. |
214 | #ifdef __GNUC__ |
215 | #define PROTOBUF_ARRAY_SIZE(n) (n) |
216 | #else |
217 | #define PROTOBUF_ARRAY_SIZE(n) ((n) ? (n) : 1) |
218 | #endif |
219 | |
220 | template <int N> |
221 | struct SCCInfo { |
222 | SCCInfoBase base; |
223 | // Semantically this is const SCCInfo<T>* which is is a templated type. |
224 | // The obvious inheriting from SCCInfoBase mucks with struct initialization. |
225 | // Attempts showed the compiler was generating dynamic initialization code. |
226 | // This deps array consists of base.num_deps pointers to SCCInfoBase followed |
227 | // by base.num_implicit_weak_deps pointers to SCCInfoBase*. We need the extra |
228 | // pointer indirection for implicit weak fields. We cannot use a union type |
229 | // here, since that would prevent the array from being linker-initialized. |
230 | void* deps[PROTOBUF_ARRAY_SIZE(N)]; |
231 | }; |
232 | |
233 | #undef PROTOBUF_ARRAY_SIZE |
234 | |
235 | PROTOBUF_EXPORT void InitSCCImpl(SCCInfoBase* scc); |
236 | |
237 | inline void InitSCC(SCCInfoBase* scc) { |
238 | auto status = scc->visit_status.load(m: std::memory_order_acquire); |
239 | if (PROTOBUF_PREDICT_FALSE(status != SCCInfoBase::kInitialized)) |
240 | InitSCCImpl(scc); |
241 | } |
242 | |
243 | PROTOBUF_EXPORT void DestroyMessage(const void* message); |
244 | PROTOBUF_EXPORT void DestroyString(const void* s); |
245 | // Destroy (not delete) the message |
246 | inline void OnShutdownDestroyMessage(const void* ptr) { |
247 | OnShutdownRun(f: DestroyMessage, arg: ptr); |
248 | } |
249 | // Destroy the string (call std::string destructor) |
250 | inline void OnShutdownDestroyString(const std::string* ptr) { |
251 | OnShutdownRun(f: DestroyString, arg: ptr); |
252 | } |
253 | |
254 | } // namespace internal |
255 | } // namespace protobuf |
256 | } // namespace google |
257 | |
258 | #include <google/protobuf/port_undef.inc> |
259 | |
260 | #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ |
261 | |