Coverage Report

Created: 2023-06-07 07:09

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