Export of internal Abseil changes

--
2aa4544070113a4943f93464df74759f043bab92 by CJ Johnson <johnsoncj@google.com>:

Spelling fix in InlinedVector

PiperOrigin-RevId: 308241764

--
0d8a8ff71023df845c490c73811da598a42f12d9 by Todd Jackson <tjackson@google.com>:

Fix CMake warnings on absl/types/CMakeLists.txt.

PiperOrigin-RevId: 308123331

--
f35fbd79437ba999097b1499770103b7865078e5 by Samuel Benzaquen <sbenza@google.com>:

Speed up the integral printer.

PiperOrigin-RevId: 308081531

--
b1676b869ed0547e1cca23c83bb370f459bdf2cb by Samuel Benzaquen <sbenza@google.com>:

Collapse the template arguments to enums earlier to reduce the number of
instantiations of FormatSpecTemplate.
This doesn't affect opt builds much, but reduces the bloat in non-opt builds.

PiperOrigin-RevId: 308066155

--
edda0c227adad392cfff2af6ed532822c481f013 by Abseil Team <absl-team@google.com>:

Minor documentation fix for `absl::Status` CTOR.

PiperOrigin-RevId: 308037725

--
8326b85569f0fdb15632b0076e38baba4c69794b by Derek Mauro <dmauro@google.com>:

Internal change

PiperOrigin-RevId: 307914168
GitOrigin-RevId: 2aa4544070113a4943f93464df74759f043bab92
Change-Id: I553ce3838c5e35d04954f560dc75ec24033919af
This commit is contained in:
Abseil Team 2020-04-24 06:12:31 -07:00 committed by Derek Mauro
parent 68494aae95
commit cde2e2410e
8 changed files with 189 additions and 165 deletions

View file

@ -5,4 +5,4 @@ find_dependency(Threads)
@PACKAGE_INIT@
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")

View file

