/src/LPM/external.protobuf/include/google/protobuf/metadata_lite.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 | | // |
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 | | #ifndef GOOGLE_PROTOBUF_METADATA_LITE_H__ |
9 | | #define GOOGLE_PROTOBUF_METADATA_LITE_H__ |
10 | | |
11 | | #include <string> |
12 | | |
13 | | #include "google/protobuf/arena.h" |
14 | | #include "google/protobuf/port.h" |
15 | | |
16 | | // Must be included last. |
17 | | #include "google/protobuf/port_def.inc" |
18 | | |
19 | | #ifdef SWIG |
20 | | #error "You cannot SWIG proto headers" |
21 | | #endif |
22 | | |
23 | | namespace google { |
24 | | namespace protobuf { |
25 | | |
26 | | class UnknownFieldSet; |
27 | | |
28 | | namespace internal { |
29 | | |
30 | | // This is the representation for messages that support arena allocation. It |
31 | | // uses a tagged pointer to either store the owning Arena pointer, if there are |
32 | | // no unknown fields, or a pointer to a block of memory with both the owning |
33 | | // Arena pointer and the UnknownFieldSet, if there are unknown fields. Besides, |
34 | | // it also uses the tag to distinguish whether the owning Arena pointer is also |
35 | | // used by sub-structure allocation. This optimization allows for |
36 | | // "zero-overhead" storage of the Arena pointer, relative to the above baseline |
37 | | // implementation. |
38 | | // |
39 | | // The tagged pointer uses the least two significant bits to disambiguate cases. |
40 | | // It uses bit 0 == 0 to indicate an arena pointer and bit 0 == 1 to indicate a |
41 | | // UFS+Arena-container pointer. Besides it uses bit 1 == 0 to indicate arena |
42 | | // allocation and bit 1 == 1 to indicate heap allocation. |
43 | | class PROTOBUF_EXPORT InternalMetadata { |
44 | | public: |
45 | 0 | constexpr InternalMetadata() : ptr_(0) {} |
46 | 4.08M | explicit InternalMetadata(Arena* arena) { |
47 | 4.08M | ptr_ = reinterpret_cast<intptr_t>(arena); |
48 | 4.08M | } |
49 | | |
50 | | // Delete will delete the unknown fields only if they weren't allocated on an |
51 | | // arena. Then it updates the flags so that if you call |
52 | | // have_unknown_fields(), it will return false. |
53 | | // |
54 | | // It is designed to be used as part of a Message class's destructor call, so |
55 | | // that when control eventually gets to ~InternalMetadata(), we don't need to |
56 | | // check for have_unknown_fields() again. |
57 | | template <typename T> |
58 | 4.08M | void Delete() { |
59 | | // Note that Delete<> should be called not more than once. |
60 | 4.08M | if (have_unknown_fields()) { |
61 | 0 | DeleteOutOfLineHelper<T>(); |
62 | 0 | } |
63 | 4.08M | } |
64 | | |
65 | 1.26M | PROTOBUF_NDEBUG_INLINE Arena* arena() const { |
66 | 1.26M | if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) { |
67 | 0 | return PtrValue<ContainerBase>()->arena; |
68 | 1.26M | } else { |
69 | 1.26M | return PtrValue<Arena>(); |
70 | 1.26M | } |
71 | 1.26M | } |
72 | | |
73 | 5.35M | PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const { |
74 | 5.35M | return HasUnknownFieldsTag(); |
75 | 5.35M | } |
76 | | |
77 | 0 | PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const { |
78 | 0 | return reinterpret_cast<void*>(ptr_); |
79 | 0 | } |
80 | | |
81 | | template <typename T> |
82 | | PROTOBUF_NDEBUG_INLINE const T& unknown_fields( |
83 | 0 | const T& (*default_instance)()) const { |
84 | 0 | if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) { |
85 | 0 | return PtrValue<Container<T>>()->unknown_fields; |
86 | 0 | } else { |
87 | 0 | return default_instance(); |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | | template <typename T> |
92 | 0 | PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() { |
93 | 0 | if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) { |
94 | 0 | return &PtrValue<Container<T>>()->unknown_fields; |
95 | 0 | } else { |
96 | 0 | return mutable_unknown_fields_slow<T>(); |
97 | 0 | } |
98 | 0 | } Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::protobuf::internal::InternalMetadata::mutable_unknown_fields<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >() Unexecuted instantiation: google::protobuf::UnknownFieldSet* google::protobuf::internal::InternalMetadata::mutable_unknown_fields<google::protobuf::UnknownFieldSet>() |
99 | | |
100 | | template <typename T> |
101 | | PROTOBUF_NDEBUG_INLINE void Swap(InternalMetadata* other) { |
102 | | // Semantics here are that we swap only the unknown fields, not the arena |
103 | | // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to |
104 | | // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in |
105 | | // different states (direct arena pointer vs. container with UFS) so we |
106 | | // cannot simply swap ptr_ and then restore the arena pointers. We reuse |
107 | | // UFS's swap implementation instead. |
108 | | if (have_unknown_fields() || other->have_unknown_fields()) { |
109 | | DoSwap<T>(other->mutable_unknown_fields<T>()); |
110 | | } |
111 | | } |
112 | | |
113 | | PROTOBUF_NDEBUG_INLINE void InternalSwap( |
114 | 0 | InternalMetadata* PROTOBUF_RESTRICT other) { |
115 | 0 | std::swap(ptr_, other->ptr_); |
116 | 0 | } |
117 | | |
118 | | template <typename T> |
119 | 722 | PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) { |
120 | 722 | if (other.have_unknown_fields()) { |
121 | 0 | DoMergeFrom<T>(other.unknown_fields<T>(nullptr)); |
122 | 0 | } |
123 | 722 | } |
124 | | |
125 | | template <typename T> |
126 | 6.86k | PROTOBUF_NDEBUG_INLINE void Clear() { |
127 | 6.86k | if (have_unknown_fields()) { |
128 | 0 | DoClear<T>(); |
129 | 0 | } |
130 | 6.86k | } |
131 | | |
132 | | private: |
133 | | intptr_t ptr_; |
134 | | |
135 | | // Tagged pointer implementation. |
136 | | static constexpr intptr_t kUnknownFieldsTagMask = 1; |
137 | | static constexpr intptr_t kPtrTagMask = kUnknownFieldsTagMask; |
138 | | static constexpr intptr_t kPtrValueMask = ~kPtrTagMask; |
139 | | |
140 | | // Accessors for pointer tag and pointer value. |
141 | 5.35M | PROTOBUF_ALWAYS_INLINE bool HasUnknownFieldsTag() const { |
142 | 5.35M | return ptr_ & kUnknownFieldsTagMask; |
143 | 5.35M | } |
144 | | |
145 | | template <typename U> |
146 | 1.26M | U* PtrValue() const { |
147 | 1.26M | return reinterpret_cast<U*>(ptr_ & kPtrValueMask); |
148 | 1.26M | } Unexecuted instantiation: google::protobuf::internal::InternalMetadata::ContainerBase* google::protobuf::internal::InternalMetadata::PtrValue<google::protobuf::internal::InternalMetadata::ContainerBase>() const google::protobuf::Arena* google::protobuf::internal::InternalMetadata::PtrValue<google::protobuf::Arena>() const Line | Count | Source | 146 | 1.26M | U* PtrValue() const { | 147 | 1.26M | return reinterpret_cast<U*>(ptr_ & kPtrValueMask); | 148 | 1.26M | } |
Unexecuted instantiation: google::protobuf::internal::InternalMetadata::Container<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >* google::protobuf::internal::InternalMetadata::PtrValue<google::protobuf::internal::InternalMetadata::Container<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >() const Unexecuted instantiation: google::protobuf::internal::InternalMetadata::Container<google::protobuf::UnknownFieldSet>* google::protobuf::internal::InternalMetadata::PtrValue<google::protobuf::internal::InternalMetadata::Container<google::protobuf::UnknownFieldSet> >() const |
149 | | |
150 | | // If ptr_'s tag is kTagContainer, it points to an instance of this struct. |
151 | | struct ContainerBase { |
152 | | Arena* arena; |
153 | | }; |
154 | | |
155 | | template <typename T> |
156 | | struct Container : public ContainerBase { |
157 | | T unknown_fields; |
158 | | }; |
159 | | |
160 | | template <typename T> |
161 | 0 | PROTOBUF_NOINLINE void DeleteOutOfLineHelper() { |
162 | 0 | delete PtrValue<Container<T>>(); |
163 | 0 | // TODO: This store is load-bearing. Since we are destructing |
164 | 0 | // the message at this point, see if we can eliminate it. |
165 | 0 | ptr_ = 0; |
166 | 0 | } |
167 | | |
168 | | template <typename T> |
169 | 0 | PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() { |
170 | 0 | Arena* my_arena = arena(); |
171 | 0 | Container<T>* container = Arena::Create<Container<T>>(my_arena); |
172 | 0 | // Two-step assignment works around a bug in clang's static analyzer: |
173 | 0 | // https://bugs.llvm.org/show_bug.cgi?id=34198. |
174 | 0 | ptr_ = reinterpret_cast<intptr_t>(container); |
175 | 0 | ptr_ |= kUnknownFieldsTagMask; |
176 | 0 | container->arena = my_arena; |
177 | 0 | return &(container->unknown_fields); |
178 | 0 | } Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::protobuf::internal::InternalMetadata::mutable_unknown_fields_slow<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >() Unexecuted instantiation: google::protobuf::UnknownFieldSet* google::protobuf::internal::InternalMetadata::mutable_unknown_fields_slow<google::protobuf::UnknownFieldSet>() |
179 | | |
180 | | // Templated functions. |
181 | | |
182 | | template <typename T> |
183 | 0 | PROTOBUF_NOINLINE void DoClear() { |
184 | 0 | mutable_unknown_fields<T>()->Clear(); |
185 | 0 | } |
186 | | |
187 | | template <typename T> |
188 | 0 | PROTOBUF_NOINLINE void DoMergeFrom(const T& other) { |
189 | 0 | mutable_unknown_fields<T>()->MergeFrom(other); |
190 | 0 | } |
191 | | |
192 | | template <typename T> |
193 | | PROTOBUF_NOINLINE void DoSwap(T* other) { |
194 | | mutable_unknown_fields<T>()->Swap(other); |
195 | | } |
196 | | |
197 | | // Private helper with debug checks for ~InternalMetadata() |
198 | | void CheckedDestruct(); |
199 | | }; |
200 | | |
201 | | // String Template specializations. |
202 | | |
203 | | template <> |
204 | | PROTOBUF_EXPORT void InternalMetadata::DoClear<std::string>(); |
205 | | template <> |
206 | | PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom<std::string>( |
207 | | const std::string& other); |
208 | | template <> |
209 | | PROTOBUF_EXPORT void InternalMetadata::DoSwap<std::string>(std::string* other); |
210 | | |
211 | | // Instantiated once in message.cc (where the definition of UnknownFieldSet is |
212 | | // known) to prevent much duplication across translation units of a large build. |
213 | | extern template PROTOBUF_EXPORT void |
214 | | InternalMetadata::DoClear<UnknownFieldSet>(); |
215 | | extern template PROTOBUF_EXPORT void |
216 | | InternalMetadata::DoMergeFrom<UnknownFieldSet>(const UnknownFieldSet& other); |
217 | | extern template PROTOBUF_EXPORT void |
218 | | InternalMetadata::DoSwap<UnknownFieldSet>(UnknownFieldSet* other); |
219 | | extern template PROTOBUF_EXPORT void |
220 | | InternalMetadata::DeleteOutOfLineHelper<UnknownFieldSet>(); |
221 | | extern template PROTOBUF_EXPORT UnknownFieldSet* |
222 | | InternalMetadata::mutable_unknown_fields_slow<UnknownFieldSet>(); |
223 | | |
224 | | // This helper RAII class is needed to efficiently parse unknown fields. We |
225 | | // should only call mutable_unknown_fields if there are actual unknown fields. |
226 | | // The obvious thing to just use a stack string and swap it at the end of |
227 | | // the parse won't work, because the destructor of StringOutputStream needs to |
228 | | // be called before we can modify the string (it check-fails). Using |
229 | | // LiteUnknownFieldSetter setter(&_internal_metadata_); |
230 | | // StringOutputStream stream(setter.buffer()); |
231 | | // guarantees that the string is only swapped after stream is destroyed. |
232 | | class PROTOBUF_EXPORT LiteUnknownFieldSetter { |
233 | | public: |
234 | | explicit LiteUnknownFieldSetter(InternalMetadata* metadata) |
235 | 0 | : metadata_(metadata) { |
236 | 0 | if (metadata->have_unknown_fields()) { |
237 | 0 | buffer_.swap(*metadata->mutable_unknown_fields<std::string>()); |
238 | 0 | } |
239 | 0 | } |
240 | 0 | ~LiteUnknownFieldSetter() { |
241 | 0 | if (!buffer_.empty()) |
242 | 0 | metadata_->mutable_unknown_fields<std::string>()->swap(buffer_); |
243 | 0 | } |
244 | 0 | std::string* buffer() { return &buffer_; } |
245 | | |
246 | | private: |
247 | | InternalMetadata* metadata_; |
248 | | std::string buffer_; |
249 | | }; |
250 | | |
251 | | } // namespace internal |
252 | | } // namespace protobuf |
253 | | } // namespace google |
254 | | |
255 | | #include "google/protobuf/port_undef.inc" |
256 | | |
257 | | #endif // GOOGLE_PROTOBUF_METADATA_LITE_H__ |