Back to home page

EIC code displayed by LXR

 
 

    


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

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_INLINED_STRING_FIELD_H__
0009 #define GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
0010 
0011 #include <string>
0012 #include <utility>
0013 
0014 #include "absl/log/absl_check.h"
0015 #include "absl/strings/string_view.h"
0016 #include "google/protobuf/arenastring.h"
0017 #include "google/protobuf/explicitly_constructed.h"
0018 #include "google/protobuf/message_lite.h"
0019 #include "google/protobuf/port.h"
0020 
0021 // Must be included last.
0022 #include "google/protobuf/port_def.inc"
0023 
0024 #ifdef SWIG
0025 #error "You cannot SWIG proto headers"
0026 #endif
0027 
0028 namespace google {
0029 namespace protobuf {
0030 
0031 class Arena;
0032 
0033 namespace internal {
0034 
0035 // InlinedStringField wraps a std::string instance and exposes an API similar to
0036 // ArenaStringPtr's wrapping of a std::string* instance.
0037 //
0038 // default_value parameters are taken for consistency with ArenaStringPtr, but
0039 // are not used for most methods. With inlining, these should be removed from
0040 // the generated binary.
0041 //
0042 // InlinedStringField has a donating mechanism that allows string buffer
0043 // allocated on arena. A string is donated means both the string container and
0044 // the data buffer are on arena. The donating mechanism here is similar to the
0045 // one in ArenaStringPtr with some differences:
0046 //
0047 // When an InlinedStringField is constructed, the donating state is true. This
0048 // is because the string container is directly stored in the message on the
0049 // arena:
0050 //
0051 //   Construction: donated=true
0052 //   Arena:
0053 //   +-----------------------+
0054 //   |Message foo:           |
0055 //   | +-------------------+ |
0056 //   | |InlinedStringField:| |
0057 //   | | +-----+           | |
0058 //   | | | | | |           | |
0059 //   | | +-----+           | |
0060 //   | +-------------------+ |
0061 //   +-----------------------+
0062 //
0063 // When lvalue Set is called, the donating state is still true. String data will
0064 // be allocated on the arena:
0065 //
0066 //   Lvalue Set: donated=true
0067 //   Arena:
0068 //   +-----------------------+
0069 //   |Message foo:           |
0070 //   | +-------------------+ |
0071 //   | |InlinedStringField:| |
0072 //   | | +-----+           | |
0073 //   | | | | | |           | |
0074 //   | | +|----+           | |
0075 //   | +--|----------------+ |
0076 //   |    V                  |
0077 //   |  +----------------+   |
0078 //   |  |'f','o','o',... |   |
0079 //   |  +----------------+   |
0080 //   +-----------------------+
0081 //
0082 // Some operations will undonate a donated string, including: Mutable,
0083 // SetAllocated, Rvalue Set, and Swap with a non-donated string.
0084 //
0085 // For more details of the donating states transitions, go/pd-inlined-string.
0086 class PROTOBUF_EXPORT InlinedStringField {
0087  public:
0088   InlinedStringField() : str_() {}
0089   InlinedStringField(const InlinedStringField&) = delete;
0090   InlinedStringField& operator=(const InlinedStringField&) = delete;
0091 #if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L
0092   // No need to do dynamic initialization here.
0093   constexpr void Init() {}
0094   // Add the dummy parameter just to make InlinedStringField(nullptr)
0095   // unambiguous.
0096   constexpr InlinedStringField(
0097       const ExplicitlyConstructed<std::string>* /*default_value*/,
0098       bool /*dummy*/)
0099       : str_{} {}
0100 #else
0101   inline void Init() { ::new (static_cast<void*>(&str_)) std::string(); }
0102   // Add the dummy parameter just to make InlinedStringField(nullptr)
0103   // unambiguous.
0104   constexpr InlinedStringField(
0105       const ExplicitlyConstructed<std::string>* /*default_value*/,
0106       bool /*dummy*/)
0107       : dummy_{} {}
0108 #endif
0109 
0110   explicit InlinedStringField(const std::string& default_value);
0111   explicit InlinedStringField(Arena* arena);
0112   InlinedStringField(Arena* arena, const InlinedStringField& rhs);
0113   ~InlinedStringField() { Destruct(); }
0114 
0115   // Lvalue Set. To save space, we pack the donating states of multiple
0116   // InlinedStringFields into an uint32_t `donating_states`. The `mask`
0117   // indicates the position of the bit for this InlinedStringField. `donated` is
0118   // whether this field is donated.
0119   //
0120   // The caller should guarantee that:
0121   //
0122   //   `donated == ((donating_states & ~mask) != 0)`
0123   //
0124   // This method never changes the `donating_states`.
0125   void Set(absl::string_view value, Arena* arena, bool donated,
0126            uint32_t* donating_states, uint32_t mask, MessageLite* msg);
0127 
0128   // Rvalue Set. If this field is donated, this method will undonate this field
0129   // by mutating the `donating_states` according to `mask`.
0130   void Set(std::string&& value, Arena* arena, bool donated,
0131            uint32_t* donating_states, uint32_t mask, MessageLite* msg);
0132 
0133   void Set(const char* str, ::google::protobuf::Arena* arena, bool donated,
0134            uint32_t* donating_states, uint32_t mask, MessageLite* msg);
0135 
0136   void Set(const char* str, size_t size, ::google::protobuf::Arena* arena, bool donated,
0137            uint32_t* donating_states, uint32_t mask, MessageLite* msg);
0138 
0139   template <typename RefWrappedType>
0140   void Set(std::reference_wrapper<RefWrappedType> const_string_ref,
0141            ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
0142            uint32_t mask, MessageLite* msg);
0143 
0144   void SetBytes(absl::string_view value, Arena* arena, bool donated,
0145                 uint32_t* donating_states, uint32_t mask, MessageLite* msg);
0146 
0147   void SetBytes(std::string&& value, Arena* arena, bool donated,
0148                 uint32_t* donating_states, uint32_t mask, MessageLite* msg);
0149 
0150   void SetBytes(const char* str, ::google::protobuf::Arena* arena, bool donated,
0151                 uint32_t* donating_states, uint32_t mask, MessageLite* msg);
0152 
0153   void SetBytes(const void* p, size_t size, ::google::protobuf::Arena* arena,
0154                 bool donated, uint32_t* donating_states, uint32_t mask,
0155                 MessageLite* msg);
0156 
0157   template <typename RefWrappedType>
0158   void SetBytes(std::reference_wrapper<RefWrappedType> const_string_ref,
0159                 ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
0160                 uint32_t mask, MessageLite* msg);
0161 
0162   PROTOBUF_NDEBUG_INLINE void SetNoArena(absl::string_view value);
0163   PROTOBUF_NDEBUG_INLINE void SetNoArena(std::string&& value);
0164 
0165   // Basic accessors.
0166   PROTOBUF_NDEBUG_INLINE const std::string& Get() const { return GetNoArena(); }
0167   PROTOBUF_NDEBUG_INLINE const std::string& GetNoArena() const;
0168 
0169   // Mutable returns a std::string* instance that is heap-allocated. If this
0170   // field is donated, this method undonates this field by mutating the
0171   // `donating_states` according to `mask`, and copies the content of the
0172   // original string to the returning string.
0173   std::string* Mutable(Arena* arena, bool donated, uint32_t* donating_states,
0174                        uint32_t mask, MessageLite* msg);
0175   std::string* Mutable(const LazyString& default_value, Arena* arena,
0176                        bool donated, uint32_t* donating_states, uint32_t mask,
0177                        MessageLite* msg);
0178 
0179   // Mutable(nullptr_t) is an overload to explicitly support Mutable(nullptr)
0180   // calls used by the internal parser logic. This provides API equivalence with
0181   // ArenaStringPtr, while still protecting against calls with arena pointers.
0182   std::string* Mutable(std::nullptr_t);
0183   std::string* MutableNoCopy(std::nullptr_t);
0184 
0185   // Takes a std::string that is heap-allocated, and takes ownership. The
0186   // std::string's destructor is registered with the arena. Used to implement
0187   // set_allocated_<field> in generated classes.
0188   //
0189   // If this field is donated, this method undonates this field by mutating the
0190   // `donating_states` according to `mask`.
0191   void SetAllocated(const std::string* default_value, std::string* value,
0192                     Arena* arena, bool donated, uint32_t* donating_states,
0193                     uint32_t mask, MessageLite* msg);
0194 
0195   void SetAllocatedNoArena(const std::string* default_value,
0196                            std::string* value);
0197 
0198   // Release returns a std::string* instance that is heap-allocated and is not
0199   // Own()'d by any arena. If the field is not set, this returns nullptr. The
0200   // caller retains ownership. Clears this field back to nullptr state. Used to
0201   // implement release_<field>() methods on generated classes.
0202   [[nodiscard]] std::string* Release(Arena* arena, bool donated);
0203   [[nodiscard]] std::string* Release();
0204 
0205   // --------------------------------------------------------
0206   // Below functions will be removed in subsequent code change
0207   // --------------------------------------------------------
0208 #ifdef DEPRECATED_METHODS_TO_BE_DELETED
0209   [[nodiscard]] std::string* Release(const std::string*, Arena* arena,
0210                                      bool donated) {
0211     return Release(arena, donated);
0212   }
0213 
0214   [[nodiscard]] std::string* ReleaseNonDefault(const std::string*,
0215                                                Arena* arena) {
0216     return Release();
0217   }
0218 
0219   std::string* ReleaseNonDefaultNoArena(const std::string* default_value) {
0220     return Release();
0221   }
0222 
0223   void Set(const std::string*, absl::string_view value, Arena* arena,
0224            bool donated, uint32_t* donating_states, uint32_t mask,
0225            MessageLite* msg) {
0226     Set(value, arena, donated, donating_states, mask, msg);
0227   }
0228 
0229   void Set(const std::string*, std::string&& value, Arena* arena, bool donated,
0230            uint32_t* donating_states, uint32_t mask, MessageLite* msg) {
0231     Set(std::move(value), arena, donated, donating_states, mask, msg);
0232   }
0233 
0234 
0235   template <typename FirstParam>
0236   void Set(FirstParam, const char* str, ::google::protobuf::Arena* arena, bool donated,
0237            uint32_t* donating_states, uint32_t mask, MessageLite* msg) {
0238     Set(str, arena, donated, donating_states, mask, msg);
0239   }
0240 
0241   template <typename FirstParam>
0242   void Set(FirstParam p1, const char* str, size_t size, ::google::protobuf::Arena* arena,
0243            bool donated, uint32_t* donating_states, uint32_t mask,
0244            MessageLite* msg) {
0245     Set(str, size, arena, donated, donating_states, mask, msg);
0246   }
0247 
0248   template <typename FirstParam, typename RefWrappedType>
0249   void Set(FirstParam p1,
0250            std::reference_wrapper<RefWrappedType> const_string_ref,
0251            ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
0252            uint32_t mask, MessageLite* msg) {
0253     Set(const_string_ref, arena, donated, donating_states, mask, msg);
0254   }
0255 
0256   void SetBytes(const std::string*, absl::string_view value, Arena* arena,
0257                 bool donated, uint32_t* donating_states, uint32_t mask,
0258                 MessageLite* msg) {
0259     Set(value, arena, donated, donating_states, mask, msg);
0260   }
0261 
0262 
0263   void SetBytes(const std::string*, std::string&& value, Arena* arena,
0264                 bool donated, uint32_t* donating_states, uint32_t mask,
0265                 MessageLite* msg) {
0266     Set(std::move(value), arena, donated, donating_states, mask, msg);
0267   }
0268 
0269   template <typename FirstParam>
0270   void SetBytes(FirstParam p1, const char* str, ::google::protobuf::Arena* arena,
0271                 bool donated, uint32_t* donating_states, uint32_t mask,
0272                 MessageLite* msg) {
0273     SetBytes(str, arena, donated, donating_states, mask, msg);
0274   }
0275 
0276   template <typename FirstParam>
0277   void SetBytes(FirstParam p1, const void* p, size_t size,
0278                 ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
0279                 uint32_t mask, MessageLite* msg) {
0280     SetBytes(p, size, arena, donated, donating_states, mask, msg);
0281   }
0282 
0283   template <typename FirstParam, typename RefWrappedType>
0284   void SetBytes(FirstParam p1,
0285                 std::reference_wrapper<RefWrappedType> const_string_ref,
0286                 ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
0287                 uint32_t mask, MessageLite* msg) {
0288     SetBytes(const_string_ref.get(), arena, donated, donating_states, mask,
0289              msg);
0290   }
0291 
0292   void SetNoArena(const std::string*, absl::string_view value) {
0293     SetNoArena(value);
0294   }
0295   void SetNoArena(const std::string*, std::string&& value) {
0296     SetNoArena(std::move(value));
0297   }
0298 
0299   std::string* Mutable(ArenaStringPtr::EmptyDefault, Arena* arena, bool donated,
0300                        uint32_t* donating_states, uint32_t mask,
0301                        MessageLite* msg) {
0302     return Mutable(arena, donated, donating_states, mask, msg);
0303   }
0304 
0305   PROTOBUF_NDEBUG_INLINE std::string* MutableNoArenaNoDefault(
0306       const std::string* /*default_value*/) {
0307     return MutableNoCopy(nullptr);
0308   }
0309 
0310 #endif  // DEPRECATED_METHODS_TO_BE_DELETED
0311 
0312   // Arena-safety semantics: this is guarded by the logic in
0313   // Swap()/UnsafeArenaSwap() at the message level, so this method is
0314   // 'unsafe' if called directly.
0315   PROTOBUF_NDEBUG_INLINE static void InternalSwap(
0316       InlinedStringField* lhs, bool lhs_arena_dtor_registered,
0317       MessageLite* lhs_msg,  //
0318       InlinedStringField* rhs, bool rhs_arena_dtor_registered,
0319       MessageLite* rhs_msg, Arena* arena);
0320 
0321   // Frees storage (if not on an arena).
0322   PROTOBUF_NDEBUG_INLINE void Destroy(const std::string* default_value,
0323                                       Arena* arena) {
0324     if (arena == nullptr) {
0325       DestroyNoArena(default_value);
0326     }
0327   }
0328   PROTOBUF_NDEBUG_INLINE void DestroyNoArena(const std::string* default_value);
0329 
0330   // Clears content, but keeps allocated std::string, to avoid the overhead of
0331   // heap operations. After this returns, the content (as seen by the user) will
0332   // always be the empty std::string.
0333   PROTOBUF_NDEBUG_INLINE void ClearToEmpty() { ClearNonDefaultToEmpty(); }
0334   PROTOBUF_NDEBUG_INLINE void ClearNonDefaultToEmpty() {
0335     get_mutable()->clear();
0336   }
0337 
0338   // Clears content, but keeps allocated std::string if arena != nullptr, to
0339   // avoid the overhead of heap operations. After this returns, the content (as
0340   // seen by the user) will always be equal to |default_value|.
0341   void ClearToDefault(const LazyString& default_value, Arena* arena,
0342                       bool donated);
0343 
0344   // Generated code / reflection only! Returns a mutable pointer to the string.
0345   PROTOBUF_NDEBUG_INLINE std::string* UnsafeMutablePointer();
0346 
0347   // InlinedStringField doesn't have things like the `default_value` pointer in
0348   // ArenaStringPtr.
0349   static constexpr bool IsDefault() { return false; }
0350   static constexpr bool IsDefault(const std::string*) { return false; }
0351 
0352  private:
0353   // ScopedCheckInvariants checks all string in-variants at destruction.
0354   class ScopedCheckInvariants;
0355 
0356   void Destruct() { get_mutable()->~basic_string(); }
0357 
0358   PROTOBUF_NDEBUG_INLINE std::string* get_mutable();
0359   PROTOBUF_NDEBUG_INLINE const std::string* get_const() const;
0360 
0361   union {
0362     std::string str_;
0363     char dummy_;
0364   };
0365 
0366   std::string* MutableSlow(::google::protobuf::Arena* arena, bool donated,
0367                            uint32_t* donating_states, uint32_t mask,
0368                            MessageLite* msg);
0369 
0370 
0371   // When constructed in an Arena, we want our destructor to be skipped.
0372   friend class ::google::protobuf::Arena;
0373   typedef void InternalArenaConstructable_;
0374   typedef void DestructorSkippable_;
0375 };
0376 
0377 inline std::string* InlinedStringField::get_mutable() { return &str_; }
0378 
0379 inline const std::string* InlinedStringField::get_const() const {
0380   return &str_;
0381 }
0382 
0383 inline InlinedStringField::InlinedStringField(
0384     const std::string& default_value) {
0385   new (get_mutable()) std::string(default_value);
0386 }
0387 
0388 
0389 #ifdef GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
0390 constexpr uint32_t InitDonatingStates() { return ~0u; }
0391 inline void InternalRegisterArenaDtor(Arena*, void*, void (*)(void*)) {}
0392 #else   // !GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
0393 constexpr uint32_t InitDonatingStates() { return 0u; }
0394 inline void InternalRegisterArenaDtor(Arena* arena, void* object,
0395                                       void (*destruct)(void*)) {
0396   if (arena != nullptr) {
0397     arena->OwnCustomDestructor(object, destruct);
0398   }
0399 }
0400 #endif  // GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
0401 
0402 inline InlinedStringField::InlinedStringField(Arena* /*arena*/) : str_() {}
0403 
0404 inline InlinedStringField::InlinedStringField([[maybe_unused]] Arena* arena,
0405                                               const InlinedStringField& rhs) {
0406   const std::string& src = *rhs.get_const();
0407   ::new (static_cast<void*>(&str_)) std::string(src);
0408 }
0409 
0410 inline const std::string& InlinedStringField::GetNoArena() const {
0411   return *get_const();
0412 }
0413 
0414 inline void InlinedStringField::SetAllocatedNoArena(
0415     const std::string* /*default_value*/, std::string* value) {
0416   if (value == nullptr) {
0417     // Currently, inlined string field can't have non empty default.
0418     get_mutable()->clear();
0419   } else {
0420     get_mutable()->assign(std::move(*value));
0421     delete value;
0422   }
0423 }
0424 
0425 inline void InlinedStringField::DestroyNoArena(const std::string*) {
0426   // This is invoked from the generated message's ArenaDtor, which is used to
0427   // clean up objects not allocated on the Arena.
0428   this->~InlinedStringField();
0429 }
0430 
0431 inline void InlinedStringField::SetNoArena(absl::string_view value) {
0432   get_mutable()->assign(value.data(), value.length());
0433 }
0434 
0435 inline void InlinedStringField::SetNoArena(std::string&& value) {
0436   get_mutable()->assign(std::move(value));
0437 }
0438 
0439 PROTOBUF_NDEBUG_INLINE void InlinedStringField::InternalSwap(
0440     InlinedStringField* lhs, bool lhs_arena_dtor_registered,
0441     MessageLite* lhs_msg,  //
0442     InlinedStringField* rhs, bool rhs_arena_dtor_registered,
0443     MessageLite* rhs_msg, Arena* arena) {
0444 #ifdef GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
0445   lhs->get_mutable()->swap(*rhs->get_mutable());
0446   if (!lhs_arena_dtor_registered && rhs_arena_dtor_registered) {
0447     lhs_msg->OnDemandRegisterArenaDtor(arena);
0448   } else if (lhs_arena_dtor_registered && !rhs_arena_dtor_registered) {
0449     rhs_msg->OnDemandRegisterArenaDtor(arena);
0450   }
0451 #else
0452   (void)arena;
0453   (void)lhs_arena_dtor_registered;
0454   (void)rhs_arena_dtor_registered;
0455   (void)lhs_msg;
0456   (void)rhs_msg;
0457   lhs->get_mutable()->swap(*rhs->get_mutable());
0458 #endif
0459 }
0460 
0461 inline void InlinedStringField::Set(absl::string_view value, Arena* arena,
0462                                     bool donated, uint32_t* /*donating_states*/,
0463                                     uint32_t /*mask*/, MessageLite* /*msg*/) {
0464   (void)arena;
0465   (void)donated;
0466   SetNoArena(value);
0467 }
0468 
0469 inline void InlinedStringField::Set(const char* str, ::google::protobuf::Arena* arena,
0470                                     bool donated, uint32_t* donating_states,
0471                                     uint32_t mask, MessageLite* msg) {
0472   Set(absl::string_view(str), arena, donated, donating_states, mask, msg);
0473 }
0474 
0475 inline void InlinedStringField::Set(const char* str, size_t size,
0476                                     ::google::protobuf::Arena* arena, bool donated,
0477                                     uint32_t* donating_states, uint32_t mask,
0478                                     MessageLite* msg) {
0479   Set(absl::string_view{str, size}, arena, donated, donating_states, mask, msg);
0480 }
0481 
0482 inline void InlinedStringField::SetBytes(absl::string_view value, Arena* arena,
0483                                          bool donated,
0484                                          uint32_t* donating_states,
0485                                          uint32_t mask, MessageLite* msg) {
0486   Set(value, arena, donated, donating_states, mask, msg);
0487 }
0488 
0489 inline void InlinedStringField::SetBytes(std::string&& value, Arena* arena,
0490                                          bool donated,
0491                                          uint32_t* donating_states,
0492                                          uint32_t mask, MessageLite* msg) {
0493   Set(std::move(value), arena, donated, donating_states, mask, msg);
0494 }
0495 
0496 inline void InlinedStringField::SetBytes(const char* str,
0497                                          ::google::protobuf::Arena* arena, bool donated,
0498                                          uint32_t* donating_states,
0499                                          uint32_t mask, MessageLite* msg) {
0500   Set(str, arena, donated, donating_states, mask, msg);
0501 }
0502 
0503 inline void InlinedStringField::SetBytes(const void* p, size_t size,
0504                                          ::google::protobuf::Arena* arena, bool donated,
0505                                          uint32_t* donating_states,
0506                                          uint32_t mask, MessageLite* msg) {
0507   Set(static_cast<const char*>(p), size, arena, donated, donating_states, mask,
0508       msg);
0509 }
0510 
0511 template <typename RefWrappedType>
0512 inline void InlinedStringField::Set(
0513     std::reference_wrapper<RefWrappedType> const_string_ref,
0514     ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
0515     uint32_t mask, MessageLite* msg) {
0516   Set(const_string_ref.get(), arena, donated, donating_states, mask, msg);
0517 }
0518 
0519 template <typename RefWrappedType>
0520 inline void InlinedStringField::SetBytes(
0521     std::reference_wrapper<RefWrappedType> const_string_ref,
0522     ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
0523     uint32_t mask, MessageLite* msg) {
0524   Set(const_string_ref.get(), arena, donated, donating_states, mask, msg);
0525 }
0526 
0527 inline std::string* InlinedStringField::UnsafeMutablePointer() {
0528   return get_mutable();
0529 }
0530 
0531 inline std::string* InlinedStringField::Mutable(std::nullptr_t) {
0532   return get_mutable();
0533 }
0534 
0535 inline std::string* InlinedStringField::MutableNoCopy(std::nullptr_t) {
0536   return get_mutable();
0537 }
0538 
0539 }  // namespace internal
0540 }  // namespace protobuf
0541 }  // namespace google
0542 
0543 #include "google/protobuf/port_undef.inc"
0544 
0545 #endif  // GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__