about summary refs log tree commit diff
path: root/third_party/abseil_cpp/absl/strings/cord.cc
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2020-11-21T13·43+0100
committerVincent Ambo <mail@tazj.in>2020-11-21T14·48+0100
commit082c006c04343a78d87b6c6ab3608c25d6213c3f (patch)
tree16e6f04f8d1d1d2d67e8e917d5e7bb48c1b60375 /third_party/abseil_cpp/absl/strings/cord.cc
parentcc27324d0226953943f408ce3c69ad7d648e005e (diff)
merge(3p/absl): subtree merge of Abseil up to e19260f r/1889
... notably, this includes Abseil's own StatusOr type, which
conflicted with our implementation (that was taken from TensorFlow).

Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
Diffstat (limited to 'third_party/abseil_cpp/absl/strings/cord.cc')
-rw-r--r--third_party/abseil_cpp/absl/strings/cord.cc168
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 68f5398791..9efd135750 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();