File indexing completed on 2025-01-31 10:12:06
0001
0002
0003
0004
0005
0006
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
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
0039 PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString
0040 fixed_address_empty_string;
0041
0042
0043
0044 class PROTOBUF_EXPORT LazyString {
0045 public:
0046
0047
0048
0049
0050 struct InitValue {
0051 const char* ptr;
0052 size_t size;
0053 };
0054
0055
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
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
0071
0072 const std::string& Init() const;
0073 };
0074
0075 class PROTOBUF_EXPORT TaggedStringPtr {
0076 public:
0077
0078
0079 enum Flags {
0080 kArenaBit = 0x1,
0081 kMutableBit = 0x2,
0082 kMask = 0x3
0083 };
0084
0085
0086 enum Type {
0087
0088 kDefault = 0,
0089
0090
0091
0092 kAllocated = kMutableBit,
0093
0094
0095
0096
0097
0098 kMutableArena = kArenaBit | kMutableBit,
0099
0100
0101
0102
0103
0104
0105
0106 kFixedSizeArena = kArenaBit,
0107 };
0108
0109 TaggedStringPtr() = default;
0110 explicit constexpr TaggedStringPtr(ExplicitlyConstructedArenaString* ptr)
0111 : ptr_(ptr) {}
0112
0113
0114
0115 inline const std::string* SetDefault(const std::string* p) {
0116 return TagAs(kDefault, const_cast<std::string*>(p));
0117 }
0118
0119
0120
0121
0122 inline std::string* SetAllocated(std::string* p) {
0123 return TagAs(kAllocated, p);
0124 }
0125
0126
0127
0128
0129 inline std::string* SetFixedSizeArena(std::string* p) {
0130 return TagAs(kFixedSizeArena, p);
0131 }
0132
0133
0134
0135
0136 inline std::string* SetMutableArena(std::string* p) {
0137 return TagAs(kMutableArena, p);
0138 }
0139
0140
0141 inline bool IsMutable() const { return as_int() & kMutableBit; }
0142
0143
0144 inline bool IsDefault() const { return (as_int() & kMask) == kDefault; }
0145
0146
0147
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
0158
0159 inline bool IsArena() const { return as_int() & kArenaBit; }
0160
0161
0162 inline bool IsFixedSizeArena() const {
0163 return (as_int() & kMask) == kFixedSizeArena;
0164 }
0165
0166
0167 inline std::string* Get() const {
0168 return reinterpret_cast<std::string*>(as_int() & ~kMask);
0169 }
0170
0171
0172
0173
0174 inline bool IsNull() const { return ptr_ == nullptr; }
0175
0176
0177
0178 TaggedStringPtr Copy(Arena* arena) const;
0179
0180
0181
0182
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
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
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 struct PROTOBUF_EXPORT ArenaStringPtr {
0230
0231 ArenaStringPtr() = default;
0232
0233
0234 constexpr ArenaStringPtr(ExplicitlyConstructedArenaString* default_value,
0235 ConstantInitialized)
0236 : tagged_ptr_(default_value) {}
0237
0238
0239
0240
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
0249
0250
0251
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
0260
0261
0262
0263
0264
0265 ArenaStringPtr(Arena* arena, const ArenaStringPtr& rhs)
0266 : tagged_ptr_(rhs.tagged_ptr_.Copy(arena)) {}
0267
0268
0269
0270
0271
0272
0273
0274 ArenaStringPtr(Arena* arena, const ArenaStringPtr& rhs,
0275 const LazyString& default_value)
0276 : tagged_ptr_(rhs.tagged_ptr_.Copy(arena, default_value)) {}
0277
0278
0279
0280
0281
0282
0283 inline void InitDefault();
0284
0285
0286
0287
0288 inline void InitExternal(const std::string* str);
0289
0290
0291
0292
0293
0294
0295
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
0319
0320
0321
0322 std::string* Mutable(Arena* arena);
0323 std::string* Mutable(const LazyString& default_value, Arena* arena);
0324
0325
0326
0327
0328
0329
0330
0331
0332 std::string* MutableNoCopy(Arena* arena);
0333
0334
0335 PROTOBUF_NDEBUG_INLINE const std::string& Get() const {
0336
0337 return *tagged_ptr_.Get();
0338 }
0339
0340
0341
0342 PROTOBUF_NDEBUG_INLINE const std::string* UnsafeGetPointer() const
0343 ABSL_ATTRIBUTE_RETURNS_NONNULL {
0344 return tagged_ptr_.Get();
0345 }
0346
0347
0348
0349
0350
0351 PROTOBUF_NODISCARD std::string* Release();
0352
0353
0354
0355
0356 void SetAllocated(std::string* value, Arena* arena);
0357
0358
0359 void Destroy();
0360
0361
0362
0363
0364
0365 void ClearToEmpty();
0366
0367
0368
0369 void ClearNonDefaultToEmpty();
0370
0371
0372
0373
0374 void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena);
0375
0376
0377
0378
0379 inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(ArenaStringPtr* rhs,
0380 ArenaStringPtr* lhs,
0381 Arena* arena);
0382
0383
0384
0385 void UnsafeSetTaggedPointer(TaggedStringPtr value) { tagged_ptr_ = value; }
0386
0387
0388
0389 std::string* UnsafeMutablePointer() ABSL_ATTRIBUTE_RETURNS_NONNULL;
0390
0391
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
0411
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
0421
0422
0423
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
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
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
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
0522 }
0523
0524 inline void ArenaStringPtr::ClearNonDefaultToEmpty() {
0525
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 }
0537 }
0538 }
0539
0540 #include "google/protobuf/port_undef.inc"
0541
0542 #endif