summaryrefslogtreecommitdiff
path: root/absl/strings/cord.h
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbaren@google.com>2024-09-03 11:49:29 -0400
committerGravatar Benjamin Barenblat <bbaren@google.com>2024-09-03 11:49:29 -0400
commitc1afa8b8238c25591ca80d068477aa7d4ce05fc8 (patch)
tree284a9f8b319de5783ff83ad004a9e390cb60fd0d /absl/strings/cord.h
parent23778b53f420f54eebc195dd8430e79bda165e5b (diff)
parent4447c7562e3bc702ade25105912dce503f0c4010 (diff)
Merge new upstream LTS 20240722.0
Diffstat (limited to 'absl/strings/cord.h')
-rw-r--r--absl/strings/cord.h75
1 files changed, 68 insertions, 7 deletions
diff --git a/absl/strings/cord.h b/absl/strings/cord.h
index b3e556b6..69aa8ef4 100644
--- a/absl/strings/cord.h
+++ b/absl/strings/cord.h
@@ -75,6 +75,7 @@
#include "absl/base/internal/per_thread_tls.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
+#include "absl/base/optimization.h"
#include "absl/base/port.h"
#include "absl/container/inlined_vector.h"
#include "absl/crc/internal/crc_cord_state.h"
@@ -95,6 +96,7 @@
#include "absl/strings/internal/resize_uninitialized.h"
#include "absl/strings/internal/string_constant.h"
#include "absl/strings/string_view.h"
+#include "absl/types/compare.h"
#include "absl/types/optional.h"
namespace absl {
@@ -104,6 +106,7 @@ class CordTestPeer;
template <typename Releaser>
Cord MakeCordFromExternal(absl::string_view, Releaser&&);
void CopyCordToString(const Cord& src, absl::Nonnull<std::string*> dst);
+void AppendCordToString(const Cord& src, absl::Nonnull<std::string*> dst);
// Cord memory accounting modes
enum class CordMemoryAccounting {
@@ -420,6 +423,18 @@ class Cord {
friend void CopyCordToString(const Cord& src,
absl::Nonnull<std::string*> dst);
+ // AppendCordToString()
+ //
+ // Appends the contents of a `src` Cord to a `*dst` string.
+ //
+ // This function optimizes the case of appending to a non-empty destination
+ // string. If `*dst` already has capacity to store the contents of the cord,
+ // this function does not invalidate pointers previously returned by
+ // `dst->data()`. If `*dst` is a new object, prefer to simply use the
+ // conversion operator to `std::string`.
+ friend void AppendCordToString(const Cord& src,
+ absl::Nonnull<std::string*> dst);
+
class CharIterator;
//----------------------------------------------------------------------------
@@ -757,7 +772,7 @@ class Cord {
// Cord::Find()
//
- // Returns an iterator to the first occurrance of the substring `needle`.
+ // Returns an iterator to the first occurrence of the substring `needle`.
//
// If the substring `needle` does not occur, `Cord::char_end()` is returned.
CharIterator Find(absl::string_view needle) const;
@@ -835,6 +850,38 @@ class Cord {
friend bool operator==(const Cord& lhs, const Cord& rhs);
friend bool operator==(const Cord& lhs, absl::string_view rhs);
+#ifdef __cpp_impl_three_way_comparison
+
+ // Cords support comparison with other Cords and string_views via operator<
+ // and others; here we provide a wrapper for the C++20 three-way comparison
+ // <=> operator.
+
+ static inline std::strong_ordering ConvertCompareResultToStrongOrdering(
+ int c) {
+ if (c == 0) {
+ return std::strong_ordering::equal;
+ } else if (c < 0) {
+ return std::strong_ordering::less;
+ } else {
+ return std::strong_ordering::greater;
+ }
+ }
+
+ friend inline std::strong_ordering operator<=>(const Cord& x, const Cord& y) {
+ return ConvertCompareResultToStrongOrdering(x.Compare(y));
+ }
+
+ friend inline std::strong_ordering operator<=>(const Cord& lhs,
+ absl::string_view rhs) {
+ return ConvertCompareResultToStrongOrdering(lhs.Compare(rhs));
+ }
+
+ friend inline std::strong_ordering operator<=>(absl::string_view lhs,
+ const Cord& rhs) {
+ return ConvertCompareResultToStrongOrdering(-rhs.Compare(lhs));
+ }
+#endif
+
friend absl::Nullable<const CordzInfo*> GetCordzInfoForTesting(
const Cord& cord);
@@ -1065,6 +1112,8 @@ class Cord {
const;
CharIterator FindImpl(CharIterator it, absl::string_view needle) const;
+
+ void CopyToArrayImpl(absl::Nonnull<char*> dst) const;
};
ABSL_NAMESPACE_END
@@ -1103,8 +1152,8 @@ absl::Nonnull<CordRep*> NewExternalRep(absl::string_view data,
// Overload for function reference types that dispatches using a function
// pointer because there are no `alignof()` or `sizeof()` a function reference.
// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
-inline absl::Nonnull<CordRep*> NewExternalRep(absl::string_view data,
- void (&releaser)(absl::string_view)) {
+inline absl::Nonnull<CordRep*> NewExternalRep(
+ absl::string_view data, void (&releaser)(absl::string_view)) {
return NewExternalRep(data, &releaser);
}
@@ -1120,7 +1169,7 @@ Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
} else {
using ReleaserType = absl::decay_t<Releaser>;
cord_internal::InvokeReleaser(
- cord_internal::Rank0{}, ReleaserType(std::forward<Releaser>(releaser)),
+ cord_internal::Rank1{}, ReleaserType(std::forward<Releaser>(releaser)),
data);
}
return cord;
@@ -1170,7 +1219,8 @@ inline void Cord::InlineRep::Swap(absl::Nonnull<Cord::InlineRep*> rhs) {
if (rhs == this) {
return;
}
- std::swap(data_, rhs->data_);
+ using std::swap;
+ swap(data_, rhs->data_);
}
inline absl::Nullable<const char*> Cord::InlineRep::data() const {
@@ -1352,7 +1402,8 @@ inline size_t Cord::EstimatedMemoryUsage(
return result;
}
-inline absl::optional<absl::string_view> Cord::TryFlat() const {
+inline absl::optional<absl::string_view> Cord::TryFlat() const
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
absl::cord_internal::CordRep* rep = contents_.tree();
if (rep == nullptr) {
return absl::string_view(contents_.data(), contents_.size());
@@ -1364,7 +1415,7 @@ inline absl::optional<absl::string_view> Cord::TryFlat() const {
return absl::nullopt;
}
-inline absl::string_view Cord::Flatten() {
+inline absl::string_view Cord::Flatten() ABSL_ATTRIBUTE_LIFETIME_BOUND {
absl::cord_internal::CordRep* rep = contents_.tree();
if (rep == nullptr) {
return absl::string_view(contents_.data(), contents_.size());
@@ -1387,6 +1438,7 @@ inline void Cord::Prepend(absl::string_view src) {
inline void Cord::Append(CordBuffer buffer) {
if (ABSL_PREDICT_FALSE(buffer.length() == 0)) return;
+ contents_.MaybeRemoveEmptyCrcNode();
absl::string_view short_value;
if (CordRep* rep = buffer.ConsumeValue(short_value)) {
contents_.AppendTree(rep, CordzUpdateTracker::kAppendCordBuffer);
@@ -1397,6 +1449,7 @@ inline void Cord::Append(CordBuffer buffer) {
inline void Cord::Prepend(CordBuffer buffer) {
if (ABSL_PREDICT_FALSE(buffer.length() == 0)) return;
+ contents_.MaybeRemoveEmptyCrcNode();
absl::string_view short_value;
if (CordRep* rep = buffer.ConsumeValue(short_value)) {
contents_.PrependTree(rep, CordzUpdateTracker::kPrependCordBuffer);
@@ -1445,6 +1498,14 @@ inline bool Cord::StartsWith(absl::string_view rhs) const {
return EqualsImpl(rhs, rhs_size);
}
+inline void Cord::CopyToArrayImpl(absl::Nonnull<char*> dst) const {
+ if (!contents_.is_tree()) {
+ if (!empty()) contents_.CopyToArray(dst);
+ } else {
+ CopyToArraySlowPath(dst);
+ }
+}
+
inline void Cord::ChunkIterator::InitTree(
absl::Nonnull<cord_internal::CordRep*> tree) {
tree = cord_internal::SkipCrcNode(tree);