Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:12:23

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2008 Google Inc.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
0007 
0008 #ifndef GOOGLE_PROTOBUF_METADATA_LITE_H__
0009 #define GOOGLE_PROTOBUF_METADATA_LITE_H__
0010 
0011 #include <string>
0012 
0013 #include "google/protobuf/arena.h"
0014 #include "google/protobuf/port.h"
0015 
0016 // Must be included last.
0017 #include "google/protobuf/port_def.inc"
0018 
0019 #ifdef SWIG
0020 #error "You cannot SWIG proto headers"
0021 #endif
0022 
0023 namespace google {
0024 namespace protobuf {
0025 
0026 class UnknownFieldSet;
0027 
0028 namespace internal {
0029 
0030 // This is the representation for messages that support arena allocation. It
0031 // uses a tagged pointer to either store the owning Arena pointer, if there are
0032 // no unknown fields, or a pointer to a block of memory with both the owning
0033 // Arena pointer and the UnknownFieldSet, if there are unknown fields. Besides,
0034 // it also uses the tag to distinguish whether the owning Arena pointer is also
0035 // used by sub-structure allocation. This optimization allows for
0036 // "zero-overhead" storage of the Arena pointer, relative to the above baseline
0037 // implementation.
0038 //
0039 // The tagged pointer uses the least two significant bits to disambiguate cases.
0040 // It uses bit 0 == 0 to indicate an arena pointer and bit 0 == 1 to indicate a
0041 // UFS+Arena-container pointer. Besides it uses bit 1 == 0 to indicate arena
0042 // allocation and bit 1 == 1 to indicate heap allocation.
0043 class PROTOBUF_EXPORT InternalMetadata {
0044  public:
0045   constexpr InternalMetadata() : ptr_(0) {}
0046   explicit InternalMetadata(Arena* arena) {
0047     ptr_ = reinterpret_cast<intptr_t>(arena);
0048   }
0049 
0050   // Delete will delete the unknown fields only if they weren't allocated on an
0051   // arena.  Then it updates the flags so that if you call
0052   // have_unknown_fields(), it will return false.
0053   //
0054   // It is designed to be used as part of a Message class's destructor call, so
0055   // that when control eventually gets to ~InternalMetadata(), we don't need to
0056   // check for have_unknown_fields() again.
0057   template <typename T>
0058   void Delete() {
0059     // Note that Delete<> should be called not more than once.
0060     if (have_unknown_fields()) {
0061       DeleteOutOfLineHelper<T>();
0062     }
0063   }
0064 
0065   PROTOBUF_NDEBUG_INLINE Arena* arena() const {
0066     if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
0067       return PtrValue<ContainerBase>()->arena;
0068     } else {
0069       return PtrValue<Arena>();
0070     }
0071   }
0072 
0073   PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const {
0074     return HasUnknownFieldsTag();
0075   }
0076 
0077   PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const {
0078     return reinterpret_cast<void*>(ptr_);
0079   }
0080 
0081   template <typename T>
0082   PROTOBUF_NDEBUG_INLINE const T& unknown_fields(
0083       const T& (*default_instance)()) const {
0084     if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
0085       return PtrValue<Container<T>>()->unknown_fields;
0086     } else {
0087       return default_instance();
0088     }
0089   }
0090 
0091   template <typename T>
0092   PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() {
0093     if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) {
0094       return &PtrValue<Container<T>>()->unknown_fields;
0095     } else {
0096       return mutable_unknown_fields_slow<T>();
0097     }
0098   }
0099 
0100   template <typename T>
0101   PROTOBUF_NDEBUG_INLINE void Swap(InternalMetadata* other) {
0102     // Semantics here are that we swap only the unknown fields, not the arena
0103     // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
0104     // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
0105     // different states (direct arena pointer vs. container with UFS) so we
0106     // cannot simply swap ptr_ and then restore the arena pointers. We reuse
0107     // UFS's swap implementation instead.
0108     if (have_unknown_fields() || other->have_unknown_fields()) {
0109       DoSwap<T>(other->mutable_unknown_fields<T>());
0110     }
0111   }
0112 
0113   PROTOBUF_NDEBUG_INLINE void InternalSwap(
0114       InternalMetadata* PROTOBUF_RESTRICT other) {
0115     std::swap(ptr_, other->ptr_);
0116   }
0117 
0118   template <typename T>
0119   PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) {
0120     if (other.have_unknown_fields()) {
0121       DoMergeFrom<T>(other.unknown_fields<T>(nullptr));
0122     }
0123   }
0124 
0125   template <typename T>
0126   PROTOBUF_NDEBUG_INLINE void Clear() {
0127     if (have_unknown_fields()) {
0128       DoClear<T>();
0129     }
0130   }
0131 
0132  private:
0133   intptr_t ptr_;
0134 
0135   // Tagged pointer implementation.
0136   static constexpr intptr_t kUnknownFieldsTagMask = 1;
0137   static constexpr intptr_t kPtrTagMask = kUnknownFieldsTagMask;
0138   static constexpr intptr_t kPtrValueMask = ~kPtrTagMask;
0139 
0140   // Accessors for pointer tag and pointer value.
0141   PROTOBUF_ALWAYS_INLINE bool HasUnknownFieldsTag() const {
0142     return ptr_ & kUnknownFieldsTagMask;
0143   }
0144 
0145   template <typename U>
0146   U* PtrValue() const {
0147     return reinterpret_cast<U*>(ptr_ & kPtrValueMask);
0148   }
0149 
0150   // If ptr_'s tag is kTagContainer, it points to an instance of this struct.
0151   struct ContainerBase {
0152     Arena* arena;
0153   };
0154 
0155   template <typename T>
0156   struct Container : public ContainerBase {
0157     T unknown_fields;
0158   };
0159 
0160   template <typename T>
0161   PROTOBUF_NOINLINE void DeleteOutOfLineHelper() {
0162     delete PtrValue<Container<T>>();
0163     // TODO:  This store is load-bearing.  Since we are destructing
0164     // the message at this point, see if we can eliminate it.
0165     ptr_ = 0;
0166   }
0167 
0168   template <typename T>
0169   PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() {
0170     Arena* my_arena = arena();
0171     Container<T>* container = Arena::Create<Container<T>>(my_arena);
0172     // Two-step assignment works around a bug in clang's static analyzer:
0173     // https://bugs.llvm.org/show_bug.cgi?id=34198.
0174     ptr_ = reinterpret_cast<intptr_t>(container);
0175     ptr_ |= kUnknownFieldsTagMask;
0176     container->arena = my_arena;
0177     return &(container->unknown_fields);
0178   }
0179 
0180   // Templated functions.
0181 
0182   template <typename T>
0183   PROTOBUF_NOINLINE void DoClear() {
0184     mutable_unknown_fields<T>()->Clear();
0185   }
0186 
0187   template <typename T>
0188   PROTOBUF_NOINLINE void DoMergeFrom(const T& other) {
0189     mutable_unknown_fields<T>()->MergeFrom(other);
0190   }
0191 
0192   template <typename T>
0193   PROTOBUF_NOINLINE void DoSwap(T* other) {
0194     mutable_unknown_fields<T>()->Swap(other);
0195   }
0196 
0197   // Private helper with debug checks for ~InternalMetadata()
0198   void CheckedDestruct();
0199 };
0200 
0201 // String Template specializations.
0202 
0203 template <>
0204 PROTOBUF_EXPORT void InternalMetadata::DoClear<std::string>();
0205 template <>
0206 PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom<std::string>(
0207     const std::string& other);
0208 template <>
0209 PROTOBUF_EXPORT void InternalMetadata::DoSwap<std::string>(std::string* other);
0210 
0211 // Instantiated once in message.cc (where the definition of UnknownFieldSet is
0212 // known) to prevent much duplication across translation units of a large build.
0213 extern template PROTOBUF_EXPORT void
0214 InternalMetadata::DoClear<UnknownFieldSet>();
0215 extern template PROTOBUF_EXPORT void
0216 InternalMetadata::DoMergeFrom<UnknownFieldSet>(const UnknownFieldSet& other);
0217 extern template PROTOBUF_EXPORT void
0218 InternalMetadata::DoSwap<UnknownFieldSet>(UnknownFieldSet* other);
0219 extern template PROTOBUF_EXPORT void
0220 InternalMetadata::DeleteOutOfLineHelper<UnknownFieldSet>();
0221 extern template PROTOBUF_EXPORT UnknownFieldSet*
0222 InternalMetadata::mutable_unknown_fields_slow<UnknownFieldSet>();
0223 
0224 // This helper RAII class is needed to efficiently parse unknown fields. We
0225 // should only call mutable_unknown_fields if there are actual unknown fields.
0226 // The obvious thing to just use a stack string and swap it at the end of
0227 // the parse won't work, because the destructor of StringOutputStream needs to
0228 // be called before we can modify the string (it check-fails). Using
0229 // LiteUnknownFieldSetter setter(&_internal_metadata_);
0230 // StringOutputStream stream(setter.buffer());
0231 // guarantees that the string is only swapped after stream is destroyed.
0232 class PROTOBUF_EXPORT LiteUnknownFieldSetter {
0233  public:
0234   explicit LiteUnknownFieldSetter(InternalMetadata* metadata)
0235       : metadata_(metadata) {
0236     if (metadata->have_unknown_fields()) {
0237       buffer_.swap(*metadata->mutable_unknown_fields<std::string>());
0238     }
0239   }
0240   ~LiteUnknownFieldSetter() {
0241     if (!buffer_.empty())
0242       metadata_->mutable_unknown_fields<std::string>()->swap(buffer_);
0243   }
0244   std::string* buffer() { return &buffer_; }
0245 
0246  private:
0247   InternalMetadata* metadata_;
0248   std::string buffer_;
0249 };
0250 
0251 }  // namespace internal
0252 }  // namespace protobuf
0253 }  // namespace google
0254 
0255 #include "google/protobuf/port_undef.inc"
0256 
0257 #endif  // GOOGLE_PROTOBUF_METADATA_LITE_H__