Coverage Report

Created: 2023-03-26 07:54

/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
// 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
#ifndef GOOGLE_PROTOBUF_METADATA_LITE_H__
32
#define GOOGLE_PROTOBUF_METADATA_LITE_H__
33
34
#include <string>
35
#include <google/protobuf/stubs/common.h>
36
#include <google/protobuf/arena.h>
37
#include <google/protobuf/port.h>
38
39
// Must be included last.
40
#include <google/protobuf/port_def.inc>
41
42
#ifdef SWIG
43
#error "You cannot SWIG proto headers"
44
#endif
45
46
namespace google {
47
namespace protobuf {
48
namespace internal {
49
50
// This is the representation for messages that support arena allocation. It
51
// uses a tagged pointer to either store the owning Arena pointer, if there are
52
// no unknown fields, or a pointer to a block of memory with both the owning
53
// Arena pointer and the UnknownFieldSet, if there are unknown fields. Besides,
54
// it also uses the tag to distinguish whether the owning Arena pointer is also
55
// used by sub-structure allocation. This optimization allows for
56
// "zero-overhead" storage of the Arena pointer, relative to the above baseline
57
// implementation.
58
//
59
// The tagged pointer uses the least two significant bits to disambiguate cases.
60
// It uses bit 0 == 0 to indicate an arena pointer and bit 0 == 1 to indicate a
61
// UFS+Arena-container pointer. Besides it uses bit 1 == 0 to indicate arena
62
// allocation and bit 1 == 1 to indicate heap allocation.
63
class PROTOBUF_EXPORT InternalMetadata {
64
 public:
65
0
  constexpr InternalMetadata() : ptr_(0) {}
66
683k
  explicit InternalMetadata(Arena* arena, bool is_message_owned = false) {
67
683k
    SetArena(arena, is_message_owned);
68
683k
  }
69
70
683k
  void SetArena(Arena* arena, bool is_message_owned) {
71
683k
    ptr_ = is_message_owned
72
683k
               ? reinterpret_cast<intptr_t>(arena) | kMessageOwnedArenaTagMask
73
683k
               : reinterpret_cast<intptr_t>(arena);
74
683k
    GOOGLE_DCHECK(!is_message_owned || arena != nullptr);
75
683k
  }
76
77
  // To keep the ABI identical between debug and non-debug builds,
78
  // the destructor is always defined here even though it may delegate
79
  // to a non-inline private method.
80
  // (see https://github.com/protocolbuffers/protobuf/issues/9947)
81
683k
  ~InternalMetadata() {
82
683k
#if defined(NDEBUG) || defined(_MSC_VER)
83
683k
    if (HasMessageOwnedArenaTag()) {
84
0
      delete reinterpret_cast<Arena*>(ptr_ - kMessageOwnedArenaTagMask);
85
0
    }
86
#else
87
    CheckedDestruct();
88
#endif
89
683k
  }
90
91
  template <typename T>
92
  void Delete() {
93
    // Note that Delete<> should be called not more than once.
94
    if (have_unknown_fields()) {
95
      DeleteOutOfLineHelper<T>();
96
    }
97
  }
98
99
  // DeleteReturnArena will delete the unknown fields only if they weren't
100
  // allocated on an arena.  Then it updates the flags so that if you call
101
  // have_unknown_fields(), it will return false.  Finally, it returns the
102
  // current value of arena().  It is designed to be used as part of a
103
  // Message class's destructor call, so that when control eventually gets
104
  // to ~InternalMetadata(), we don't need to check for have_unknown_fields()
105
  // again.
106
  template <typename T>
107
683k
  Arena* DeleteReturnArena() {
108
683k
    if (have_unknown_fields()) {
109
0
      return DeleteOutOfLineHelper<T>();
110
683k
    } else {
111
683k
      return PtrValue<Arena>();
112
683k
    }
113
683k
  }
114
115
0
  PROTOBUF_NDEBUG_INLINE Arena* owning_arena() const {
116
0
    return HasMessageOwnedArenaTag() ? nullptr : arena();
117
0
  }
118
119
0
  PROTOBUF_NDEBUG_INLINE Arena* user_arena() const {
120
0
    Arena* a = arena();
121
0
    return a && !a->IsMessageOwned() ? a : nullptr;
122
0
  }
123
124
108k
  PROTOBUF_NDEBUG_INLINE Arena* arena() const {
125
108k
    if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
126
0
      return PtrValue<ContainerBase>()->arena;
127
108k
    } else {
128
108k
      return PtrValue<Arena>();
129
108k
    }
130
108k
  }
131
132
817k
  PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const {
133
817k
    return HasUnknownFieldsTag();
134
817k
  }
135
136
0
  PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const {
137
0
    return reinterpret_cast<void*>(ptr_);
138
0
  }
139
140
  template <typename T>
141
  PROTOBUF_NDEBUG_INLINE const T& unknown_fields(
142
0
      const T& (*default_instance)()) const {
143
0
    if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
144
0
      return PtrValue<Container<T>>()->unknown_fields;
145
0
    } else {
146
0
      return default_instance();
147
0
    }
148
0
  }
149
150
  template <typename T>
151
0
  PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() {
152
0
    if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) {
153
0
      return &PtrValue<Container<T>>()->unknown_fields;
154
0
    } else {
155
0
      return mutable_unknown_fields_slow<T>();
156
0
    }
157
0
  }
Unexecuted instantiation: google::protobuf::UnknownFieldSet* google::protobuf::internal::InternalMetadata::mutable_unknown_fields<google::protobuf::UnknownFieldSet>()
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> > >()
158
159
  template <typename T>
160
  PROTOBUF_NDEBUG_INLINE void Swap(InternalMetadata* other) {
161
    // Semantics here are that we swap only the unknown fields, not the arena
162
    // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
163
    // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
164
    // different states (direct arena pointer vs. container with UFS) so we
165
    // cannot simply swap ptr_ and then restore the arena pointers. We reuse
166
    // UFS's swap implementation instead.
167
    if (have_unknown_fields() || other->have_unknown_fields()) {
168
      DoSwap<T>(other->mutable_unknown_fields<T>());
169
    }
170
  }
171
172
0
  PROTOBUF_NDEBUG_INLINE void InternalSwap(InternalMetadata* other) {
173
0
    std::swap(ptr_, other->ptr_);
174
0
  }
175
176
  template <typename T>
177
0
  PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) {
178
0
    if (other.have_unknown_fields()) {
179
0
      DoMergeFrom<T>(other.unknown_fields<T>(nullptr));
180
0
    }
181
0
  }
