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: [email protected] (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 | |
71 | namespace io { |
72 | class CodedInputStream; |
73 | } |
74 | |
75 | namespace internal { |
76 | |
77 | template <typename To, typename From> |
78 | inline To DownCast(From* f) { |
79 | return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f); |
80 | } |
81 | template <typename To, typename From> |
82 | inline To DownCast(From& f) { |
83 | return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f); |
84 | } |
85 | |
86 | |
87 | PROTOBUF_EXPORT void InitProtobufDefaults(); |
88 | |
89 | // This used by proto1 |
90 | PROTOBUF_EXPORT inline const std::string& GetEmptyString() { |
91 | InitProtobufDefaults(); |
92 | return GetEmptyStringAlreadyInited(); |
93 | } |
94 | |
95 | |
96 | // True if IsInitialized() is true for all elements of t. Type is expected |
97 | // to be a RepeatedPtrField<some message type>. It's useful to have this |
98 | // helper here to keep the protobuf compiler from ever having to emit loops in |
99 | // IsInitialized() methods. We want the C++ compiler to inline this or not |
100 | // as it sees fit. |
101 | template <typename Msg> |
102 | bool AllAreInitialized(const RepeatedPtrField<Msg>& t) { |
103 | for (int i = t.size(); --i >= 0;) { |
104 | if (!t.Get(i).IsInitialized()) return false; |
105 | } |
106 | return true; |
107 | } |
108 | |
109 | // "Weak" variant of AllAreInitialized, used to implement implicit weak fields. |
110 | // This version operates on MessageLite to avoid introducing a dependency on the |
111 | // concrete message type. |
112 | template <class T> |
113 | bool AllAreInitializedWeak(const RepeatedPtrField<T>& t) { |
114 | for (int i = t.size(); --i >= 0;) { |
115 | if (!reinterpret_cast<const RepeatedPtrFieldBase&>(t) |
116 | .Get<ImplicitWeakTypeHandler<T> >(i) |
117 | .IsInitialized()) { |
118 | return false; |
119 | } |
120 | } |
121 | return true; |
122 | } |
123 | |
124 | inline bool IsPresent(const void* base, uint32 hasbit) { |
125 | const uint32* has_bits_array = static_cast<const uint32*>(base); |
126 | return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0; |
127 | } |
128 | |
129 | inline bool IsOneofPresent(const void* base, uint32 offset, uint32 tag) { |
130 | const uint32* oneof = |
131 | reinterpret_cast<const uint32*>(static_cast<const uint8*>(base) + offset); |
132 | return *oneof == tag >> 3; |
133 | } |
134 | |
135 | typedef void (*SpecialSerializer)(const uint8* base, uint32 offset, uint32 tag, |
136 | uint32 has_offset, |
137 | io::CodedOutputStream* output); |
138 | |
139 | PROTOBUF_EXPORT void ExtensionSerializer(const uint8* base, uint32 offset, |
140 | uint32 tag, uint32 has_offset, |
141 | io::CodedOutputStream* output); |
142 | PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8* base, |
143 | uint32 offset, uint32 tag, |
144 | uint32 has_offset, |
145 | io::CodedOutputStream* output); |
146 | |
147 | PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message); |
148 | PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena, |
149 | MessageLite* submessage, |
150 | Arena* submessage_arena); |
151 | PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2); |
152 | |
153 | template <typename T> |
154 | T* DuplicateIfNonNull(T* message) { |
155 | // The casts must be reinterpret_cast<> because T might be a forward-declared |
156 | // type that the compiler doesn't know is related to MessageLite. |
157 | return reinterpret_cast<T*>( |
158 | DuplicateIfNonNullInternal(reinterpret_cast<MessageLite*>(message))); |
159 | } |
160 | |
161 | template <typename T> |
162 | T* GetOwnedMessage(Arena* message_arena, T* submessage, |
163 | Arena* submessage_arena) { |
164 | // The casts must be reinterpret_cast<> because T might be a forward-declared |
165 | // type that the compiler doesn't know is related to MessageLite. |
166 | return reinterpret_cast<T*>(GetOwnedMessageInternal( |
167 | message_arena, reinterpret_cast<MessageLite*>(submessage), |
168 | submessage_arena)); |
169 | } |
170 | |
171 | // Hide atomic from the public header and allow easy change to regular int |
172 | // on platforms where the atomic might have a perf impact. |
173 | class PROTOBUF_EXPORT CachedSize { |
174 | public: |
175 | int Get() const { return size_.load(std::memory_order_relaxed); } |
176 | void Set(int size) { size_.store(size, std::memory_order_relaxed); } |
177 | |
178 | private: |
179 | std::atomic<int> size_{0}; |
180 | }; |
181 | |
182 | // SCCInfo represents information of a strongly connected component of |
183 | // mutual dependent messages. |
184 | struct PROTOBUF_EXPORT SCCInfoBase { |
185 | // We use 0 for the Initialized state, because test eax,eax, jnz is smaller |
186 | // and is subject to macro fusion. |
187 | enum { |
188 | kInitialized = 0, // final state |
189 | kRunning = 1, |
190 | kUninitialized = -1, // initial state |
191 | }; |
192 | #if defined(_MSC_VER) && !defined(__clang__) |
193 | // MSVC doesnt make std::atomic constant initialized. This union trick |
194 | // makes it so. |
195 | union { |
196 | int visit_status_to_make_linker_init; |
197 | std::atomic<int> visit_status; |
198 | }; |
199 | #else |
200 | std::atomic<int> visit_status; |
201 | #endif |
202 | int num_deps; |
203 | int num_implicit_weak_deps; |
204 | void (*init_func)(); |
205 | // This is followed by an array of num_deps |
206 | // const SCCInfoBase* deps[]; |
207 | }; |
208 | |
209 | // Zero-length arrays are a language extension available in GCC and Clang but |
210 | // not MSVC. |
211 | #ifdef __GNUC__ |
212 | #define PROTOBUF_ARRAY_SIZE(n) (n) |
213 | #else |
214 | #define PROTOBUF_ARRAY_SIZE(n) ((n) ? (n) : 1) |
215 | #endif |
216 | |
217 | template <int N> |
218 | struct SCCInfo { |
219 | SCCInfoBase base; |
220 | // Semantically this is const SCCInfo<T>* which is is a templated type. |
221 | // The obvious inheriting from SCCInfoBase mucks with struct initialization. |
222 | // Attempts showed the compiler was generating dynamic initialization code. |
223 | // This deps array consists of base.num_deps pointers to SCCInfoBase followed |
224 | // by base.num_implicit_weak_deps pointers to SCCInfoBase*. We need the extra |
225 | // pointer indirection for implicit weak fields. We cannot use a union type |
226 | // here, since that would prevent the array from being linker-initialized. |
227 | void* deps[PROTOBUF_ARRAY_SIZE(N)]; |
228 | }; |
229 | |
230 | #undef PROTOBUF_ARRAY_SIZE |
231 | |
232 | PROTOBUF_EXPORT void InitSCCImpl(SCCInfoBase* scc); |
233 | |
234 | inline void InitSCC(SCCInfoBase* scc) { |
235 | auto status = scc->visit_status.load(std::memory_order_acquire); |
236 | if (PROTOBUF_PREDICT_FALSE(status != SCCInfoBase::kInitialized)) |
237 | InitSCCImpl(scc); |
238 | } |
239 | |
240 | PROTOBUF_EXPORT void DestroyMessage(const void* message); |
241 | PROTOBUF_EXPORT void DestroyString(const void* s); |
242 | // Destroy (not delete) the message |
243 | inline void OnShutdownDestroyMessage(const void* ptr) { |
244 | OnShutdownRun(DestroyMessage, ptr); |
245 | } |
246 | // Destroy the string (call std::string destructor) |
247 | inline void OnShutdownDestroyString(const std::string* ptr) { |
248 | OnShutdownRun(DestroyString, ptr); |
249 | } |
250 | |
251 | } // namespace internal |
252 | } // namespace protobuf |
253 | } // namespace google |
254 | |
255 | #include <google/protobuf/port_undef.inc> |
256 | |
257 | #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ |
258 | |