merge(3p/abseil_cpp): Merge upstream at 'ccdbb5941'

Change-Id: I6e85fc7b5f76bba1f1eef15e600a8acb64e97ef5
This commit is contained in:
Vincent Ambo 2020-06-17 14:53:11 +01:00
commit 543379ce45
97 changed files with 3546 additions and 2316 deletions

View file

@ -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);

View file

@ -147,11 +147,8 @@ class Cord {
// Creates a Cord from a `std::string&&` rvalue. These constructors are
// templated to avoid ambiguities for types that are convertible to both
// `absl::string_view` and `std::string`, such as `const char*`.
//
// Note that these functions reserve the right to use the `string&&`'s
// memory and that they will do so in the future.
template <typename T, EnableIfString<T> = 0>
explicit Cord(T&& src) : Cord(absl::string_view(src)) {}
explicit Cord(T&& src);
template <typename T, EnableIfString<T> = 0>
Cord& operator=(T&& src);
@ -1048,11 +1045,8 @@ inline Cord& Cord::operator=(Cord&& x) noexcept {
return *this;
}
template <typename T, Cord::EnableIfString<T>>
inline Cord& Cord::operator=(T&& src) {
*this = absl::string_view(src);
return *this;
}
extern template Cord::Cord(std::string&& src);
extern template Cord& Cord::operator=(std::string&& src);
inline size_t Cord::size() const {
// Length is 1st field in str.rep_
@ -1098,19 +1092,8 @@ inline void Cord::Append(absl::string_view src) {
contents_.AppendArray(src.data(), src.size());
}
template <typename T, Cord::EnableIfString<T>>
inline void Cord::Append(T&& src) {
// Note that this function reserves the right to reuse the `string&&`'s
// memory and that it will do so in the future.
Append(absl::string_view(src));
}
template <typename T, Cord::EnableIfString<T>>
inline void Cord::Prepend(T&& src) {
// Note that this function reserves the right to reuse the `string&&`'s
// memory and that it will do so in the future.
Prepend(absl::string_view(src));
}
extern template void Cord::Append(std::string&& src);
extern template void Cord::Prepend(std::string&& src);
inline int Cord::Compare(const Cord& rhs) const {
if (!contents_.is_tree() && !rhs.contents_.is_tree()) {

View file

@ -764,6 +764,12 @@ TEST_F(FormatConvertTest, LongDouble) {
}
}
// Regression tests
//
// Using a string literal because not all platforms support hex literals or it
// might be out of range.
doubles.push_back(std::strtold("-0xf.ffffffb5feafffbp-16324L", nullptr));
for (const char *fmt : kFormats) {
for (char f : {'f', 'F', //
'g', 'G', //

View file

@ -224,13 +224,13 @@ class FractionalDigitGenerator {
// This function will allocate enough stack space to perform the conversion.
static void RunConversion(
uint128 v, int exp, absl::FunctionRef<void(FractionalDigitGenerator)> f) {
using Limits = std::numeric_limits<long double>;
assert(-exp < 0);
assert(-exp >= std::numeric_limits<long double>::min_exponent - 128);
static_assert(
StackArray::kMaxCapacity >=
(128 - std::numeric_limits<long double>::min_exponent + 31) / 32,
"");
StackArray::RunWithCapacity((exp + 31) / 32,
assert(-exp >= Limits::min_exponent - 128);
static_assert(StackArray::kMaxCapacity >=
(Limits::digits + 128 - Limits::min_exponent + 31) / 32,
"");
StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32,
[=](absl::Span<uint32_t> input) {
f(FractionalDigitGenerator(input, v, exp));
});

View file

@ -19,7 +19,7 @@
//
// The `str_format` library is a typesafe replacement for the family of
// `printf()` string formatting routines within the `<cstdio>` standard library
// header. Like the `printf` family, the `str_format` uses a "format string" to
// header. Like the `printf` family, `str_format` uses a "format string" to
// perform argument substitutions based on types. See the `FormatSpec` section
// below for format string documentation.
//

View file

@ -8,6 +8,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/strings/cord.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
@ -353,6 +354,7 @@ TEST(StrFormat, BehavesAsDocumented) {
EXPECT_EQ(StrFormat("%s", "C"), "C");
EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
EXPECT_EQ(StrFormat("%s", absl::Cord("cord")), "cord");
// Integral Conversion
// These format integral types: char, int, long, uint64_t, etc.
EXPECT_EQ(StrFormat("%d", char{10}), "10");

View file

@ -44,6 +44,7 @@
#include <vector>
#include "absl/base/internal/raw_logging.h"
#include "absl/base/macros.h"
#include "absl/strings/internal/str_split_internal.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"