diff options
Diffstat (limited to 'third_party/abseil_cpp/absl/strings/cord.cc')
-rw-r--r-- | third_party/abseil_cpp/absl/strings/cord.cc | 168 |
1 files changed, 55 insertions, 113 deletions
diff --git a/third_party/abseil_cpp/absl/strings/cord.cc b/third_party/abseil_cpp/absl/strings/cord.cc index 68f5398791db..9efd13575039 100644 --- a/third_party/abseil_cpp/absl/strings/cord.cc +++ b/third_party/abseil_cpp/absl/strings/cord.cc @@ -50,58 +50,10 @@ using ::absl::cord_internal::CordRepConcat; using ::absl::cord_internal::CordRepExternal; using ::absl::cord_internal::CordRepSubstring; -// Various representations that we allow -enum CordRepKind { - CONCAT = 0, - EXTERNAL = 1, - SUBSTRING = 2, - - // We have different tags for different sized flat arrays, - // starting with FLAT - FLAT = 3, -}; - -namespace { - -// Type used with std::allocator for allocating and deallocating -// `CordRepExternal`. std::allocator is used because it opaquely handles the -// different new / delete overloads available on a given platform. -struct alignas(absl::cord_internal::ExternalRepAlignment()) ExternalAllocType { - unsigned char value[absl::cord_internal::ExternalRepAlignment()]; -}; - -// Returns the number of objects to pass in to std::allocator<ExternalAllocType> -// allocate() and deallocate() to create enough room for `CordRepExternal` with -// `releaser_size` bytes on the end. -constexpr size_t GetExternalAllocNumObjects(size_t releaser_size) { - // Be sure to round up since `releaser_size` could be smaller than - // `sizeof(ExternalAllocType)`. - return (sizeof(CordRepExternal) + releaser_size + sizeof(ExternalAllocType) - - 1) / - sizeof(ExternalAllocType); -} - -// Allocates enough memory for `CordRepExternal` and a releaser with size -// `releaser_size` bytes. -void* AllocateExternal(size_t releaser_size) { - return std::allocator<ExternalAllocType>().allocate( - GetExternalAllocNumObjects(releaser_size)); -} - -// Deallocates the memory for a `CordRepExternal` assuming it was allocated with -// a releaser of given size and alignment. -void DeallocateExternal(CordRepExternal* p, size_t releaser_size) { - std::allocator<ExternalAllocType>().deallocate( - reinterpret_cast<ExternalAllocType*>(p), - GetExternalAllocNumObjects(releaser_size)); -} - -// Returns a pointer to the type erased releaser for the given CordRepExternal. -void* GetExternalReleaser(CordRepExternal* rep) { - return rep + 1; -} - -} // namespace +using ::absl::cord_internal::CONCAT; +using ::absl::cord_internal::EXTERNAL; +using ::absl::cord_internal::FLAT; +using ::absl::cord_internal::SUBSTRING; namespace cord_internal { @@ -289,6 +241,7 @@ static void UnrefInternal(CordRep* rep) { absl::InlinedVector<CordRep*, kInlinedVectorSize> pending; while (true) { + assert(!rep->refcount.IsImmortal()); if (rep->tag == CONCAT) { CordRepConcat* rep_concat = rep->concat(); CordRep* right = rep_concat->right; @@ -304,11 +257,8 @@ static void UnrefInternal(CordRep* rep) { } } else if (rep->tag == EXTERNAL) { CordRepExternal* rep_external = rep->external(); - absl::string_view data(rep_external->base, rep->length); - void* releaser = GetExternalReleaser(rep_external); - size_t releaser_size = rep_external->releaser_invoker(releaser, data); - rep_external->~CordRepExternal(); - DeallocateExternal(rep_external, releaser_size); + assert(rep_external->releaser_invoker != nullptr); + rep_external->releaser_invoker(rep_external); rep = nullptr; } else if (rep->tag == SUBSTRING) { CordRepSubstring* rep_substring = rep->substring(); @@ -458,18 +408,12 @@ static CordRep* NewTree(const char* data, namespace cord_internal { -ExternalRepReleaserPair NewExternalWithUninitializedReleaser( - absl::string_view data, ExternalReleaserInvoker invoker, - size_t releaser_size) { +void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) { assert(!data.empty()); - - void* raw_rep = AllocateExternal(releaser_size); - auto* rep = new (raw_rep) CordRepExternal(); rep->length = data.size(); rep->tag = EXTERNAL; rep->base = data.data(); - rep->releaser_invoker = invoker; - return {VerifyTree(rep), GetExternalReleaser(rep)}; + VerifyTree(rep); } } // namespace cord_internal @@ -493,57 +437,55 @@ static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) { // -------------------------------------------------------------------- // Cord::InlineRep functions -// This will trigger LNK2005 in MSVC. -#ifndef COMPILER_MSVC -const unsigned char Cord::InlineRep::kMaxInline; -#endif // COMPILER_MSVC +constexpr unsigned char Cord::InlineRep::kMaxInline; inline void Cord::InlineRep::set_data(const char* data, size_t n, bool nullify_tail) { static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15"); - cord_internal::SmallMemmove(data_, data, n, nullify_tail); - data_[kMaxInline] = static_cast<char>(n); + cord_internal::SmallMemmove(data_.as_chars, data, n, nullify_tail); + set_tagged_size(static_cast<char>(n)); } inline char* Cord::InlineRep::set_data(size_t n) { assert(n <= kMaxInline); - memset(data_, 0, sizeof(data_)); - data_[kMaxInline] = static_cast<char>(n); - return data_; + ResetToEmpty(); + set_tagged_size(static_cast<char>(n)); + return data_.as_chars; } inline CordRep* Cord::InlineRep::force_tree(size_t extra_hint) { - size_t len = data_[kMaxInline]; - CordRep* result; + size_t len = tagged_size(); if (len > kMaxInline) { - memcpy(&result, data_, sizeof(result)); - } else { - result = NewFlat(len + extra_hint); - result->length = len; - memcpy(result->data, data_, len); - set_tree(result); + return data_.as_tree.rep; } + + CordRep* result = NewFlat(len + extra_hint); + result->length = len; + static_assert(kMinFlatLength >= sizeof(data_.as_chars), ""); + memcpy(result->data, data_.as_chars, sizeof(data_.as_chars)); + set_tree(result); return result; } inline void Cord::InlineRep::reduce_size(size_t n) { - size_t tag = data_[kMaxInline]; + size_t tag = tagged_size(); assert(tag <= kMaxInline); assert(tag >= n); tag -= n; - memset(data_ + tag, 0, n); - data_[kMaxInline] = static_cast<char>(tag); + memset(data_.as_chars + tag, 0, n); + set_tagged_size(static_cast<char>(tag)); } inline void Cord::InlineRep::remove_prefix(size_t n) { - cord_internal::SmallMemmove(data_, data_ + n, data_[kMaxInline] - n); + cord_internal::SmallMemmove(data_.as_chars, data_.as_chars + n, + tagged_size() - n); reduce_size(n); } void Cord::InlineRep::AppendTree(CordRep* tree) { if (tree == nullptr) return; - size_t len = data_[kMaxInline]; + size_t len = tagged_size(); if (len == 0) { set_tree(tree); } else { @@ -552,8 +494,8 @@ void Cord::InlineRep::AppendTree(CordRep* tree) { } void Cord::InlineRep::PrependTree(CordRep* tree) { - if (tree == nullptr) return; - size_t len = data_[kMaxInline]; + assert(tree != nullptr); + size_t len = tagged_size(); if (len == 0) { set_tree(tree); } else { @@ -609,11 +551,11 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size, } // Try to fit in the inline buffer if possible. - size_t inline_length = data_[kMaxInline]; + size_t inline_length = tagged_size(); if (inline_length < kMaxInline && max_length <= kMaxInline - inline_length) { - *region = data_ + inline_length; + *region = data_.as_chars + inline_length; *size = max_length; - data_[kMaxInline] = static_cast<char>(inline_length + max_length); + set_tagged_size(static_cast<char>(inline_length + max_length)); return; } @@ -637,11 +579,11 @@ void Cord::InlineRep::GetAppendRegion(char** region, size_t* size) { const size_t max_length = std::numeric_limits<size_t>::max(); // Try to fit in the inline buffer if possible. - size_t inline_length = data_[kMaxInline]; + size_t inline_length = tagged_size(); if (inline_length < kMaxInline) { - *region = data_ + inline_length; + *region = data_.as_chars + inline_length; *size = kMaxInline - inline_length; - data_[kMaxInline] = kMaxInline; + set_tagged_size(kMaxInline); return; } @@ -676,7 +618,7 @@ static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) { void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) { ClearSlow(); - memcpy(data_, src.data_, sizeof(data_)); + data_ = src.data_; if (is_tree()) { Ref(tree()); } @@ -686,7 +628,7 @@ void Cord::InlineRep::ClearSlow() { if (is_tree()) { Unref(tree()); } - memset(data_, 0, sizeof(data_)); + ResetToEmpty(); } // -------------------------------------------------------------------- @@ -724,12 +666,12 @@ Cord::Cord(T&& src) { std::string data; }; const absl::string_view original_data = src; - CordRepExternal* rep = - static_cast<CordRepExternal*>(absl::cord_internal::NewExternalRep( - original_data, StringReleaser{std::move(src)})); + auto* rep = static_cast< + ::absl::cord_internal::CordRepExternalImpl<StringReleaser>*>( + absl::cord_internal::NewExternalRep( + original_data, StringReleaser{std::forward<T>(src)})); // Moving src may have invalidated its data pointer, so adjust it. - rep->base = - static_cast<StringReleaser*>(GetExternalReleaser(rep))->data.data(); + rep->base = rep->template get<0>().data.data(); contents_.set_tree(rep); } } @@ -778,7 +720,7 @@ Cord& Cord::operator=(T&& src) { if (src.size() <= kMaxBytesToCopy) { *this = absl::string_view(src); } else { - *this = Cord(std::move(src)); + *this = Cord(std::forward<T>(src)); } return *this; } @@ -790,11 +732,11 @@ template Cord& Cord::operator=(std::string&& src); void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) { if (src_size == 0) return; // memcpy(_, nullptr, 0) is undefined. // Try to fit in the inline buffer if possible. - size_t inline_length = data_[kMaxInline]; + size_t inline_length = tagged_size(); if (inline_length < kMaxInline && src_size <= kMaxInline - inline_length) { // Append new data to embedded array - data_[kMaxInline] = static_cast<char>(inline_length + src_size); - memcpy(data_ + inline_length, src_data, src_size); + set_tagged_size(static_cast<char>(inline_length + src_size)); + memcpy(data_.as_chars + inline_length, src_data, src_size); return; } @@ -817,7 +759,7 @@ void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) { const size_t size2 = inline_length + src_size / 10; root = NewFlat(std::max<size_t>(size1, size2)); appended = std::min(src_size, TagToLength(root->tag) - inline_length); - memcpy(root->data, data_, inline_length); + memcpy(root->data, data_.as_chars, inline_length); memcpy(root->data + inline_length, src_data, appended); root->length = inline_length + appended; set_tree(root); @@ -901,7 +843,7 @@ void Cord::Append(T&& src) { if (src.size() <= kMaxBytesToCopy) { Append(absl::string_view(src)); } else { - Append(Cord(std::move(src))); + Append(Cord(std::forward<T>(src))); } } @@ -941,7 +883,7 @@ inline void Cord::Prepend(T&& src) { if (src.size() <= kMaxBytesToCopy) { Prepend(absl::string_view(src)); } else { - Prepend(Cord(std::move(src))); + Prepend(Cord(std::forward<T>(src))); } } @@ -1126,7 +1068,7 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const { } else if (new_size <= InlineRep::kMaxInline) { Cord::ChunkIterator it = chunk_begin(); it.AdvanceBytes(pos); - char* dest = sub_cord.contents_.data_; + char* dest = sub_cord.contents_.data_.as_chars; size_t remaining_size = new_size; while (remaining_size > it->size()) { cord_internal::SmallMemmove(dest, it->data(), it->size()); @@ -1135,7 +1077,7 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const { ++it; } cord_internal::SmallMemmove(dest, it->data(), remaining_size); - sub_cord.contents_.data_[InlineRep::kMaxInline] = new_size; + sub_cord.contents_.set_tagged_size(new_size); } else { sub_cord.contents_.set_tree(NewSubRange(tree, pos, new_size)); } @@ -1324,9 +1266,9 @@ bool ComputeCompareResult<bool>(int memcmp_res) { // Helper routine. Locates the first flat chunk of the Cord without // initializing the iterator. inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const { - size_t n = data_[kMaxInline]; + size_t n = tagged_size(); if (n <= kMaxInline) { - return absl::string_view(data_, n); + return absl::string_view(data_.as_chars, n); } CordRep* node = tree(); |