@ -535,7 +535,7 @@ class InlinedVector {
//
// Resizes the inlined vector to contain `n` elements.
//
// NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n`
// NOTE: If `n` is smaller than `size()`, extra elements are destroyed. If `n`
// is larger than `size()`, new elements are value-initialized.
void resize(size_type n) {
ABSL_HARDENING_ASSERT(n <= max_size());

View file

@ -78,7 +78,7 @@ class ABSL_MUST_USE_RESULT Status final {
Status();
// Create a status in the canonical error space with the specified code and
// error message. If `code == util::error::OK`, `msg` is ignored and an
// error message. If `code == absl::StatusCode::kOk`, `msg` is ignored and an
// object identical to an OK status is constructed.
//
// `msg` must be in UTF-8. The implementation may complain (e.g.,

View file

@ -12,14 +12,13 @@
#include "absl/base/port.h"
#include "absl/strings/internal/str_format/float_conversion.h"
#include "absl/strings/numbers.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
const char kDigit[2][32] = { "0123456789abcdef", "0123456789ABCDEF" };
// Reduce *capacity by s.size(), clipped to a 0 minimum.
void ReducePadding(string_view s, size_t *capacity) {
*capacity = Excess(s.size(), *capacity);
@ -48,94 +47,144 @@ struct IsSigned<absl::int128> : std::true_type {};
template <>
struct IsSigned<absl::uint128> : std::false_type {};
class ConvertedIntInfo {
// Integral digit printer.
// Call one of the PrintAs* routines after construction once.
// Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results.
class IntDigits {
public:
// Print the unsigned integer as octal.
// Supports unsigned integral types and uint128.
template <typename T>
ConvertedIntInfo(T v, ConversionChar conv) {
using Unsigned = typename MakeUnsigned<T>::type;
auto u = static_cast<Unsigned>(v);
if (IsNeg(v)) {
is_neg_ = true;
u = Unsigned{} - u;
} else {
is_neg_ = false;
}
UnsignedToStringRight(u, conv);
void PrintAsOct(T v) {
static_assert(!IsSigned<T>::value, "");
char *p = storage_ + sizeof(storage_);
do {
*--p = static_cast<char>('0' + (static_cast<size_t>(v) & 7));
v >>= 3;
} while (v);
start_ = p;
size_ = storage_ + sizeof(storage_) - p;
}
string_view digits() const {
return {end() - size_, static_cast<size_t>(size_)};
// Print the signed or unsigned integer as decimal.
// Supports all integral types.
template <typename T>
void PrintAsDec(T v) {
static_assert(std::is_integral<T>::value, "");
start_ = storage_;
size_ = numbers_internal::FastIntToBuffer(v, storage_) - storage_;
}
bool is_neg() const { return is_neg_; }
void PrintAsDec(int128 v) {
auto u = static_cast<uint128>(v);
bool add_neg = false;
if (v < 0) {
add_neg = true;
u = uint128{} - u;
}
PrintAsDec(u, add_neg);
}
void PrintAsDec(uint128 v, bool add_neg = false) {
// This function can be sped up if needed. We can call FastIntToBuffer
// twice, or fix FastIntToBuffer to support uint128.
char *p = storage_ + sizeof(storage_);
do {
p -= 2;
numbers_internal::PutTwoDigits(static_cast<size_t>(v % 100), p);
v /= 100;
} while (v);
if (p[0] == '0') {
// We printed one too many hexits.
++p;
}
if (add_neg) {
*--p = '-';
}
size_ = storage_ + sizeof(storage_) - p;
start_ = p;
}
// Print the unsigned integer as hex using lowercase.
// Supports unsigned integral types and uint128.
template <typename T>
void PrintAsHexLower(T v) {
static_assert(!IsSigned<T>::value, "");
char *p = storage_ + sizeof(storage_);
do {
p -= 2;
constexpr const char* table = numbers_internal::kHexTable;
std::memcpy(p, table + 2 * (static_cast<size_t>(v) & 0xFF), 2);
if (sizeof(T) == 1) break;
v >>= 8;
} while (v);
if (p[0] == '0') {
// We printed one too many digits.
++p;
}
start_ = p;
size_ = storage_ + sizeof(storage_) - p;
}
// Print the unsigned integer as hex using uppercase.
// Supports unsigned integral types and uint128.
template <typename T>
void PrintAsHexUpper(T v) {
static_assert(!IsSigned<T>::value, "");
char *p = storage_ + sizeof(storage_);
// kHexTable is only lowercase, so do it manually for uppercase.
do {
*--p = "0123456789ABCDEF"[static_cast<size_t>(v) & 15];
v >>= 4;
} while (v);
start_ = p;
size_ = storage_ + sizeof(storage_) - p;
}
// The printed value including the '-' sign if available.
// For inputs of value `0`, this will return "0"
string_view with_neg_and_zero() const { return {start_, size_}; }
// The printed value not including the '-' sign.
// For inputs of value `0`, this will return "".
string_view without_neg_or_zero() const {
static_assert('-' < '0', "The check below verifies both.");
size_t advance = start_[0] <= '0' ? 1 : 0;
return {start_ + advance, size_ - advance};
}
bool is_negative() const { return start_[0] == '-'; }
private:
template <typename T, bool IsSigned>
struct IsNegImpl {
static bool Eval(T v) { return v < 0; }
};
template <typename T>
struct IsNegImpl<T, false> {
static bool Eval(T) {
return false;
}
};
template <typename T>
bool IsNeg(T v) {
return IsNegImpl<T, IsSigned<T>::value>::Eval(v);
}
template <typename T>
void UnsignedToStringRight(T u, ConversionChar conv) {
char *p = end();
switch (FormatConversionCharRadix(conv)) {
default:
case 10:
for (; u; u /= 10)
*--p = static_cast<char>('0' + static_cast<size_t>(u % 10));
break;
case 8:
for (; u; u /= 8)
*--p = static_cast<char>('0' + static_cast<size_t>(u % 8));
break;
case 16: {
const char *digits = kDigit[FormatConversionCharIsUpper(conv) ? 1 : 0];
for (; u; u /= 16) *--p = digits[static_cast<size_t>(u % 16)];
break;
}
}
size_ = static_cast<int>(end() - p);
}
const char *end() const { return storage_ + sizeof(storage_); }
char *end() { return storage_ + sizeof(storage_); }
bool is_neg_;
int size_;
// Max size: 128 bit value as octal -> 43 digits
char storage_[128 / 3 + 1];
const char *start_;
size_t size_;
// Max size: 128 bit value as octal -> 43 digits, plus sign char
char storage_[128 / 3 + 1 + 1];
};
// Note: 'o' conversions do not have a base indicator, it's just that
// the '#' flag is specified to modify the precision for 'o' conversions.
string_view BaseIndicator(const ConvertedIntInfo &info,
string_view BaseIndicator(const IntDigits &as_digits,
const ConversionSpec conv) {
bool alt = conv.has_alt_flag();
int radix = FormatConversionCharRadix(conv.conversion_char());
if (conv.conversion_char() == ConversionChar::p)
alt = true; // always show 0x for %p.
// always show 0x for %p.
bool alt = conv.has_alt_flag() || conv.conversion_char() == ConversionChar::p;
bool hex = (conv.conversion_char() == FormatConversionChar::x ||
conv.conversion_char() == FormatConversionChar::X ||
conv.conversion_char() == FormatConversionChar::p);
// From the POSIX description of '#' flag:
// "For x or X conversion specifiers, a non-zero result shall have
// 0x (or 0X) prefixed to it."
if (alt && radix == 16 && !info.digits().empty()) {
if (FormatConversionCharIsUpper(conv.conversion_char())) return "0X";
return "0x";
if (alt && hex && !as_digits.without_neg_or_zero().empty()) {
return conv.conversion_char() == FormatConversionChar::X ? "0X" : "0x";
}
return {};
}
string_view SignColumn(bool neg, const ConversionSpec conv) {
if (FormatConversionCharIsSigned(conv.conversion_char())) {
if (conv.conversion_char() == FormatConversionChar::d ||
conv.conversion_char() == FormatConversionChar::i) {
if (neg) return "-";
if (conv.has_show_pos_flag()) return "+";
if (conv.has_sign_col_flag()) return " ";
@ -154,20 +203,20 @@ bool ConvertCharImpl(unsigned char v, const ConversionSpec conv,
return true;
}
bool ConvertIntImplInner(const ConvertedIntInfo &info,
const ConversionSpec conv, FormatSinkImpl *sink) {
bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
const ConversionSpec conv, FormatSinkImpl *sink) {
// Print as a sequence of Substrings:
// [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
size_t fill = 0;
if (conv.width() >= 0) fill = conv.width();
string_view formatted = info.digits();
string_view formatted = as_digits.without_neg_or_zero();
ReducePadding(formatted, &fill);
string_view sign = SignColumn(info.is_neg(), conv);
string_view sign = SignColumn(as_digits.is_negative(), conv);
ReducePadding(sign, &fill);
string_view base_indicator = BaseIndicator(info, conv);
string_view base_indicator = BaseIndicator(as_digits, conv);
ReducePadding(base_indicator, &fill);
int precision = conv.precision();
@ -209,34 +258,53 @@ bool ConvertIntImplInner(const ConvertedIntInfo &info,
}
template <typename T>
bool ConvertIntImplInner(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
ConvertedIntInfo info(v, conv.conversion_char());
if (conv.is_basic() && (conv.conversion_char() != ConversionChar::p)) {
if (info.is_neg()) sink->Append(1, '-');
if (info.digits().empty()) {
sink->Append(1, '0');
} else {
sink->Append(info.digits());
}
bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
using U = typename MakeUnsigned<T>::type;
IntDigits as_digits;
switch (conv.conversion_char()) {
case FormatConversionChar::c:
return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
case FormatConversionChar::o:
as_digits.PrintAsOct(static_cast<U>(v));
break;
case FormatConversionChar::x:
as_digits.PrintAsHexLower(static_cast<U>(v));
break;
case FormatConversionChar::X:
as_digits.PrintAsHexUpper(static_cast<U>(v));
break;
case FormatConversionChar::u:
as_digits.PrintAsDec(static_cast<U>(v));
break;
case FormatConversionChar::d:
case FormatConversionChar::i:
as_digits.PrintAsDec(v);
break;
case FormatConversionChar::a:
case FormatConversionChar::e:
case FormatConversionChar::f:
case FormatConversionChar::g:
case FormatConversionChar::A:
case FormatConversionChar::E:
case FormatConversionChar::F:
case FormatConversionChar::G:
return ConvertFloatImpl(static_cast<double>(v), conv, sink);
default:
return false;
}
if (conv.is_basic()) {
sink->Append(as_digits.with_neg_and_zero());
return true;
}
return ConvertIntImplInner(info, conv, sink);
}
template <typename T>
bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
if (FormatConversionCharIsFloat(conv.conversion_char())) {
return FormatConvertImpl(static_cast<double>(v), conv, sink).value;
}
if (conv.conversion_char() == ConversionChar::c)
return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
if (!FormatConversionCharIsIntegral(conv.conversion_char())) return false;
if (!FormatConversionCharIsSigned(conv.conversion_char()) &&
IsSigned<T>::value) {
using U = typename MakeUnsigned<T>::type;
return FormatConvertImpl(static_cast<U>(v), conv, sink).value;
}
return ConvertIntImplInner(v, conv, sink);
return ConvertIntImplInnerSlow(as_digits, conv, sink);
}
template <typename T>
@ -296,7 +364,9 @@ ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, const ConversionSpec conv,
sink->Append("(nil)");
return {true};
}
return {ConvertIntImplInner(v.value, conv, sink)};
IntDigits as_digits;
as_digits.PrintAsHexLower(v.value);
return {ConvertIntImplInnerSlow(as_digits, conv, sink)};
}
// ==================== Floats ====================

View file

@ -60,7 +60,7 @@ class UntypedFormatSpecImpl {
size_t size_;
};
template <typename T, typename...>
template <typename T, FormatConversionCharSet...>
struct MakeDependent {
using type = T;
};
@ -68,7 +68,7 @@ struct MakeDependent {
// Implicitly convertible from `const char*`, `string_view`, and the
// `ExtendedParsedFormat` type. This abstraction allows all format functions to
// operate on any without providing too many overloads.
template <typename... Args>
template <FormatConversionCharSet... Args>
class FormatSpecTemplate
: public MakeDependent<UntypedFormatSpec, Args...>::type {
using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
@ -105,13 +105,11 @@ class FormatSpecTemplate
// Good format overload.
FormatSpecTemplate(const char* s) // NOLINT
__attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
"bad format trap")))
__attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
: Base(s) {}
FormatSpecTemplate(string_view s) // NOLINT
__attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
"bad format trap")))
__attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
: Base(s) {}
#else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
@ -121,19 +119,14 @@ class FormatSpecTemplate
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
template <Conv... C, typename = typename std::enable_if<
AllOf(sizeof...(C) == sizeof...(Args),
Contains(ArgumentToConv<Args>(),
C)...)>::type>
template <Conv... C,
typename = typename std::enable_if<
AllOf(sizeof...(C) == sizeof...(Args), Contains(Args,
C)...)>::type>
FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT
: Base(&pc) {}
};
template <typename... Args>
struct FormatSpecDeductionBarrier {
using type = FormatSpecTemplate<Args...>;
};
class Streamable {
public:
Streamable(const UntypedFormatSpecImpl& format,

View file

@ -170,21 +170,6 @@ inline FormatConversionChar FormatConversionCharFromChar(char c) {
return FormatConversionChar::kNone;
}
inline int FormatConversionCharRadix(FormatConversionChar c) {
switch (c) {
case FormatConversionChar::x:
case FormatConversionChar::X:
case FormatConversionChar::a:
case FormatConversionChar::A:
case FormatConversionChar::p:
return 16;
case FormatConversionChar::o:
return 8;
default:
return 10;
}
}
inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
switch (c) {
case FormatConversionChar::X:
@ -198,30 +183,6 @@ inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
}
}
inline bool FormatConversionCharIsSigned(FormatConversionChar c) {
switch (c) {
case FormatConversionChar::d:
case FormatConversionChar::i:
return true;
default:
return false;
}
}
inline bool FormatConversionCharIsIntegral(FormatConversionChar c) {
switch (c) {
case FormatConversionChar::d:
case FormatConversionChar::i:
case FormatConversionChar::u:
case FormatConversionChar::o:
case FormatConversionChar::x:
case FormatConversionChar::X:
return true;
default:
return false;
}
}
inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
switch (c) {
case FormatConversionChar::a:

View file

@ -254,8 +254,8 @@ class FormatCountCapture {
// argument, etc.
template <typename... Args>
using FormatSpec =
typename str_format_internal::FormatSpecDeductionBarrier<Args...>::type;
using FormatSpec = str_format_internal::FormatSpecTemplate<
str_format_internal::ArgumentToConv<Args>()...>;
// ParsedFormat
//

View file

@ -246,10 +246,10 @@ absl_cc_library(
"internal/conformance_aliases.h"
"internal/conformance_archetype.h"
"internal/conformance_profile.h"
"internal/conformance_testing.h",
"internal/conformance_testing_helpers.h",
"internal/parentheses.h",
"internal/transform_args.h",
"internal/conformance_testing.h"
"internal/conformance_testing_helpers.h"
"internal/parentheses.h"
"internal/transform_args.h"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS