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/stubs/once.h> // Add direct dep on port for pb.cc |
50 | #include <google/protobuf/port.h> |
51 | #include <google/protobuf/stubs/strutil.h> |
52 | #include <google/protobuf/any.h> |
53 | #include <google/protobuf/has_bits.h> |
54 | #include <google/protobuf/implicit_weak_message.h> |
55 | #include <google/protobuf/message_lite.h> |
56 | #include <google/protobuf/repeated_field.h> |
57 | #include <google/protobuf/wire_format_lite.h> |
58 | #include <google/protobuf/stubs/casts.h> |
59 | |
60 | // Must be included last. |
61 | #include <google/protobuf/port_def.inc> |
62 | |
63 | #ifdef SWIG |
64 | #error "You cannot SWIG proto headers" |
65 | #endif |
66 | |
67 | namespace google { |
68 | namespace protobuf { |
69 | |
70 | class Arena; |
71 | class Message; |
72 | |
73 | namespace io { |
74 | class CodedInputStream; |
75 | } |
76 | |
77 | namespace internal { |
78 | |
79 | template <typename To, typename From> |
80 | inline To DownCast(From* f) { |
81 | return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f); |
82 | } |
83 | template <typename To, typename From> |
84 | inline To DownCast(From& f) { |
85 | return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f); |
86 | } |
87 | |
88 | |
89 | // This fastpath inlines a single branch instead of having to make the |
90 | // InitProtobufDefaults function call. |
91 | // It also generates less inlined code than a function-scope static initializer. |
92 | PROTOBUF_EXPORT extern std::atomic<bool> init_protobuf_defaults_state; |
93 | PROTOBUF_EXPORT void InitProtobufDefaultsSlow(); |
94 | PROTOBUF_EXPORT inline void InitProtobufDefaults() { |
95 | if (PROTOBUF_PREDICT_FALSE( |
96 | !init_protobuf_defaults_state.load(std::memory_order_acquire))) { |
97 | InitProtobufDefaultsSlow(); |
98 | } |
99 | } |
100 | |
101 | // This used by proto1 |
102 | PROTOBUF_EXPORT inline const std::string& GetEmptyString() { |
103 | InitProtobufDefaults(); |
104 | return GetEmptyStringAlreadyInited(); |
105 | } |
106 | |
107 | |
108 | // True if IsInitialized() is true for all elements of t. Type is expected |
109 | // to be a RepeatedPtrField<some message type>. It's useful to have this |
110 | // helper here to keep the protobuf compiler from ever having to emit loops in |
111 | // IsInitialized() methods. We want the C++ compiler to inline this or not |
112 | // as it sees fit. |
113 | template <typename Msg> |
114 | bool AllAreInitialized(const RepeatedPtrField<Msg>& t) { |
115 | for (int i = t.size(); --i >= 0;) { |
116 | if (!t.Get(i).IsInitialized()) return false; |
117 | } |
118 | return true; |
119 | } |
120 | |
121 | // "Weak" variant of AllAreInitialized, used to implement implicit weak fields. |
122 | // This version operates on MessageLite to avoid introducing a dependency on the |
123 | // concrete message type. |
124 | template <class T> |
125 | bool AllAreInitializedWeak(const RepeatedPtrField<T>& t) { |
126 | for (int i = t.size(); --i >= 0;) { |
127 | if (!reinterpret_cast<const RepeatedPtrFieldBase&>(t) |
128 | .Get<ImplicitWeakTypeHandler<T> >(i) |
129 | .IsInitialized()) { |
130 | return false; |
131 | } |
132 | } |
133 | return true; |
134 | } |
135 | |
136 | inline bool IsPresent(const void* base, uint32_t hasbit) { |
137 | const uint32_t* has_bits_array = static_cast<const uint32_t*>(base); |
138 | return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0; |
139 | } |
140 | |
141 | inline bool IsOneofPresent(const void* base, uint32_t offset, uint32_t tag) { |
142 | const uint32_t* oneof = reinterpret_cast<const uint32_t*>( |
143 | static_cast<const uint8_t*>(base) + offset); |
144 | return *oneof == tag >> 3; |
145 | } |
146 | |
147 | typedef void (*SpecialSerializer)(const uint8_t* base, uint32_t offset, |
148 | uint32_t tag, uint32_t has_offset, |
149 | io::CodedOutputStream* output); |
150 | |
151 | PROTOBUF_EXPORT void ExtensionSerializer(const MessageLite* extendee, |
152 | const uint8_t* ptr, uint32_t offset, |
153 | uint32_t tag, uint32_t has_offset, |
154 | io::CodedOutputStream* output); |
155 | PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8_t* base, |
156 | uint32_t offset, uint32_t tag, |
157 | uint32_t has_offset, |
158 | io::CodedOutputStream* output); |
159 | |
160 | PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message); |
161 | PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena, |
162 | MessageLite* submessage, |
163 | Arena* submessage_arena); |
164 | PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2); |
165 | // We specialize GenericSwap for non-lite messages to benefit from reflection. |
166 | PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2); |
167 | |
168 | template <typename T> |
169 | T* DuplicateIfNonNull(T* message) { |
170 | // The casts must be reinterpret_cast<> because T might be a forward-declared |
171 | // type that the compiler doesn't know is related to MessageLite. |
172 | return reinterpret_cast<T*>( |
173 | DuplicateIfNonNullInternal(message: reinterpret_cast<MessageLite*>(message))); |
174 | } |
175 | |
176 | template <typename T> |
177 | T* GetOwnedMessage(Arena* message_arena, T* submessage, |
178 | Arena* submessage_arena) { |
179 | // The casts must be reinterpret_cast<> because T might be a forward-declared |
180 | // type that the compiler doesn't know is related to MessageLite. |
181 | return reinterpret_cast<T*>(GetOwnedMessageInternal( |
182 | message_arena, submessage: reinterpret_cast<MessageLite*>(submessage), |
183 | submessage_arena)); |
184 | } |
185 | |
186 | // Hide atomic from the public header and allow easy change to regular int |
187 | // on platforms where the atomic might have a perf impact. |
188 | class PROTOBUF_EXPORT CachedSize { |
189 | public: |
190 | int Get() const { return size_.load(m: std::memory_order_relaxed); } |
191 | void Set(int size) { size_.store(i: size, m: std::memory_order_relaxed); } |
192 | |
193 | private: |
194 | std::atomic<int> size_{0}; |
195 | }; |
196 | |
197 | PROTOBUF_EXPORT void DestroyMessage(const void* message); |
198 | PROTOBUF_EXPORT void DestroyString(const void* s); |
199 | // Destroy (not delete) the message |
200 | inline void OnShutdownDestroyMessage(const void* ptr) { |
201 | OnShutdownRun(f: DestroyMessage, arg: ptr); |
202 | } |
203 | // Destroy the string (call std::string destructor) |
204 | inline void OnShutdownDestroyString(const std::string* ptr) { |
205 | OnShutdownRun(f: DestroyString, arg: ptr); |
206 | } |
207 | |
208 | } // namespace internal |
209 | } // namespace protobuf |
210 | } // namespace google |
211 | |
212 | #include <google/protobuf/port_undef.inc> |
213 | |
214 | #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ |
215 | |