|
|
|
@ -420,6 +420,7 @@ Cord& Cord::operator=(absl::string_view src) { |
|
|
|
|
// we keep it here to make diffs easier.
|
|
|
|
|
void Cord::InlineRep::AppendArray(absl::string_view src, |
|
|
|
|
MethodIdentifier method) { |
|
|
|
|
MaybeRemoveEmptyCrcNode(); |
|
|
|
|
if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
|
|
|
|
|
|
|
|
|
|
size_t appended = 0; |
|
|
|
@ -479,6 +480,10 @@ inline CordRep* Cord::TakeRep() && { |
|
|
|
|
template <typename C> |
|
|
|
|
inline void Cord::AppendImpl(C&& src) { |
|
|
|
|
auto constexpr method = CordzUpdateTracker::kAppendCord; |
|
|
|
|
|
|
|
|
|
contents_.MaybeRemoveEmptyCrcNode(); |
|
|
|
|
if (src.empty()) return; |
|
|
|
|
|
|
|
|
|
if (empty()) { |
|
|
|
|
// Since destination is empty, we can avoid allocating a node,
|
|
|
|
|
if (src.contents_.is_tree()) { |
|
|
|
@ -591,6 +596,9 @@ void Cord::Append(T&& src) { |
|
|
|
|
template void Cord::Append(std::string&& src); |
|
|
|
|
|
|
|
|
|
void Cord::Prepend(const Cord& src) { |
|
|
|
|
contents_.MaybeRemoveEmptyCrcNode(); |
|
|
|
|
if (src.empty()) return; |
|
|
|
|
|
|
|
|
|
CordRep* src_tree = src.contents_.tree(); |
|
|
|
|
if (src_tree != nullptr) { |
|
|
|
|
CordRep::Ref(src_tree); |
|
|
|
@ -605,7 +613,9 @@ void Cord::Prepend(const Cord& src) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Cord::PrependArray(absl::string_view src, MethodIdentifier method) { |
|
|
|
|
contents_.MaybeRemoveEmptyCrcNode(); |
|
|
|
|
if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
|
|
|
|
|
|
|
|
|
|
if (!contents_.is_tree()) { |
|
|
|
|
size_t cur_size = contents_.inline_size(); |
|
|
|
|
if (cur_size + src.size() <= InlineRep::kMaxInline) { |
|
|
|
@ -665,6 +675,7 @@ void Cord::RemovePrefix(size_t n) { |
|
|
|
|
ABSL_INTERNAL_CHECK(n <= size(), |
|
|
|
|
absl::StrCat("Requested prefix size ", n, |
|
|
|
|
" exceeds Cord's size ", size())); |
|
|
|
|
contents_.MaybeRemoveEmptyCrcNode(); |
|
|
|
|
CordRep* tree = contents_.tree(); |
|
|
|
|
if (tree == nullptr) { |
|
|
|
|
contents_.remove_prefix(n); |
|
|
|
@ -695,6 +706,7 @@ void Cord::RemoveSuffix(size_t n) { |
|
|
|
|
ABSL_INTERNAL_CHECK(n <= size(), |
|
|
|
|
absl::StrCat("Requested suffix size ", n, |
|
|
|
|
" exceeds Cord's size ", size())); |
|
|
|
|
contents_.MaybeRemoveEmptyCrcNode(); |
|
|
|
|
CordRep* tree = contents_.tree(); |
|
|
|
|
if (tree == nullptr) { |
|
|
|
|
contents_.reduce_size(n); |
|
|
|
@ -844,9 +856,10 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const { |
|
|
|
|
|
|
|
|
|
void Cord::SetExpectedChecksum(uint32_t crc) { |
|
|
|
|
auto constexpr method = CordzUpdateTracker::kSetExpectedChecksum; |
|
|
|
|
if (empty()) return; |
|
|
|
|
|
|
|
|
|
if (!contents_.is_tree()) { |
|
|
|
|
if (empty()) { |
|
|
|
|
CordRep* rep = CordRepCrc::New(nullptr, crc); |
|
|
|
|
contents_.EmplaceTree(rep, method); |
|
|
|
|
} else if (!contents_.is_tree()) { |
|
|
|
|
CordRep* rep = contents_.MakeFlatWithExtraCapacity(0); |
|
|
|
|
rep = CordRepCrc::New(rep, crc); |
|
|
|
|
contents_.EmplaceTree(rep, method); |
|
|
|
@ -929,6 +942,7 @@ inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline absl::string_view Cord::GetFirstChunk(const Cord& c) { |
|
|
|
|
if (c.empty()) return {}; |
|
|
|
|
return c.contents_.FindFlatStartPiece(); |
|
|
|
|
} |
|
|
|
|
inline absl::string_view Cord::GetFirstChunk(absl::string_view sv) { |
|
|
|
@ -1166,6 +1180,10 @@ absl::string_view Cord::FlattenSlowPath() { |
|
|
|
|
|
|
|
|
|
/* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) { |
|
|
|
|
assert(rep != nullptr); |
|
|
|
|
if (rep->length == 0) { |
|
|
|
|
*fragment = absl::string_view(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
rep = cord_internal::SkipCrcNode(rep); |
|
|
|
|
if (rep->IsFlat()) { |
|
|
|
|
*fragment = absl::string_view(rep->flat()->Data(), rep->length); |
|
|
|
@ -1197,6 +1215,7 @@ absl::string_view Cord::FlattenSlowPath() { |
|
|
|
|
absl::cord_internal::CordRep* rep, |
|
|
|
|
absl::FunctionRef<void(absl::string_view)> callback) { |
|
|
|
|
assert(rep != nullptr); |
|
|
|
|
if (rep->length == 0) return; |
|
|
|
|
rep = cord_internal::SkipCrcNode(rep); |
|
|
|
|
|
|
|
|
|
if (rep->IsBtree()) { |
|
|
|
@ -1230,7 +1249,11 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, |
|
|
|
|
if (include_data) *os << static_cast<void*>(rep); |
|
|
|
|
*os << "]"; |
|
|
|
|
*os << " " << std::setw(indent) << ""; |
|
|
|
|
if (rep->IsCrc()) { |
|
|
|
|
bool leaf = false; |
|
|
|
|
if (rep == nullptr) { |
|
|
|
|
*os << "NULL\n"; |
|
|
|
|
leaf = true; |
|
|
|
|
} else if (rep->IsCrc()) { |
|
|
|
|
*os << "CRC crc=" << rep->crc()->crc << "\n"; |
|
|
|
|
indent += kIndentStep; |
|
|
|
|
rep = rep->crc()->child; |
|
|
|
@ -1239,6 +1262,7 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, |
|
|
|
|
indent += kIndentStep; |
|
|
|
|
rep = rep->substring()->child; |
|
|
|
|
} else { // Leaf or ring
|
|
|
|
|
leaf = true; |
|
|
|
|
if (rep->IsExternal()) { |
|
|
|
|
*os << "EXTERNAL ["; |
|
|
|
|
if (include_data) |
|
|
|
@ -1252,6 +1276,8 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, |
|
|
|
|
} else { |
|
|
|
|
CordRepBtree::Dump(rep, /*label=*/ "", include_data, *os); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (leaf) { |
|
|
|
|
if (stack.empty()) break; |
|
|
|
|
rep = stack.back(); |
|
|
|
|
stack.pop_back(); |
|
|
|
@ -1297,11 +1323,14 @@ static bool VerifyNode(CordRep* root, CordRep* start_node, |
|
|
|
|
node->substring()->child->length, |
|
|
|
|
ReportError(root, node)); |
|
|
|
|
} else if (node->IsCrc()) { |
|
|
|
|
ABSL_INTERNAL_CHECK(node->crc()->child != nullptr, |
|
|
|
|
ReportError(root, node)); |
|
|
|
|
ABSL_INTERNAL_CHECK(node->crc()->length == node->crc()->child->length, |
|
|
|
|
ReportError(root, node)); |
|
|
|
|
worklist.push_back(node->crc()->child); |
|
|
|
|
ABSL_INTERNAL_CHECK( |
|
|
|
|
node->crc()->child != nullptr || node->crc()->length == 0, |
|
|
|
|
ReportError(root, node)); |
|
|
|
|
if (node->crc()->child != nullptr) { |
|
|
|
|
ABSL_INTERNAL_CHECK(node->crc()->length == node->crc()->child->length, |
|
|
|
|
ReportError(root, node)); |
|
|
|
|
worklist.push_back(node->crc()->child); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} while (!worklist.empty()); |
|
|
|
|
return true; |
|
|
|
|