182
183
  template <typename T>
184
24.6k
  PROTOBUF_NDEBUG_INLINE void Clear() {
185
24.6k
    if (have_unknown_fields()) {
186
0
      DoClear<T>();
187
0
    }
188
24.6k
  }
189
190
 private:
191
  intptr_t ptr_;
192
193
  // Tagged pointer implementation.
194
  static constexpr intptr_t kUnknownFieldsTagMask = 1;
195
  static constexpr intptr_t kMessageOwnedArenaTagMask = 2;
196
  static constexpr intptr_t kPtrTagMask =
197
      kUnknownFieldsTagMask | kMessageOwnedArenaTagMask;
198
  static constexpr intptr_t kPtrValueMask = ~kPtrTagMask;
199
200
  // Accessors for pointer tag and pointer value.
201
817k
  PROTOBUF_ALWAYS_INLINE bool HasUnknownFieldsTag() const {
202
817k
    return ptr_ & kUnknownFieldsTagMask;
203
817k
  }
204
683k
  PROTOBUF_ALWAYS_INLINE bool HasMessageOwnedArenaTag() const {
205
683k
    return ptr_ & kMessageOwnedArenaTagMask;
206
683k
  }
207
208
  template <typename U>
209
792k
  U* PtrValue() const {
210
792k
    return reinterpret_cast<U*>(ptr_ & kPtrValueMask);
211
792k
  }
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
209
792k
  U* PtrValue() const {
210
792k
    return reinterpret_cast<U*>(ptr_ & kPtrValueMask);
211
792k
  }
Unexecuted instantiation: google::protobuf::internal::InternalMetadata::Container<google::protobuf::UnknownFieldSet>* google::protobuf::internal::InternalMetadata::PtrValue<google::protobuf::internal::InternalMetadata::Container<google::protobuf::UnknownFieldSet> >() const
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
212
213
  // If ptr_'s tag is kTagContainer, it points to an instance of this struct.
214
  struct ContainerBase {
215
    Arena* arena;
216
  };
217
218
  template <typename T>
