summaryrefslogtreecommitdiff
path: root/absl/strings/cord.cc
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-05-26 10:57:33 -0700
committerGravatar Derek Mauro <dmauro@google.com>2020-05-26 14:45:38 -0400
commit33caf1097ecce4fe892567462fa8821d477854b4 (patch)
tree27eecef4f8c5638857b134ea117c3bd20a980b96 /absl/strings/cord.cc
parentcf1a02e2dc5a1bc9d095f4c996306de448ca200f (diff)
Export of internal Abseil changes
-- 7d0468a6610ed85586d5c87fd65de8dac5118923 by Derek Mauro <dmauro@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 313226473 -- 1131ef6d116f5ce7d46537a82f300ea06dcaaa53 by Gennadiy Rozental <rogeeff@google.com>: Migrate internal interface to use mutable references. PiperOrigin-RevId: 312931131 -- 96225212a9f5fbd0b38c71fe65539164992c7c3b by Laramie Leavitt <lar@google.com>: Remove random/internal/distributions.h This file was something of an historical artifact. All of the related code has either been removed or migraged, and so the only remaining type belongs with uniform_helper.h, as it is used to infer the return type of the absl::Uniform method in a few cases. PiperOrigin-RevId: 312878173 -- 6dcbd5be58ad425e08740ff64088373ee7fe4a72 by Mark Barolak <mbar@google.com>: Release the StrFormat test case for Cords to open source. PiperOrigin-RevId: 312707974 -- 34484d18dfb63a0a7ad6e2aaeb570e33592968be by Abseil Team <absl-team@google.com>: Let Cord::Cord(string&&), Cord::operator=(string&&), Cord::Append(string&&), and Cord::Prepend(string&&) steal string data and embed it into the Cord as a single external chunk, instead of copying it into flat chunks (at most 4083-byte each). Stealing string data is faster, but it creates a long chunk, which leads to a higher more memory usage if its subcords are created and outlive the whole Cord. These functions revert to copying the data if any of the following conditions holds: - string size is at most kMaxBytesToCopy (511), to avoid the overhead of an external chunk for short strings; - less than half of string capacity is used, to avoid pinning to much unused memory. PiperOrigin-RevId: 312683785 GitOrigin-RevId: 7d0468a6610ed85586d5c87fd65de8dac5118923 Change-Id: If79b5a1dfe6d53a8ddddbc7da84338f11fc4cfa3
Diffstat (limited to 'absl/strings/cord.cc')
-rw-r--r--absl/strings/cord.cc65
1 files changed, 65 insertions, 0 deletions
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index 1ddd6aec..68f53987 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -705,6 +705,37 @@ Cord::Cord(absl::string_view src) {
}
}
+template <typename T, Cord::EnableIfString<T>>
+Cord::Cord(T&& src) {
+ if (
+ // String is short: copy data to avoid external block overhead.
+ src.size() <= kMaxBytesToCopy ||
+ // String is wasteful: copy data to avoid pinning too much unused memory.
+ src.size() < src.capacity() / 2
+ ) {
+ if (src.size() <= InlineRep::kMaxInline) {
+ contents_.set_data(src.data(), src.size(), false);
+ } else {
+ contents_.set_tree(NewTree(src.data(), src.size(), 0));
+ }
+ } else {
+ struct StringReleaser {
+ void operator()(absl::string_view /* data */) {}
+ 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)}));
+ // Moving src may have invalidated its data pointer, so adjust it.
+ rep->base =
+ static_cast<StringReleaser*>(GetExternalReleaser(rep))->data.data();
+ contents_.set_tree(rep);
+ }
+}
+
+template Cord::Cord(std::string&& src);
+
// The destruction code is separate so that the compiler can determine
// that it does not need to call the destructor on a moved-from Cord.
void Cord::DestroyCordSlow() {
@@ -742,6 +773,18 @@ Cord& Cord::operator=(absl::string_view src) {
return *this;
}
+template <typename T, Cord::EnableIfString<T>>
+Cord& Cord::operator=(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ *this = absl::string_view(src);
+ } else {
+ *this = Cord(std::move(src));
+ }
+ return *this;
+}
+
+template Cord& Cord::operator=(std::string&& src);
+
// TODO(sanjay): Move to Cord::InlineRep section of file. For now,
// we keep it here to make diffs easier.
void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
@@ -853,6 +896,17 @@ void Cord::Append(const Cord& src) { AppendImpl(src); }
void Cord::Append(Cord&& src) { AppendImpl(std::move(src)); }
+template <typename T, Cord::EnableIfString<T>>
+void Cord::Append(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Append(absl::string_view(src));
+ } else {
+ Append(Cord(std::move(src)));
+ }
+}
+
+template void Cord::Append(std::string&& src);
+
void Cord::Prepend(const Cord& src) {
CordRep* src_tree = src.contents_.tree();
if (src_tree != nullptr) {
@@ -882,6 +936,17 @@ void Cord::Prepend(absl::string_view src) {
}
}
+template <typename T, Cord::EnableIfString<T>>
+inline void Cord::Prepend(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Prepend(absl::string_view(src));
+ } else {
+ Prepend(Cord(std::move(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 Ref(node);