summaryrefslogtreecommitdiff
path: root/absl/strings/cord.cc
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2022-03-01 13:02:10 -0800
committerGravatar dinord <dino.radakovich@gmail.com>2022-03-02 16:54:53 -0500
commit1dd160f9f091ac30fc83326306b96827ca32c3cd (patch)
treecbfb302a3f5d30d370057f720bb06879593e0f31 /absl/strings/cord.cc
parent5e4ea1ce097f3571e7d87af33b6b30d11b3a211e (diff)
Export of internal Abseil changes
-- f0b7d230a90c82c6fee7adcb46a213d2582b6a7b by Martijn Vels <mvels@google.com>: Optimize substring logic now that CONCAT is removed This CL adds a static Substring() method to CordRepSubstring, and implements substring logic in cord.cc in terms of the new function. This cleans up various helper functions and logic remaining from previous complex CONCAT logic that is no longer needed. PiperOrigin-RevId: 431756805 Change-Id: I39c875b5af119916780e68598c7fc619fb2e8476 -- fa7d1bedf0e1244303844869a332c2a5dbd9ac0f by Derek Mauro <dmauro@google.com>: Allow macro expansion within ABSL_FLAG and ABSL_DECLARE_FLAG args PiperOrigin-RevId: 431721184 Change-Id: I6e19713fb541205d796f940998db5ee25178d55e -- 1b328badd92304ed1c634f23e1c191be57b7bb15 by Laramie Leavitt <lar@google.com>: Add #include for std:: types PiperOrigin-RevId: 431546757 Change-Id: I75efbcd3c77e6f53e4db66494101d30d670d988e -- e25323b299d4d3840218702860f537cdd2a3926f by Thomas Köppe <tkoeppe@google.com>: Add hashing support for pointers to member. Also add tests for function pointers to the existing "pointer" test. PiperOrigin-RevId: 431067588 Change-Id: I3686010635d9fee34c47a418b72402e10737cdbc -- ab27b012a61cf10109fd51932b3b0b05ee78f32f by Laramie Leavitt <lar@google.com>: Avoid use of std::pow in ChiSquare test. PiperOrigin-RevId: 431015830 Change-Id: Idd767ff2f51009ee171de48757207b38330ffea3 -- 28c359135d89061177958580fe4a7493802499cb by Laramie Leavitt <lar@google.com>: Add #include <type_traits> for std::false_type PiperOrigin-RevId: 431005757 Change-Id: I85a6a918778601e19512aaea744424cf39018521 -- a920730f23669479d92e3a696d65d0bc3a5b1de1 by Laramie Leavitt <lar@google.com>: #include <utility> for std::declval PiperOrigin-RevId: 431004934 Change-Id: I295237b2d44e9a15e4083698ea121b68ce0a1bb7 GitOrigin-RevId: f0b7d230a90c82c6fee7adcb46a213d2582b6a7b
Diffstat (limited to 'absl/strings/cord.cc')
-rw-r--r--absl/strings/cord.cc156
1 files changed, 20 insertions, 136 deletions
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index b65dc58b..c6ec1ecf 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -87,30 +87,6 @@ static inline CordRep* VerifyTree(CordRep* node) {
return node;
}
-// Create a concatenation of the specified nodes.
-// Does not change the refcounts of "left" and "right".
-// The returned node has a refcount of 1.
-static CordRep* RawConcat(CordRep* left, CordRep* right) {
- // Avoid making degenerate concat nodes (one child is empty)
- if (left == nullptr) return right;
- if (right == nullptr) return left;
- if (left->length == 0) {
- CordRep::Unref(left);
- return right;
- }
- if (right->length == 0) {
- CordRep::Unref(right);
- return left;
- }
- ABSL_INTERNAL_LOG(FATAL, "CordRepConcat is no longer supported");
- return nullptr;
-}
-
-static CordRep* Concat(CordRep* left, CordRep* right) {
- CordRep* rep = RawConcat(left, right);
- return VerifyTree(rep);
-}
-
static CordRepFlat* CreateFlat(const char* data, size_t length,
size_t alloc_hint) {
CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);
@@ -608,68 +584,6 @@ inline void Cord::Prepend(T&& src) {
template void Cord::Prepend(std::string&& src);
-static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
- if (n >= node->length) return nullptr;
- if (n == 0) return CordRep::Ref(node);
- absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack;
-
- assert(!node->IsCrc());
- assert(n <= node->length);
-
- if (n == 0) {
- CordRep::Ref(node);
- } else {
- size_t start = n;
- size_t len = node->length - n;
- if (node->IsSubstring()) {
- // Consider in-place update of node, similar to in RemoveSuffixFrom().
- start += node->substring()->start;
- node = node->substring()->child;
- }
- node = CordRepSubstring::Create(CordRep::Ref(node), start, len);
- }
- while (!rhs_stack.empty()) {
- node = Concat(node, CordRep::Ref(rhs_stack.back()));
- rhs_stack.pop_back();
- }
- return node;
-}
-
-// RemoveSuffixFrom() is very similar to RemovePrefixFrom(), with the
-// exception that removing a suffix has an optimization where a node may be
-// edited in place iff that node and all its ancestors have a refcount of 1.
-static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
- if (n >= node->length) return nullptr;
- if (n == 0) return CordRep::Ref(node);
- absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack;
- bool inplace_ok = node->refcount.IsOne();
- assert(!node->IsCrc());
-
- assert(n <= node->length);
-
- if (n == 0) {
- CordRep::Ref(node);
- } else if (inplace_ok && !node->IsExternal()) {
- // Consider making a new buffer if the current node capacity is much
- // larger than the new length.
- CordRep::Ref(node);
- node->length -= n;
- } else {
- size_t start = 0;
- size_t len = node->length - n;
- if (node->IsSubstring()) {
- start = node->substring()->start;
- node = node->substring()->child;
- }
- node = CordRepSubstring::Create(CordRep::Ref(node), start, len);
- }
- while (!lhs_stack.empty()) {
- node = Concat(CordRep::Ref(lhs_stack.back()), node);
- lhs_stack.pop_back();
- }
- return node;
-}
-
void Cord::RemovePrefix(size_t n) {
ABSL_INTERNAL_CHECK(n <= size(),
absl::StrCat("Requested prefix size ", n,
@@ -681,14 +595,20 @@ void Cord::RemovePrefix(size_t n) {
auto constexpr method = CordzUpdateTracker::kRemovePrefix;
CordzUpdateScope scope(contents_.cordz_info(), method);
tree = cord_internal::RemoveCrcNode(tree);
- if (tree->IsBtree()) {
+ if (n >= tree->length) {
+ CordRep::Unref(tree);
+ tree = nullptr;
+ } else if (tree->IsBtree()) {
CordRep* old = tree;
tree = tree->btree()->SubTree(n, tree->length - n);
CordRep::Unref(old);
+ } else if (tree->IsSubstring() && tree->refcount.IsOne()) {
+ tree->substring()->start += n;
+ tree->length -= n;
} else {
- CordRep* newrep = RemovePrefixFrom(tree, n);
+ CordRep* rep = CordRepSubstring::Substring(tree, n, tree->length - n);
CordRep::Unref(tree);
- tree = VerifyTree(newrep);
+ tree = rep;
}
contents_.SetTreeOrEmpty(tree, scope);
}
@@ -705,59 +625,23 @@ void Cord::RemoveSuffix(size_t n) {
auto constexpr method = CordzUpdateTracker::kRemoveSuffix;
CordzUpdateScope scope(contents_.cordz_info(), method);
tree = cord_internal::RemoveCrcNode(tree);
- if (tree->IsBtree()) {
+ if (n >= tree->length) {
+ CordRep::Unref(tree);
+ tree = nullptr;
+ } else if (tree->IsBtree()) {
tree = CordRepBtree::RemoveSuffix(tree->btree(), n);
+ } else if (!tree->IsExternal() && tree->refcount.IsOne()) {
+ assert(tree->IsFlat() || tree->IsSubstring());
+ tree->length -= n;
} else {
- CordRep* newrep = RemoveSuffixFrom(tree, n);
+ CordRep* rep = CordRepSubstring::Substring(tree, 0, tree->length - n);
CordRep::Unref(tree);
- tree = VerifyTree(newrep);
+ tree = rep;
}
contents_.SetTreeOrEmpty(tree, scope);
}
}
-// Work item for NewSubRange().
-struct SubRange {
- SubRange(CordRep* a_node, size_t a_pos, size_t a_n)
- : node(a_node), pos(a_pos), n(a_n) {}
- CordRep* node; // nullptr means concat last 2 results.
- size_t pos;
- size_t n;
-};
-
-static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) {
- absl::InlinedVector<CordRep*, kInlinedVectorSize> results;
- absl::InlinedVector<SubRange, kInlinedVectorSize> todo;
- assert(!node->IsCrc());
- todo.push_back(SubRange(node, pos, n));
- do {
- const SubRange& sr = todo.back();
- node = sr.node;
- pos = sr.pos;
- n = sr.n;
- todo.pop_back();
-
- if (node == nullptr) {
- assert(results.size() >= 2);
- CordRep* right = results.back();
- results.pop_back();
- CordRep* left = results.back();
- results.pop_back();
- results.push_back(Concat(left, right));
- } else if (pos == 0 && n == node->length) {
- results.push_back(CordRep::Ref(node));
- } else {
- if (node->IsSubstring()) {
- pos += node->substring()->start;
- node = node->substring()->child;
- }
- results.push_back(CordRepSubstring::Create(CordRep::Ref(node), pos, n));
- }
- } while (!todo.empty());
- assert(results.size() == 1);
- return results[0];
-}
-
Cord Cord::Subcord(size_t pos, size_t new_size) const {
Cord sub_cord;
size_t length = size();
@@ -791,7 +675,7 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
if (tree->IsBtree()) {
tree = tree->btree()->SubTree(pos, new_size);
} else {
- tree = NewSubRange(tree, pos, new_size);
+ tree = CordRepSubstring::Substring(tree, pos, new_size);
}
sub_cord.contents_.EmplaceTree(tree, contents_.data_,
CordzUpdateTracker::kSubCord);
@@ -1140,7 +1024,7 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
: payload->flat()->Data();
const size_t offset = current_chunk_.data() - data;
- auto* tree = CordRepSubstring::Create(CordRep::Ref(payload), offset, n);
+ auto* tree = CordRepSubstring::Substring(payload, offset, n);
subcord.contents_.EmplaceTree(VerifyTree(tree), method);
bytes_remaining_ -= n;
current_chunk_.remove_prefix(n);