Back to home page

EIC code displayed by LXR

 
 

    


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

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_ARENASTRING_H__
0009 #define GOOGLE_PROTOBUF_ARENASTRING_H__
0010 
0011 #include <algorithm>
0012 #include <cstdint>
0013 #include <string>
0014 #include <type_traits>
0015 #include <utility>
0016 
0017 #include "absl/log/absl_check.h"
0018 #include "absl/strings/string_view.h"
0019 #include "google/protobuf/arena.h"
0020 #include "google/protobuf/explicitly_constructed.h"
0021 #include "google/protobuf/port.h"
0022 
0023 // must be last:
0024 #include "google/protobuf/port_def.inc"
0025 
0026 #ifdef SWIG
0027 #error "You cannot SWIG proto headers"
0028 #endif
0029 
0030 
0031 namespace google {
0032 namespace protobuf {
0033 namespace internal {
0034 class EpsCopyInputStream;
0035 
0036 class SwapFieldHelper;
0037 
0038 // Declared in message_lite.h
0039 PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString
0040     fixed_address_empty_string;
0041 
0042 // Lazy string instance to support string fields with non-empty default.
0043 // These are initialized on the first call to .get().
0044 class PROTOBUF_EXPORT LazyString {
0045  public:
0046   // We explicitly make LazyString an aggregate so that MSVC can do constant
0047   // initialization on it without marking it `constexpr`.
0048   // We do not want to use `constexpr` because it makes it harder to have extern
0049   // storage for it and causes library bloat.
0050   struct InitValue {
0051     const char* ptr;
0052     size_t size;
0053   };
0054   // We keep a union of the initialization value and the std::string to save on
0055   // space. We don't need the string array after Init() is done.
0056   union {
0057     mutable InitValue init_value_;
0058     alignas(std::string) mutable char string_buf_[sizeof(std::string)];
0059   };
0060   mutable std::atomic<const std::string*> inited_;
0061 
0062   const std::string& get() const {
0063     // This check generates less code than a call-once invocation.
0064     auto* res = inited_.load(std::memory_order_acquire);
0065     if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init();
0066     return *res;
0067   }
0068 
0069  private:
0070   // Initialize the string in `string_buf_`, update `inited_` and return it.
0071   // We return it here to avoid having to read it again in the inlined code.
0072   const std::string& Init() const;
0073 };
0074 
0075 class PROTOBUF_EXPORT TaggedStringPtr {
0076  public:
0077   // Bit flags qualifying string properties. We can use 2 bits as
0078   // ptr_ is guaranteed and enforced to be aligned on 4 byte boundaries.
0079   enum Flags {
0080     kArenaBit = 0x1,    // ptr is arena allocated
0081     kMutableBit = 0x2,  // ptr contents are fully mutable
0082     kMask = 0x3         // Bit mask
0083   };
0084 
0085   // Composed logical types
0086   enum Type {
0087     // Default strings are immutable and never owned.
0088     kDefault = 0,
0089 
0090     // Allocated strings are mutable and (as the name implies) owned.
0091     // A heap allocated string must be deleted.
0092     kAllocated = kMutableBit,
0093 
0094     // Mutable arena strings are strings where the string instance is owned
0095     // by the arena, but the string contents itself are owned by the string
0096     // instance. Mutable arena string instances need to be destroyed which is
0097     // typically done through a cleanup action added to the arena owning it.
0098     kMutableArena = kArenaBit | kMutableBit,
0099 
0100     // Fixed size arena strings are strings where both the string instance and
0101     // the string contents are fully owned by the arena. Fixed size arena
0102     // strings are a platform and c++ library specific customization. Fixed
0103     // size arena strings are immutable, with the exception of custom internal
0104     // updates to the content that fit inside the existing capacity.
0105     // Fixed size arena strings must never be deleted or destroyed.
0106     kFixedSizeArena = kArenaBit,
0107   };
0108 
0109   TaggedStringPtr() = default;
0110   explicit constexpr TaggedStringPtr(ExplicitlyConstructedArenaString* ptr)
0111       : ptr_(ptr) {}
0112 
0113   // Sets the value to `p`, tagging the value as being a 'default' value.
0114   // See documentation for kDefault for more info.
0115   inline const std::string* SetDefault(const std::string* p) {
0116     return TagAs(kDefault, const_cast<std::string*>(p));
0117   }
0118 
0119   // Sets the value to `p`, tagging the value as a heap allocated value.
0120   // Allocated strings are mutable and (as the name implies) owned.
0121   // `p` must not be null
0122   inline std::string* SetAllocated(std::string* p) {
0123     return TagAs(kAllocated, p);
0124   }
0125 
0126   // Sets the value to `p`, tagging the value as a fixed size arena string.
0127   // See documentation for kFixedSizeArena for more info.
0128   // `p` must not be null
0129   inline std::string* SetFixedSizeArena(std::string* p) {
0130     return TagAs(kFixedSizeArena, p);
0131   }
0132 
0133   // Sets the value to `p`, tagging the value as a mutable arena string.
0134   // See documentation for kMutableArena for more info.
0135   // `p` must not be null
0136   inline std::string* SetMutableArena(std::string* p) {
0137     return TagAs(kMutableArena, p);
0138   }
0139 
0140   // Returns true if the contents of the current string are fully mutable.
0141   inline bool IsMutable() const { return as_int() & kMutableBit; }
0142 
0143   // Returns true if the current string is an immutable default value.
0144   inline bool IsDefault() const { return (as_int() & kMask) == kDefault; }
0145 
0146   // If the current string is a heap-allocated mutable value, returns a pointer
0147   // to it.  Returns nullptr otherwise.
0148   inline std::string* GetIfAllocated() const {
0149     auto allocated = as_int() ^ kAllocated;
0150     if (allocated & kMask) return nullptr;
0151 
0152     auto ptr = reinterpret_cast<std::string*>(allocated);
0153     PROTOBUF_ASSUME(ptr != nullptr);
0154     return ptr;
0155   }
0156 
0157   // Returns true if the current string is an arena allocated value.
0158   // This means it's either a mutable or fixed size arena string.
0159   inline bool IsArena() const { return as_int() & kArenaBit; }
0160 
0161   // Returns true if the current string is a fixed size arena allocated value.
0162   inline bool IsFixedSizeArena() const {
0163     return (as_int() & kMask) == kFixedSizeArena;
0164   }
0165 
0166   // Returns the contained string pointer.
0167   inline std::string* Get() const {
0168     return reinterpret_cast<std::string*>(as_int() & ~kMask);
0169   }
0170 
0171   // Returns true if the contained pointer is null, indicating some error.
0172   // The Null value is only used during parsing for temporary values.
0173   // A persisted ArenaStringPtr value is never null.
0174   inline bool IsNull() const { return ptr_ == nullptr; }
0175 
0176   // Returns a copy of this instance. In debug builds, the returned value may be
0177   // a forced copy regardless if the current instance is a compile time default.
0178   TaggedStringPtr Copy(Arena* arena) const;
0179 
0180   // Identical to the above `Copy` function except that in debug builds,
0181   // `default_value` can be used to substitute an empty default with a
0182   // hardened copy of the default value.
0183   TaggedStringPtr Copy(Arena* arena, const LazyString& default_value) const;
0184 
0185  private:
0186   static inline void assert_aligned(const void* p) {
0187     static_assert(kMask <= alignof(void*), "Pointer underaligned for bit mask");
0188     static_assert(kMask <= alignof(std::string),
0189                   "std::string underaligned for bit mask");
0190     ABSL_DCHECK_EQ(reinterpret_cast<uintptr_t>(p) & kMask, 0UL);
0191   }
0192 
0193   // Creates a heap or arena allocated copy of this instance.
0194   TaggedStringPtr ForceCopy(Arena* arena) const;
0195 
0196   inline std::string* TagAs(Type type, std::string* p) {
0197     ABSL_DCHECK(p != nullptr);
0198     assert_aligned(p);
0199     ptr_ = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(p) | type);
0200     return p;
0201   }
0202 
0203   uintptr_t as_int() const { return reinterpret_cast<uintptr_t>(ptr_); }
0204   void* ptr_;
0205 };
0206 
0207 static_assert(std::is_trivial<TaggedStringPtr>::value,
0208               "TaggedStringPtr must be trivial");
0209 
0210 // This class encapsulates a pointer to a std::string with or without arena
0211 // owned contents, tagged by the bottom bits of the string pointer. It is a
0212 // high-level wrapper that almost directly corresponds to the interface required
0213 // by string fields in generated code. It replaces the old std::string* pointer
0214 // in such cases.
0215 //
0216 // The string pointer is tagged to be either a default, externally owned value,
0217 // a mutable heap allocated value, or an arena allocated value. The object uses
0218 // a single global instance of an empty string that is used as the initial
0219 // default value. Fields that have empty default values directly use this global
0220 // default. Fields that have non empty default values are supported through
0221 // lazily initialized default values managed by the LazyString class.
0222 //
0223 // Generated code and reflection code both ensure that ptr_ is never null.
0224 // Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and
0225 // the field is always manually initialized via method calls.
0226 //
0227 // See TaggedStringPtr for more information about the types of string values
0228 // being held, and the mutable and ownership invariants for each type.
0229 struct PROTOBUF_EXPORT ArenaStringPtr {
0230   // Default constructor, leaves current instance uninitialized (does nothing)
0231   ArenaStringPtr() = default;
0232 
0233   // Constexpr constructor, initializes to a constexpr, empty string value.
0234   constexpr ArenaStringPtr(ExplicitlyConstructedArenaString* default_value,
0235                            ConstantInitialized)
0236       : tagged_ptr_(default_value) {}
0237 
0238   // Arena enabled constructor for strings without a default value.
0239   // Initializes this instance to a constexpr, empty string value, unless debug
0240   // hardening is enabled, in which case this instance will hold a forced copy.
0241   explicit ArenaStringPtr(Arena* arena)
0242       : tagged_ptr_(&fixed_address_empty_string) {
0243     if (DebugHardenStringValues()) {
0244       Set(absl::string_view(""), arena);
0245     }
0246   }
0247 
0248   // Arena enabled constructor for strings with a non-empty default value.
0249   // Initializes this instance to a constexpr, empty string value, unless debug
0250   // hardening is enabled, in which case this instance will be forced to hold a
0251   // forced copy of the value in `default_value`.
0252   ArenaStringPtr(Arena* arena, const LazyString& default_value)
0253       : tagged_ptr_(&fixed_address_empty_string) {
0254     if (DebugHardenStringValues()) {
0255       Set(absl::string_view(default_value.get()), arena);
0256     }
0257   }
0258 
0259   // Arena enabled copy constructor for strings without a default value.
0260   // This instance will be initialized with a copy of the value in `rhs`.
0261   // If `rhs` holds a default (empty) value, then this instance will also be
0262   // initialized with the default empty value, unless debug hardening is
0263   // enabled, in which case this instance will be forced to hold a copy of
0264   // an empty default value.
0265   ArenaStringPtr(Arena* arena, const ArenaStringPtr& rhs)
0266       : tagged_ptr_(rhs.tagged_ptr_.Copy(arena)) {}
0267 
0268   // Arena enabled copy constructor for strings with a non-empty default value.
0269   // This instance will be initialized with a copy of the value in `rhs`.
0270   // If `rhs` holds a default (empty) value, then this instance will also be
0271   // initialized with the default empty value, unless debug hardening is
0272   // enabled, in which case this instance will be forced to hold forced copy
0273   // of the value in `default_value`.
0274   ArenaStringPtr(Arena* arena, const ArenaStringPtr& rhs,
0275                  const LazyString& default_value)
0276       : tagged_ptr_(rhs.tagged_ptr_.Copy(arena, default_value)) {}
0277 
0278   // Called from generated code / reflection runtime only. Resets value to point
0279   // to a default string pointer, with the semantics that this ArenaStringPtr
0280   // does not own the pointed-to memory. Disregards initial value of ptr_ (so
0281   // this is the *ONLY* safe method to call after construction or when
0282   // reinitializing after becoming the active field in a oneof union).
0283   inline void InitDefault();
0284 
0285   // Similar to `InitDefault` except that it allows the default value to be
0286   // initialized to an externally owned string. This method is called from
0287   // parsing code. `str` must not be null and outlive this instance.
0288   inline void InitExternal(const std::string* str);
0289 
0290   // Called from generated code / reflection runtime only. Resets the value of
0291   // this instances to the heap allocated value in `str`. `str` must not be
0292   // null. Invokes `arena->Own(str)` to transfer ownership into the arena if
0293   // `arena` is not null, else, `str` will be owned by ArenaStringPtr. This
0294   // function should only be used to initialize a ArenaStringPtr or on an
0295   // instance known to not carry any heap allocated value.
0296   inline void InitAllocated(std::string* str, Arena* arena);
0297 
0298   void Set(absl::string_view value, Arena* arena);
0299   void Set(std::string&& value, Arena* arena);
0300   template <typename... OverloadDisambiguator>
0301   void Set(const std::string& value, Arena* arena);
0302   void Set(const char* s, Arena* arena);
0303   void Set(const char* s, size_t n, Arena* arena);
0304 
0305   void SetBytes(absl::string_view value, Arena* arena);
0306   void SetBytes(std::string&& value, Arena* arena);
0307   template <typename... OverloadDisambiguator>
0308   void SetBytes(const std::string& value, Arena* arena);
0309   void SetBytes(const char* s, Arena* arena);
0310   void SetBytes(const void* p, size_t n, Arena* arena);
0311 
0312   template <typename RefWrappedType>
0313   void Set(std::reference_wrapper<RefWrappedType> const_string_ref,
0314            ::google::protobuf::Arena* arena) {
0315     Set(const_string_ref.get(), arena);
0316   }
0317 
0318   // Returns a mutable std::string reference.
0319   // The version accepting a `LazyString` value is used in the generated code to
0320   // initialize mutable copies for fields with a non-empty default where the
0321   // default value is lazily initialized.
0322   std::string* Mutable(Arena* arena);
0323   std::string* Mutable(const LazyString& default_value, Arena* arena);
0324 
0325   // Gets a mutable pointer with unspecified contents.
0326   // This function is identical to Mutable(), except it is optimized for the
0327   // case where the caller is not interested in the current contents. For
0328   // example, if the current field is not mutable, it will re-initialize the
0329   // value with an empty string rather than a (non-empty) default value.
0330   // Likewise, if the current value is a fixed size arena string with contents,
0331   // it will be initialized into an empty mutable arena string.
0332   std::string* MutableNoCopy(Arena* arena);
0333 
0334   // Basic accessors.
0335   PROTOBUF_NDEBUG_INLINE const std::string& Get() const {
0336     // Unconditionally mask away the tag.
0337     return *tagged_ptr_.Get();
0338   }
0339 
0340   // Returns a pointer to the stored contents for this instance.
0341   // This method is for internal debugging and tracking purposes only.
0342   PROTOBUF_NDEBUG_INLINE const std::string* UnsafeGetPointer() const
0343       ABSL_ATTRIBUTE_RETURNS_NONNULL {
0344     return tagged_ptr_.Get();
0345   }
0346 
0347   // Release returns a std::string* instance that is heap-allocated and is not
0348   // Own()'d by any arena. If the field is not set, this returns nullptr. The
0349   // caller retains ownership. Clears this field back to the default state.
0350   // Used to implement release_<field>() methods on generated classes.
0351   PROTOBUF_NODISCARD std::string* Release();
0352 
0353   // Takes a std::string that is heap-allocated, and takes ownership. The
0354   // std::string's destructor is registered with the arena. Used to implement
0355   // set_allocated_<field> in generated classes.
0356   void SetAllocated(std::string* value, Arena* arena);
0357 
0358   // Frees storage (if not on an arena).
0359   void Destroy();
0360 
0361   // Clears content, but keeps allocated std::string, to avoid the overhead of
0362   // heap operations. After this returns, the content (as seen by the user) will
0363   // always be the empty std::string. Assumes that |default_value| is an empty
0364   // std::string.
0365   void ClearToEmpty();
0366 
0367   // Clears content, assuming that the current value is not the empty
0368   // string default.
0369   void ClearNonDefaultToEmpty();
0370 
0371   // Clears content, but keeps allocated std::string if arena != nullptr, to
0372   // avoid the overhead of heap operations. After this returns, the content
0373   // (as seen by the user) will always be equal to |default_value|.
0374   void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena);
0375 
0376   // Swaps internal pointers. Arena-safety semantics: this is guarded by the
0377   // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
0378   // 'unsafe' if called directly.
0379   inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(ArenaStringPtr* rhs,
0380                                                          ArenaStringPtr* lhs,
0381                                                          Arena* arena);
0382 
0383   // Internal setter used only at parse time to directly set a donated string
0384   // value.
0385   void UnsafeSetTaggedPointer(TaggedStringPtr value) { tagged_ptr_ = value; }
0386   // Generated code only! An optimization, in certain cases the generated
0387   // code is certain we can obtain a std::string with no default checks and
0388   // tag tests.
0389   std::string* UnsafeMutablePointer() ABSL_ATTRIBUTE_RETURNS_NONNULL;
0390 
0391   // Returns true if this instances holds an immutable default value.
0392   inline bool IsDefault() const { return tagged_ptr_.IsDefault(); }
0393 
0394  private:
0395   template <typename... Args>
0396   inline std::string* NewString(Arena* arena, Args&&... args) {
0397     if (arena == nullptr) {
0398       auto* s = new std::string(std::forward<Args>(args)...);
0399       return tagged_ptr_.SetAllocated(s);
0400     } else {
0401       auto* s = Arena::Create<std::string>(arena, std::forward<Args>(args)...);
0402       return tagged_ptr_.SetMutableArena(s);
0403     }
0404   }
0405 
0406   TaggedStringPtr tagged_ptr_;
0407 
0408   bool IsFixedSizeArena() const { return false; }
0409 
0410   // Swaps tagged pointer without debug hardening. This is to allow python
0411   // protobuf to maintain pointer stability even in DEBUG builds.
0412   inline PROTOBUF_NDEBUG_INLINE static void UnsafeShallowSwap(
0413       ArenaStringPtr* rhs, ArenaStringPtr* lhs) {
0414     std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
0415   }
0416 
0417   friend class ::google::protobuf::internal::SwapFieldHelper;
0418   friend class TcParser;
0419 
0420   // Slow paths.
0421 
0422   // MutableSlow requires that !IsString() || IsDefault
0423   // Variadic to support 0 args for empty default and 1 arg for LazyString.
0424   template <typename... Lazy>
0425   std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default);
0426 
0427   friend class EpsCopyInputStream;
0428 };
0429 
0430 inline TaggedStringPtr TaggedStringPtr::Copy(Arena* arena) const {
0431   if (DebugHardenStringValues()) {
0432     // Harden by forcing an allocated string value.
0433     return IsNull() ? *this : ForceCopy(arena);
0434   }
0435   return IsDefault() ? *this : ForceCopy(arena);
0436 }
0437 
0438 inline TaggedStringPtr TaggedStringPtr::Copy(
0439     Arena* arena, const LazyString& default_value) const {
0440   if (DebugHardenStringValues()) {
0441     // Harden by forcing an allocated string value.
0442     TaggedStringPtr hardened(*this);
0443     if (IsDefault()) {
0444       hardened.SetDefault(&default_value.get());
0445     }
0446     return hardened.ForceCopy(arena);
0447   }
0448   return IsDefault() ? *this : ForceCopy(arena);
0449 }
0450 
0451 inline void ArenaStringPtr::InitDefault() {
0452   tagged_ptr_ = TaggedStringPtr(&fixed_address_empty_string);
0453 }
0454 
0455 inline void ArenaStringPtr::InitExternal(const std::string* str) {
0456   tagged_ptr_.SetDefault(str);
0457 }
0458 
0459 inline void ArenaStringPtr::InitAllocated(std::string* str, Arena* arena) {
0460   if (arena != nullptr) {
0461     tagged_ptr_.SetMutableArena(str);
0462     arena->Own(str);
0463   } else {
0464     tagged_ptr_.SetAllocated(str);
0465   }
0466 }
0467 
0468 inline void ArenaStringPtr::Set(const char* s, Arena* arena) {
0469   Set(absl::string_view{s}, arena);
0470 }
0471 
0472 inline void ArenaStringPtr::Set(const char* s, size_t n, Arena* arena) {
0473   Set(absl::string_view{s, n}, arena);
0474 }
0475 
0476 inline void ArenaStringPtr::SetBytes(absl::string_view value, Arena* arena) {
0477   Set(value, arena);
0478 }
0479 
0480 template <>
0481 PROTOBUF_EXPORT void ArenaStringPtr::Set(const std::string& value,
0482                                          Arena* arena);
0483 
0484 template <>
0485 inline void ArenaStringPtr::SetBytes(const std::string& value, Arena* arena) {
0486   Set(value, arena);
0487 }
0488 
0489 inline void ArenaStringPtr::SetBytes(std::string&& value, Arena* arena) {
0490   Set(std::move(value), arena);
0491 }
0492 
0493 inline void ArenaStringPtr::SetBytes(const char* s, Arena* arena) {
0494   Set(s, arena);
0495 }
0496 
0497 inline void ArenaStringPtr::SetBytes(const void* p, size_t n, Arena* arena) {
0498   Set(absl::string_view{static_cast<const char*>(p), n}, arena);
0499 }
0500 
0501 inline PROTOBUF_NDEBUG_INLINE void ArenaStringPtr::InternalSwap(
0502     ArenaStringPtr* rhs, ArenaStringPtr* lhs, Arena* arena) {
0503   // Silence unused variable warnings in release buildls.
0504   (void)arena;
0505   std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_);
0506 #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
0507   for (auto* p : {lhs, rhs}) {
0508     if (p->IsDefault()) continue;
0509     std::string* old_value = p->tagged_ptr_.Get();
0510     std::string* new_value =
0511         p->IsFixedSizeArena()
0512             ? Arena::Create<std::string>(arena, *old_value)
0513             : Arena::Create<std::string>(arena, std::move(*old_value));
0514     if (arena == nullptr) {
0515       delete old_value;
0516       p->tagged_ptr_.SetAllocated(new_value);
0517     } else {
0518       p->tagged_ptr_.SetMutableArena(new_value);
0519     }
0520   }
0521 #endif  // PROTOBUF_FORCE_COPY_IN_SWAP
0522 }
0523 
0524 inline void ArenaStringPtr::ClearNonDefaultToEmpty() {
0525   // Unconditionally mask away the tag.
0526   tagged_ptr_.Get()->clear();
0527 }
0528 
0529 inline std::string* ArenaStringPtr::UnsafeMutablePointer() {
0530   ABSL_DCHECK(tagged_ptr_.IsMutable());
0531   ABSL_DCHECK(tagged_ptr_.Get() != nullptr);
0532   return tagged_ptr_.Get();
0533 }
0534 
0535 
0536 }  // namespace internal
0537 }  // namespace protobuf
0538 }  // namespace google
0539 
0540 #include "google/protobuf/port_undef.inc"
0541 
0542 #endif  // GOOGLE_PROTOBUF_ARENASTRING_H__