mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Add absl::CopyCordToSpan()
PiperOrigin-RevId: 912247630 Change-Id: Ie5d2837c9b878e6094dce4d2ec7e60441a7c6bb7
This commit is contained in:
committed by
Copybara-Service
parent
d0d4c59910
commit
638e17aedd
@@ -1014,6 +1014,7 @@ cc_test(
|
||||
"//absl/log:check",
|
||||
"//absl/random",
|
||||
"//absl/types:compare",
|
||||
"//absl/types:span",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
|
||||
@@ -1086,6 +1086,24 @@ void Cord::CopyToArraySlowPath(char* absl_nonnull dst) const {
|
||||
}
|
||||
}
|
||||
|
||||
size_t CopyCordToSpan(const Cord& src, absl::Span<char> dst) {
|
||||
if (src.size() <= dst.size()) {
|
||||
src.CopyToArrayImpl(dst.data());
|
||||
return src.size();
|
||||
}
|
||||
|
||||
const size_t result = dst.size();
|
||||
for (absl::string_view chunk : src.Chunks()) {
|
||||
size_t n = std::min(chunk.size(), dst.size());
|
||||
if (n == 0) {
|
||||
break;
|
||||
}
|
||||
memcpy(dst.data(), chunk.data(), n);
|
||||
dst.remove_prefix(n);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
|
||||
// Failure of this assertion indicates an attempt to iterate past `end()`.
|
||||
absl::base_internal::HardeningAssertGE(bytes_remaining_, n);
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/compare.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "absl/types/span.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
@@ -107,6 +108,7 @@ template <typename Releaser>
|
||||
Cord MakeCordFromExternal(absl::string_view, Releaser&&);
|
||||
void CopyCordToString(const Cord& src, std::string* absl_nonnull dst);
|
||||
void AppendCordToString(const Cord& src, std::string* absl_nonnull dst);
|
||||
[[nodiscard]] size_t CopyCordToSpan(const Cord& src, absl::Span<char> dst);
|
||||
|
||||
// Cord memory accounting modes
|
||||
enum class CordMemoryAccounting {
|
||||
@@ -434,6 +436,12 @@ class Cord {
|
||||
friend void AppendCordToString(const Cord& src,
|
||||
std::string* absl_nonnull dst);
|
||||
|
||||
// CopyCordToSpan()
|
||||
//
|
||||
// Copies up to `dest.size()` bytes starting from the beginning of `src` to
|
||||
// `dst`. Returns the number of bytes copied.
|
||||
friend size_t CopyCordToSpan(const Cord& src, absl::Span<char> dst);
|
||||
|
||||
class CharIterator;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/compare.h"
|
||||
#include "absl/types/span.h"
|
||||
|
||||
// convenience local constants
|
||||
static constexpr auto FLAT = absl::cord_internal::FLAT;
|
||||
@@ -735,6 +736,53 @@ TEST_P(CordTest, AppendToString) {
|
||||
"appending ", "to ", "a ", "string."})));
|
||||
}
|
||||
|
||||
static void VerifyCopyToSpan(const absl::Cord& cord) {
|
||||
// Test with span exactly the same size as the cord.
|
||||
{
|
||||
std::string dst(cord.size(), '\0');
|
||||
size_t copied = absl::CopyCordToSpan(cord, absl::MakeSpan(dst));
|
||||
EXPECT_EQ(copied, cord.size());
|
||||
EXPECT_EQ(dst, cord);
|
||||
}
|
||||
|
||||
// Test with span larger than the cord.
|
||||
{
|
||||
std::string dst(cord.size() + 10, 'x');
|
||||
size_t copied = absl::CopyCordToSpan(cord, absl::MakeSpan(dst));
|
||||
EXPECT_EQ(copied, cord.size());
|
||||
EXPECT_EQ(absl::string_view(dst).substr(0, copied), cord);
|
||||
if (cord.size() < dst.size()) {
|
||||
absl::string_view tail = absl::string_view(dst).substr(copied);
|
||||
EXPECT_EQ(tail, std::string(tail.size(), 'x'));
|
||||
}
|
||||
}
|
||||
|
||||
// Test with span smaller than the cord.
|
||||
{
|
||||
size_t target_size = cord.size() / 2;
|
||||
std::string dst(target_size, '\0');
|
||||
size_t copied = absl::CopyCordToSpan(cord, absl::MakeSpan(dst));
|
||||
EXPECT_EQ(copied, target_size);
|
||||
EXPECT_EQ(dst, std::string(cord).substr(0, target_size));
|
||||
}
|
||||
|
||||
// Test with empty span.
|
||||
{
|
||||
char c = 'x';
|
||||
size_t copied = absl::CopyCordToSpan(cord, absl::MakeSpan(&c, 0));
|
||||
EXPECT_EQ(copied, 0);
|
||||
EXPECT_EQ(c, 'x');
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(CordTest, CopyToSpan) {
|
||||
VerifyCopyToSpan(absl::Cord()); // Empty cords cannot be hardened.
|
||||
VerifyCopyToSpan(MaybeHardened(absl::Cord("small cord")));
|
||||
VerifyCopyToSpan(MaybeHardened(
|
||||
absl::MakeFragmentedCord({"fragmented ", "cord ", "to ", "test ",
|
||||
"copying ", "to ", "a ", "span."})));
|
||||
}
|
||||
|
||||
TEST_P(CordTest, AppendEmptyBuffer) {
|
||||
absl::Cord cord;
|
||||
cord.Append(absl::CordBuffer());
|
||||
|
||||
Reference in New Issue
Block a user