diff options
author | Benjamin Barenblat <bbaren@google.com> | 2024-09-03 11:49:29 -0400 |
---|---|---|
committer | Benjamin Barenblat <bbaren@google.com> | 2024-09-03 11:49:29 -0400 |
commit | c1afa8b8238c25591ca80d068477aa7d4ce05fc8 (patch) | |
tree | 284a9f8b319de5783ff83ad004a9e390cb60fd0d /absl/strings/cord.h | |
parent | 23778b53f420f54eebc195dd8430e79bda165e5b (diff) | |
parent | 4447c7562e3bc702ade25105912dce503f0c4010 (diff) |
Merge new upstream LTS 20240722.0
Diffstat (limited to 'absl/strings/cord.h')
-rw-r--r-- | absl/strings/cord.h | 75 |
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); |