219
  struct Container : public ContainerBase {
220
    T unknown_fields;
221
  };
222
223
  template <typename T>
224
0
  PROTOBUF_NOINLINE Arena* DeleteOutOfLineHelper() {
225
0
    if (auto* a = arena()) {
226
      // Subtle: we want to preserve the message-owned arena flag, while at the
227
      // same time replacing the pointer to Container<T> with a pointer to the
228
      // arena.
229
0
      intptr_t message_owned_arena_tag = ptr_ & kMessageOwnedArenaTagMask;
230
0
      ptr_ = reinterpret_cast<intptr_t>(a) | message_owned_arena_tag;
231
0
      return a;
232
0
    } else {
233
0
      delete PtrValue<Container<T>>();
234
0
      ptr_ = 0;
235
0
      return nullptr;
236
0
    }
237
0
  }
238
239
  template <typename T>
240
0
  PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() {
241
0
    Arena* my_arena = arena();
242
0
    Container<T>* container = Arena::Create<Container<T>>(my_arena);
243
0
    intptr_t message_owned_arena_tag = ptr_ & kMessageOwnedArenaTagMask;
244
    // Two-step assignment works around a bug in clang's static analyzer:
245
    // https://bugs.llvm.org/show_bug.cgi?id=34198.
246
0
    ptr_ = reinterpret_cast<intptr_t>(container);
247
0
    ptr_ |= kUnknownFieldsTagMask | message_owned_arena_tag;
248
0
    container->arena = my_arena;
249
0
    return &(container->unknown_fields);
250
0
  }
Unexecuted instantiation: google::protobuf::UnknownFieldSet* google::protobuf::internal::InternalMetadata::mutable_unknown_fields_slow<google::protobuf::UnknownFieldSet>()
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> > >()
251
252
  // Templated functions.
253
254
  template <typename T>
255
0
  PROTOBUF_NOINLINE void DoClear() {
256
0
    mutable_unknown_fields<T>()->Clear();
257
0
  }
258
259
  template <typename T>
260
0
  PROTOBUF_NOINLINE void DoMergeFrom(const T& other) {
261
0
    mutable_unknown_fields<T>()->MergeFrom(other);
262
0
  }
263
264
  template <typename T>
265
  PROTOBUF_NOINLINE void DoSwap(T* other) {
266
    mutable_unknown_fields<T>()->Swap(other);
267
  }
268
269
  // Private helper with debug checks for ~InternalMetadata()
270
  void CheckedDestruct();
271
};
272
273
// String Template specializations.
274
275
template <>
276
PROTOBUF_EXPORT void InternalMetadata::DoClear<std::string>();
277
template <>
278
PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom<std::string>(
279
    const std::string& other);
280
template <>
281
PROTOBUF_EXPORT void InternalMetadata::DoSwap<std::string>(std::string* other);
282
283
// This helper RAII class is needed to efficiently parse unknown fields. We
284
// should only call mutable_unknown_fields if there are actual unknown fields.
285
// The obvious thing to just use a stack string and swap it at the end of
286
// the parse won't work, because the destructor of StringOutputStream needs to
287
// be called before we can modify the string (it check-fails). Using
288
// LiteUnknownFieldSetter setter(&_internal_metadata_);
289
// StringOutputStream stream(setter.buffer());
290
// guarantees that the string is only swapped after stream is destroyed.
291
class PROTOBUF_EXPORT LiteUnknownFieldSetter {
292
 public:
293
  explicit LiteUnknownFieldSetter(InternalMetadata* metadata)
294
0
      : metadata_(metadata) {
295
0
    if (metadata->have_unknown_fields()) {
296
0
      buffer_.swap(*metadata->mutable_unknown_fields<std::string>());
297
0
    }
298
0
  }
299
0
  ~LiteUnknownFieldSetter() {
300
0
    if (!buffer_.empty())
301
0
      metadata_->mutable_unknown_fields<std::string>()->swap(buffer_);
302
0
  }
303
0
  std::string* buffer() { return &buffer_; }
304
305
 private:
306
  InternalMetadata* metadata_;
307
  std::string buffer_;
308
};
309
310
}  // namespace internal
311
}  // namespace protobuf
312
}  // namespace google
313
314
#include <google/protobuf/port_undef.inc>
315
316
#endif  // GOOGLE_PROTOBUF_METADATA_LITE_H__