Changes imported from Abseil "staging" branch:
- a0405e7870a80a9dbc6784b06795e7df5a8c90f5 Internal change by Daniel Katz <katzdm@google.com> - 2888fe17796d7afa45f4b6ca7eb8e88f52739c39 StrCat: Support zero-padding and space-padding for decima... by Jorg Brown <jorg@google.com> - feebc521195241783730df9700394f6585550ff2 Merge GitHub PR #91. by Derek Mauro <dmauro@google.com> - e8164335efefb7335f407c17a16fce2ba4f24e3e This changes the value base_internal::kOnceDone from 32-b... by Abseil Team <absl-team@google.com> - 0f6085f3f0ee1d6baf9a558d07a25c2fcde93273 Remove `compliant` field from some type trait structs. by Matt Armstrong <marmstrong@google.com> GitOrigin-RevId: a0405e7870a80a9dbc6784b06795e7df5a8c90f5 Change-Id: Ic2efd40f6ec35f79a8aa12d4475cbea3150756d7
This commit is contained in:
parent
4791df7d1a
commit
0dc82b9d55
6 changed files with 151 additions and 18 deletions
11
WORKSPACE
11
WORKSPACE
|
@ -1,4 +1,15 @@
|
|||
workspace(name = "com_google_absl")
|
||||
# Bazel toolchains
|
||||
http_archive(
|
||||
name = "bazel_toolchains",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/f3b09700fae5d7b6e659d7cefe0dcc6e8498504c.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-toolchains/archive/f3b09700fae5d7b6e659d7cefe0dcc6e8498504c.tar.gz",
|
||||
],
|
||||
strip_prefix = "bazel-toolchains-f3b09700fae5d7b6e659d7cefe0dcc6e8498504c",
|
||||
sha256 = "ed829b5eea8af1f405f4cc3d6ecfc3b1365bb7843171036030a31b5127002311",
|
||||
)
|
||||
|
||||
# GoogleTest/GoogleMock framework. Used by most unit-tests.
|
||||
http_archive(
|
||||
name = "com_google_googletest",
|
||||
|
|
|
@ -134,7 +134,10 @@ enum {
|
|||
kOnceInit = 0,
|
||||
kOnceRunning = 0x65C2937B,
|
||||
kOnceWaiter = 0x05A308D2,
|
||||
kOnceDone = 0x3F2D8AB0,
|
||||
// A very small constant is chosen for kOnceDone so that it fit in a single
|
||||
// compare with immediate instruction for most common ISAs. This is verified
|
||||
// for x86, POWER and ARM.
|
||||
kOnceDone = 221, // Random Number
|
||||
};
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
|
|
|
@ -150,6 +150,7 @@ struct is_trivially_destructible
|
|||
: std::integral_constant<bool, __has_trivial_destructor(T) &&
|
||||
std::is_destructible<T>::value> {
|
||||
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
|
||||
private:
|
||||
static constexpr bool compliant = std::is_trivially_destructible<T>::value ==
|
||||
is_trivially_destructible::value;
|
||||
static_assert(compliant || std::is_trivially_destructible<T>::value,
|
||||
|
@ -199,6 +200,7 @@ struct is_trivially_default_constructible
|
|||
std::is_default_constructible<T>::value &&
|
||||
is_trivially_destructible<T>::value> {
|
||||
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
|
||||
private:
|
||||
static constexpr bool compliant =
|
||||
std::is_trivially_default_constructible<T>::value ==
|
||||
is_trivially_default_constructible::value;
|
||||
|
@ -230,6 +232,7 @@ struct is_trivially_copy_constructible
|
|||
std::is_copy_constructible<T>::value &&
|
||||
is_trivially_destructible<T>::value> {
|
||||
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
|
||||
private:
|
||||
static constexpr bool compliant =
|
||||
std::is_trivially_copy_constructible<T>::value ==
|
||||
is_trivially_copy_constructible::value;
|
||||
|
@ -262,6 +265,7 @@ struct is_trivially_copy_assignable
|
|||
: std::integral_constant<bool, __has_trivial_assign(T) &&
|
||||
std::is_copy_assignable<T>::value> {
|
||||
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
|
||||
private:
|
||||
static constexpr bool compliant =
|
||||
std::is_trivially_copy_assignable<T>::value ==
|
||||
is_trivially_copy_assignable::value;
|
||||
|
|
|
@ -45,6 +45,37 @@ AlphaNum::AlphaNum(Hex hex) {
|
|||
piece_ = absl::string_view(beg, end - beg);
|
||||
}
|
||||
|
||||
AlphaNum::AlphaNum(Dec dec) {
|
||||
assert(dec.width <= numbers_internal::kFastToBufferSize);
|
||||
char* const end = &digits_[numbers_internal::kFastToBufferSize];
|
||||
char* const minfill = end - dec.width;
|
||||
char* writer = end;
|
||||
uint64_t value = dec.value;
|
||||
bool neg = dec.neg;
|
||||
while (value > 9) {
|
||||
*--writer = '0' + (value % 10);
|
||||
value /= 10;
|
||||
}
|
||||
*--writer = '0' + value;
|
||||
if (neg) *--writer = '-';
|
||||
|
||||
ptrdiff_t fillers = writer - minfill;
|
||||
if (fillers > 0) {
|
||||
// Tricky: if the fill character is ' ', then it's <fill><+/-><digits>
|
||||
// But...: if the fill character is '0', then it's <+/-><fill><digits>
|
||||
bool add_sign_again = false;
|
||||
if (neg && dec.fill == '0') { // If filling with '0',
|
||||
++writer; // ignore the sign we just added
|
||||
add_sign_again = true; // and re-add the sign later.
|
||||
}
|
||||
writer -= fillers;
|
||||
std::fill_n(writer, fillers, dec.fill);
|
||||
if (add_sign_again) *--writer = '-';
|
||||
}
|
||||
|
||||
piece_ = absl::string_view(writer, end - writer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// StrCat()
|
||||
// This merges the given strings or integers, with no delimiter. This
|
||||
|
|
|
@ -76,10 +76,10 @@ struct AlphaNumBuffer {
|
|||
|
||||
} // namespace strings_internal
|
||||
|
||||
// Enum that specifies the number of significant digits to return in a `Hex`
|
||||
// conversion and fill character to use. A `kZeroPad2` value, for example, would
|
||||
// produce hexadecimal strings such as "0A","0F" and 'kSpacePad5' value would
|
||||
// produce hexadecimal strings such as " A"," F".
|
||||
// Enum that specifies the number of significant digits to return in a `Hex` or
|
||||
// `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
|
||||
// would produce hexadecimal strings such as "0A","0F" and a 'kSpacePad5' value
|
||||
// would produce hexadecimal strings such as " A"," F".
|
||||
enum PadSpec {
|
||||
kNoPad = 1,
|
||||
kZeroPad2,
|
||||
|
@ -153,6 +153,32 @@ struct Hex {
|
|||
fill(spec >= absl::kSpacePad2 ? ' ' : '0') {}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Dec
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// `Dec` stores a set of decimal std::string conversion parameters for use
|
||||
// within `AlphaNum` std::string conversions. Dec is slower than the default
|
||||
// integer conversion, so use it only if you need padding.
|
||||
struct Dec {
|
||||
uint64_t value;
|
||||
uint8_t width;
|
||||
char fill;
|
||||
bool neg;
|
||||
|
||||
template <typename Int>
|
||||
explicit Dec(Int v, PadSpec spec = absl::kNoPad,
|
||||
typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr)
|
||||
: value(v >= 0 ? static_cast<uint64_t>(v)
|
||||
: uint64_t{0} - static_cast<uint64_t>(v)),
|
||||
width(spec == absl::kNoPad
|
||||
? 1
|
||||
: spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
|
||||
: spec - absl::kZeroPad2 + 2),
|
||||
fill(spec >= absl::kSpacePad2 ? ' ' : '0'),
|
||||
neg(v < 0) {}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// AlphaNum
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -191,6 +217,7 @@ class AlphaNum {
|
|||
: piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
|
||||
|
||||
AlphaNum(Hex hex); // NOLINT(runtime/explicit)
|
||||
AlphaNum(Dec dec); // NOLINT(runtime/explicit)
|
||||
|
||||
template <size_t size>
|
||||
AlphaNum( // NOLINT(runtime/explicit)
|
||||
|
|
|
@ -431,28 +431,85 @@ void CheckHex(IntType v, const char* nopad_format, const char* zeropad_format,
|
|||
}
|
||||
}
|
||||
|
||||
void CheckHex64(uint64_t v) {
|
||||
unsigned long long llv = v; // NOLINT(runtime/int)
|
||||
template <typename IntType>
|
||||
void CheckDec(IntType v, const char* nopad_format, const char* zeropad_format,
|
||||
const char* spacepad_format) {
|
||||
char expected[256];
|
||||
|
||||
CheckHex(llv, "%llx", "%0*llx", "%*llx");
|
||||
std::string actual = absl::StrCat(absl::Dec(v, absl::kNoPad));
|
||||
snprintf(expected, sizeof(expected), nopad_format, v);
|
||||
EXPECT_EQ(expected, actual) << " decimal value " << v;
|
||||
|
||||
for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad16; ++spec) {
|
||||
std::string actual =
|
||||
absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec)));
|
||||
snprintf(expected, sizeof(expected), zeropad_format,
|
||||
spec - absl::kZeroPad2 + 2, v);
|
||||
EXPECT_EQ(expected, actual)
|
||||
<< " decimal value " << v << " format '" << zeropad_format
|
||||
<< "' digits " << (spec - absl::kZeroPad2 + 2);
|
||||
}
|
||||
|
||||
for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad16; ++spec) {
|
||||
std::string actual =
|
||||
absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec)));
|
||||
snprintf(expected, sizeof(expected), spacepad_format,
|
||||
spec - absl::kSpacePad2 + 2, v);
|
||||
EXPECT_EQ(expected, actual)
|
||||
<< " decimal value " << v << " format '" << spacepad_format
|
||||
<< "' digits " << (spec - absl::kSpacePad2 + 2);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Int32Type>
|
||||
void CheckHex32(Int32Type v) {
|
||||
CheckHex(v, "%x", "%0*x", "%*x");
|
||||
void CheckHexDec64(uint64_t v) {
|
||||
unsigned long long ullv = v; // NOLINT(runtime/int)
|
||||
|
||||
CheckHex(ullv, "%llx", "%0*llx", "%*llx");
|
||||
CheckDec(ullv, "%llu", "%0*llu", "%*llu");
|
||||
|
||||
long long llv = static_cast<long long>(ullv); // NOLINT(runtime/int)
|
||||
CheckDec(llv, "%lld", "%0*lld", "%*lld");
|
||||
}
|
||||
|
||||
void CheckHexDec32(uint32_t uv) {
|
||||
CheckHex(uv, "%x", "%0*x", "%*x");
|
||||
CheckDec(uv, "%u", "%0*u", "%*u");
|
||||
int32_t v = static_cast<int32_t>(uv);
|
||||
CheckDec(v, "%d", "%0*d", "%*d");
|
||||
}
|
||||
|
||||
void CheckAll(uint64_t v) {
|
||||
CheckHexDec64(v);
|
||||
CheckHexDec32(static_cast<uint32_t>(v));
|
||||
}
|
||||
|
||||
void TestFastPrints() {
|
||||
// Test min int to make sure that works
|
||||
// Test all small ints; there aren't many and they're common.
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
CheckHex64(i);
|
||||
CheckHex32(static_cast<uint32_t>(i));
|
||||
CheckHex32(i);
|
||||
CheckHex32(-i);
|
||||
CheckAll(i);
|
||||
}
|
||||
|
||||
CheckHex64(uint64_t{0x123456789abcdef0});
|
||||
CheckHex32(0x12345678U);
|
||||
CheckAll(std::numeric_limits<uint64_t>::max());
|
||||
CheckAll(std::numeric_limits<uint64_t>::max() - 1);
|
||||
CheckAll(std::numeric_limits<int64_t>::min());
|
||||
CheckAll(std::numeric_limits<int64_t>::min() + 1);
|
||||
CheckAll(std::numeric_limits<uint32_t>::max());
|
||||
CheckAll(std::numeric_limits<uint32_t>::max() - 1);
|
||||
CheckAll(std::numeric_limits<int32_t>::min());
|
||||
CheckAll(std::numeric_limits<int32_t>::min() + 1);
|
||||
CheckAll(999999999); // fits in 32 bits
|
||||
CheckAll(1000000000); // fits in 32 bits
|
||||
CheckAll(9999999999); // doesn't fit in 32 bits
|
||||
CheckAll(10000000000); // doesn't fit in 32 bits
|
||||
CheckAll(999999999999999999); // fits in signed 64-bit
|
||||
CheckAll(9999999999999999999u); // fits in unsigned 64-bit, but not signed.
|
||||
CheckAll(1000000000000000000); // fits in signed 64-bit
|
||||
CheckAll(10000000000000000000u); // fits in unsigned 64-bit, but not signed.
|
||||
|
||||
CheckAll(999999999876543210); // check all decimal digits, signed
|
||||
CheckAll(9999999999876543210u); // check all decimal digits, unsigned.
|
||||
CheckAll(0x123456789abcdef0); // check all hex digits
|
||||
CheckAll(0x12345678);
|
||||
|
||||
int8_t minus_one_8bit = -1;
|
||||
EXPECT_EQ("ff", absl::StrCat(absl::Hex(minus_one_8bit)));
|
||||
|
|
Loading…
Reference in a new issue