Export of internal Abseil changes
-- 44ccc0320ffaa2106ba3c6393b5a40c3b4f7b901 by Abseil Team <absl-team@google.com>: Clarify span iterator documentation. PiperOrigin-RevId: 299110584 -- 80d016d8026b8d6904aa0ff2d5e1c3ae27f129bb by Greg Falcon <gfalcon@google.com>: Add Cord::TryFlat(). PiperOrigin-RevId: 298889772 -- da6900203f1e4131d5693cbca157b6dba099bbed by Greg Falcon <gfalcon@google.com>: clang-format cord_test.cc. PiperOrigin-RevId: 298851425 GitOrigin-RevId: 44ccc0320ffaa2106ba3c6393b5a40c3b4f7b901 Change-Id: Ia5394f6fbb473d206726fdd48a00eb07a6acad6a
This commit is contained in:
parent
b19ba96766
commit
cf3a1998e9
5 changed files with 101 additions and 25 deletions
|
@ -285,6 +285,7 @@ cc_library(
|
|||
"//absl/container:inlined_vector",
|
||||
"//absl/functional:function_ref",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/types:optional",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -546,6 +546,7 @@ absl_cc_library(
|
|||
absl::fixed_array
|
||||
absl::function_ref
|
||||
absl::inlined_vector
|
||||
absl::optional
|
||||
absl::raw_logging_internal
|
||||
absl::type_traits
|
||||
PUBLIC
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "absl/strings/internal/cord_internal.h"
|
||||
#include "absl/strings/internal/resize_uninitialized.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
@ -512,6 +513,10 @@ class Cord {
|
|||
// REQUIRES: 0 <= i < size()
|
||||
char operator[](size_t i) const;
|
||||
|
||||
// If this cord's representation is a single flat array, return a
|
||||
// string_view referencing that array. Otherwise return nullopt.
|
||||
absl::optional<absl::string_view> TryFlat() const;
|
||||
|
||||
// Flattens the cord into a single array and returns a view of the data.
|
||||
//
|
||||
// If the cord was already flat, the contents are not modified.
|
||||
|
@ -630,7 +635,7 @@ class Cord {
|
|||
// Helper for MemoryUsage()
|
||||
static size_t MemoryUsageAux(const absl::cord_internal::CordRep* rep);
|
||||
|
||||
// Helper for GetFlat()
|
||||
// Helper for GetFlat() and TryFlat()
|
||||
static bool GetFlatAux(absl::cord_internal::CordRep* rep,
|
||||
absl::string_view* fragment);
|
||||
|
||||
|
@ -942,6 +947,18 @@ inline size_t Cord::EstimatedMemoryUsage() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
inline absl::optional<absl::string_view> Cord::TryFlat() const {
|
||||
absl::cord_internal::CordRep* rep = contents_.tree();
|
||||
if (rep == nullptr) {
|
||||
return absl::string_view(contents_.data(), contents_.size());
|
||||
}
|
||||
absl::string_view fragment;
|
||||
if (GetFlatAux(rep, &fragment)) {
|
||||
return fragment;
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
inline absl::string_view Cord::Flatten() {
|
||||
absl::cord_internal::CordRep* rep = contents_.tree();
|
||||
if (rep == nullptr) {
|
||||
|
|
|
@ -70,9 +70,8 @@ static std::string RandomLowercaseString(RandomEngine* rng) {
|
|||
static std::string RandomLowercaseString(RandomEngine* rng, size_t length) {
|
||||
std::string result(length, '\0');
|
||||
std::uniform_int_distribution<int> chars('a', 'z');
|
||||
std::generate(result.begin(), result.end(), [&]() {
|
||||
return static_cast<char>(chars(*rng));
|
||||
});
|
||||
std::generate(result.begin(), result.end(),
|
||||
[&]() { return static_cast<char>(chars(*rng)); });
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -424,6 +423,50 @@ TEST(Cord, CopyToString) {
|
|||
"copying ", "to ", "a ", "string."}));
|
||||
}
|
||||
|
||||
TEST(TryFlat, Empty) {
|
||||
absl::Cord c;
|
||||
EXPECT_EQ(c.TryFlat(), "");
|
||||
}
|
||||
|
||||
TEST(TryFlat, Flat) {
|
||||
absl::Cord c("hello");
|
||||
EXPECT_EQ(c.TryFlat(), "hello");
|
||||
}
|
||||
|
||||
TEST(TryFlat, SubstrInlined) {
|
||||
absl::Cord c("hello");
|
||||
c.RemovePrefix(1);
|
||||
EXPECT_EQ(c.TryFlat(), "ello");
|
||||
}
|
||||
|
||||
TEST(TryFlat, SubstrFlat) {
|
||||
absl::Cord c("longer than 15 bytes");
|
||||
c.RemovePrefix(1);
|
||||
EXPECT_EQ(c.TryFlat(), "onger than 15 bytes");
|
||||
}
|
||||
|
||||
TEST(TryFlat, Concat) {
|
||||
absl::Cord c = absl::MakeFragmentedCord({"hel", "lo"});
|
||||
EXPECT_EQ(c.TryFlat(), absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(TryFlat, External) {
|
||||
absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
|
||||
EXPECT_EQ(c.TryFlat(), "hell");
|
||||
}
|
||||
|
||||
TEST(TryFlat, SubstrExternal) {
|
||||
absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
|
||||
c.RemovePrefix(1);
|
||||
EXPECT_EQ(c.TryFlat(), "ell");
|
||||
}
|
||||
|
||||
TEST(TryFlat, SubstrConcat) {
|
||||
absl::Cord c = absl::MakeFragmentedCord({"hello", " world"});
|
||||
c.RemovePrefix(1);
|
||||
EXPECT_EQ(c.TryFlat(), absl::nullopt);
|
||||
}
|
||||
|
||||
static bool IsFlat(const absl::Cord& c) {
|
||||
return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end();
|
||||
}
|
||||
|
@ -511,24 +554,24 @@ TEST(Cord, MultipleLengths) {
|
|||
for (size_t i = 0; i < d.size(); i++) {
|
||||
std::string a = d.data(i);
|
||||
|
||||
{ // Construct from Cord
|
||||
{ // Construct from Cord
|
||||
absl::Cord tmp(a);
|
||||
absl::Cord x(tmp);
|
||||
EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
|
||||
}
|
||||
|
||||
{ // Construct from absl::string_view
|
||||
{ // Construct from absl::string_view
|
||||
absl::Cord x(a);
|
||||
EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
|
||||
}
|
||||
|
||||
{ // Append cord to self
|
||||
{ // Append cord to self
|
||||
absl::Cord self(a);
|
||||
self.Append(self);
|
||||
EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
|
||||
}
|
||||
|
||||
{ // Prepend cord to self
|
||||
{ // Prepend cord to self
|
||||
absl::Cord self(a);
|
||||
self.Prepend(self);
|
||||
EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
|
||||
|
@ -538,40 +581,40 @@ TEST(Cord, MultipleLengths) {
|
|||
for (size_t j = 0; j < d.size(); j++) {
|
||||
std::string b = d.data(j);
|
||||
|
||||
{ // CopyFrom Cord
|
||||
{ // CopyFrom Cord
|
||||
absl::Cord x(a);
|
||||
absl::Cord y(b);
|
||||
x = y;
|
||||
EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
|
||||
}
|
||||
|
||||
{ // CopyFrom absl::string_view
|
||||
{ // CopyFrom absl::string_view
|
||||
absl::Cord x(a);
|
||||
x = b;
|
||||
EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
|
||||
}
|
||||
|
||||
{ // Cord::Append(Cord)
|
||||
{ // Cord::Append(Cord)
|
||||
absl::Cord x(a);
|
||||
absl::Cord y(b);
|
||||
x.Append(y);
|
||||
EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
|
||||
}
|
||||
|
||||
{ // Cord::Append(absl::string_view)
|
||||
{ // Cord::Append(absl::string_view)
|
||||
absl::Cord x(a);
|
||||
x.Append(b);
|
||||
EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
|
||||
}
|
||||
|
||||
{ // Cord::Prepend(Cord)
|
||||
{ // Cord::Prepend(Cord)
|
||||
absl::Cord x(a);
|
||||
absl::Cord y(b);
|
||||
x.Prepend(y);
|
||||
EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
|
||||
}
|
||||
|
||||
{ // Cord::Prepend(absl::string_view)
|
||||
{ // Cord::Prepend(absl::string_view)
|
||||
absl::Cord x(a);
|
||||
x.Prepend(b);
|
||||
EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
|
||||
|
@ -1089,7 +1132,7 @@ TEST(ConstructFromExternal, ReferenceQualifierOverloads) {
|
|||
}
|
||||
|
||||
TEST(ExternalMemory, BasicUsage) {
|
||||
static const char* strings[] = { "", "hello", "there" };
|
||||
static const char* strings[] = {"", "hello", "there"};
|
||||
for (const char* str : strings) {
|
||||
absl::Cord dst("(prefix)");
|
||||
AddExternalMemory(str, &dst);
|
||||
|
|
|
@ -292,60 +292,74 @@ class Span {
|
|||
|
||||
// Span::front()
|
||||
//
|
||||
// Returns a reference to the first element of this span.
|
||||
// Returns a reference to the first element of this span. The span must not
|
||||
// be empty.
|
||||
constexpr reference front() const noexcept {
|
||||
return ABSL_ASSERT(size() > 0), *data();
|
||||
}
|
||||
|
||||
// Span::back()
|
||||
//
|
||||
// Returns a reference to the last element of this span.
|
||||
// Returns a reference to the last element of this span. The span must not
|
||||
// be empty.
|
||||
constexpr reference back() const noexcept {
|
||||
return ABSL_ASSERT(size() > 0), *(data() + size() - 1);
|
||||
}
|
||||
|
||||
// Span::begin()
|
||||
//
|
||||
// Returns an iterator to the first element of this span.
|
||||
// Returns an iterator pointing to the first element of this span, or `end()`
|
||||
// if the span is empty.
|
||||
constexpr iterator begin() const noexcept { return data(); }
|
||||
|
||||
// Span::cbegin()
|
||||
//
|
||||
// Returns a const iterator to the first element of this span.
|
||||
// Returns a const iterator pointing to the first element of this span, or
|
||||
// `end()` if the span is empty.
|
||||
constexpr const_iterator cbegin() const noexcept { return begin(); }
|
||||
|
||||
// Span::end()
|
||||
//
|
||||
// Returns an iterator to the last element of this span.
|
||||
// Returns an iterator pointing just beyond the last element at the
|
||||
// end of this span. This iterator acts as a placeholder; attempting to
|
||||
// access it results in undefined behavior.
|
||||
constexpr iterator end() const noexcept { return data() + size(); }
|
||||
|
||||
// Span::cend()
|
||||
//
|
||||
// Returns a const iterator to the last element of this span.
|
||||
// Returns a const iterator pointing just beyond the last element at the
|
||||
// end of this span. This iterator acts as a placeholder; attempting to
|
||||
// access it results in undefined behavior.
|
||||
constexpr const_iterator cend() const noexcept { return end(); }
|
||||
|
||||
// Span::rbegin()
|
||||
//
|
||||
// Returns a reverse iterator starting at the last element of this span.
|
||||
// Returns a reverse iterator pointing to the last element at the end of this
|
||||
// span, or `rend()` if the span is empty.
|
||||
constexpr reverse_iterator rbegin() const noexcept {
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
// Span::crbegin()
|
||||
//
|
||||
// Returns a reverse const iterator starting at the last element of this span.
|
||||
// Returns a const reverse iterator pointing to the last element at the end of
|
||||
// this span, or `crend()` if the span is empty.
|
||||
constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
|
||||
|
||||
// Span::rend()
|
||||
//
|
||||
// Returns a reverse iterator starting at the first element of this span.
|
||||
// Returns a reverse iterator pointing just before the first element
|
||||
// at the beginning of this span. This pointer acts as a placeholder;
|
||||
// attempting to access its element results in undefined behavior.
|
||||
constexpr reverse_iterator rend() const noexcept {
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
// Span::crend()
|
||||
//
|
||||
// Returns a reverse iterator starting at the first element of this span.
|
||||
// Returns a reverse const iterator pointing just before the first element
|
||||
// at the beginning of this span. This pointer acts as a placeholder;
|
||||
// attempting to access its element results in undefined behavior.
|
||||
constexpr const_reverse_iterator crend() const noexcept { return rend(); }
|
||||
|
||||
// Span mutations
|
||||
|
|
Loading…
Reference in a new issue