Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-20 09:13:13

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