Helper for making large values human-readable.

This commit is contained in:
Scott Lamb 2016-01-13 07:20:39 -08:00
parent 95523c3522
commit d38eb9103e
3 changed files with 39 additions and 0 deletions

View File

@ -99,6 +99,19 @@ TEST(ToHexTest, Simple) {
EXPECT_EQ("12 34 de ad be ef", ToHex("\x12\x34\xde\xad\xbe\xef", true)); EXPECT_EQ("12 34 de ad be ef", ToHex("\x12\x34\xde\xad\xbe\xef", true));
} }
TEST(HumanizeTest, Simple) {
EXPECT_EQ("1.0 B", HumanizeWithBinaryPrefix(1.f, "B"));
EXPECT_EQ("1.0 KiB", HumanizeWithBinaryPrefix(UINT64_C(1) << 10, "B"));
EXPECT_EQ("1.0 EiB", HumanizeWithBinaryPrefix(UINT64_C(1) << 60, "B"));
EXPECT_EQ("1.5 EiB", HumanizeWithBinaryPrefix(
(UINT64_C(1) << 60) + (UINT64_C(1) << 59), "B"));
EXPECT_EQ("16.0 EiB", HumanizeWithBinaryPrefix(
std::numeric_limits<uint64_t>::max(), "B"));
EXPECT_EQ("1.0 Mbps", HumanizeWithDecimalPrefix(1e6f, "bps"));
EXPECT_EQ("1000.0 Ebps", HumanizeWithDecimalPrefix(1e21, "bps"));
}
} // namespace } // namespace
} // namespace moonfire_nvr } // namespace moonfire_nvr

View File

@ -45,6 +45,15 @@ char HexDigit(unsigned int i) {
return (i < 16) ? kHexadigits[i] : 'x'; return (i < 16) ? kHexadigits[i] : 'x';
} }
std::string Humanize(std::initializer_list<const re2::StringPiece> prefixes,
float f, float n, re2::StringPiece suffix) {
size_t i;
for (i = 0; i < prefixes.size() - 1 && n >= f; ++i) n /= f;
char buf[64];
snprintf(buf, sizeof(buf), "%.1f", n);
return StrCat(buf, *(prefixes.begin() + i), suffix);
}
} // namespace } // namespace
namespace internal { namespace internal {
@ -124,6 +133,18 @@ std::string ToHex(re2::StringPiece in, bool pad) {
return out; return out;
} }
std::string HumanizeWithDecimalPrefix(float n, re2::StringPiece suffix) {
static const std::initializer_list<const re2::StringPiece> kPrefixes = {
" ", " k", " M", " G", " T", " P", " E"};
return Humanize(kPrefixes, 1000., n, suffix);
}
std::string HumanizeWithBinaryPrefix(float n, re2::StringPiece suffix) {
static const std::initializer_list<const re2::StringPiece> kPrefixes = {
" ", " Ki", " Mi", " Gi", " Ti", " Pi", " Ei"};
return Humanize(kPrefixes, 1024., n, suffix);
}
bool strto64(const char *str, int base, const char **endptr, int64_t *value) { bool strto64(const char *str, int base, const char **endptr, int64_t *value) {
static_assert(sizeof(int64_t) == sizeof(long long int), static_assert(sizeof(int64_t) == sizeof(long long int),
"unknown memory model"); "unknown memory model");

View File

@ -122,6 +122,11 @@ std::string EscapeHtml(const std::string &input);
// For example, ToHex("\xde\xad\xbe\xef", true) returns "de ad be ef". // For example, ToHex("\xde\xad\xbe\xef", true) returns "de ad be ef".
std::string ToHex(re2::StringPiece in, bool pad = false); std::string ToHex(re2::StringPiece in, bool pad = false);
// Return a human-friendly approximation of the given non-negative value, using
// SI (base-10) or IEC (base-2) prefixes.
std::string HumanizeWithDecimalPrefix(float n, re2::StringPiece suffix);
std::string HumanizeWithBinaryPrefix(float n, re2::StringPiece suffix);
// Wrapper around ::strtol that returns true iff valid and corrects // Wrapper around ::strtol that returns true iff valid and corrects
// constness. // constness.
bool strto64(const char *str, int base, const char **endptr, int64_t *value); bool strto64(const char *str, int base, const char **endptr, int64_t *value);