mirror of
https://github.com/bkaradzic/bx.git
synced 2026-02-17 12:42:34 +01:00
Added: bx::formatHumanNumber. (#368)
This commit is contained in:
committed by
GitHub
parent
016167548e
commit
36ad6131f4
@@ -450,6 +450,16 @@ namespace bx
|
||||
template <typename Ty>
|
||||
void stringPrintf(Ty& _out, const char* _format, ...);
|
||||
|
||||
/// Format number to human readable representation.
|
||||
///
|
||||
/// @param[out] _out Output string.
|
||||
/// @param[in] _count Maximum output string count.
|
||||
/// @param[in] _value Value.
|
||||
/// @param[in] _numFrac Number of fraction digits.
|
||||
/// @returns Length of output string.
|
||||
///
|
||||
int32_t formatHumanNumber(char* _out, int32_t _count, double _value, int32_t _numFrac);
|
||||
|
||||
/// Convert size in bytes to human readable string kibi units.
|
||||
int32_t prettify(char* _out, int32_t _count, uint64_t _value, Units::Enum _units = Units::Kibi);
|
||||
|
||||
|
||||
@@ -1280,6 +1280,70 @@ namespace bx
|
||||
return total;
|
||||
}
|
||||
|
||||
int32_t formatHumanNumber(char* _out, int32_t _count, double _value, int32_t _numFrac)
|
||||
{
|
||||
char temp[64];
|
||||
int32_t len = snprintf(temp, sizeof(temp), "%.*f", _numFrac, _value);
|
||||
int32_t intPartLen = len;
|
||||
|
||||
if (len >= _numFrac+1
|
||||
&& '.' == temp[len-_numFrac-1])
|
||||
{
|
||||
intPartLen = len-_numFrac-1;
|
||||
|
||||
bool zero = true;
|
||||
|
||||
for (int32_t ii = _numFrac; 0 < ii && zero; --ii)
|
||||
{
|
||||
zero &= temp[len-ii] == '0';
|
||||
}
|
||||
|
||||
if (zero)
|
||||
{
|
||||
temp[len-_numFrac-1] = '\0';
|
||||
len = intPartLen;
|
||||
}
|
||||
}
|
||||
|
||||
const int32_t fracPartLen = len - intPartLen;
|
||||
const int32_t commas = (intPartLen > 3) ? (intPartLen - 1) / 3 : 0;
|
||||
const int32_t total = intPartLen + fracPartLen + commas;
|
||||
|
||||
if (_count < total)
|
||||
{
|
||||
if (0 < _count)
|
||||
{
|
||||
_out[0] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* out = _out + total;
|
||||
*out = '\0';
|
||||
|
||||
if (0 != fracPartLen)
|
||||
{
|
||||
out -= fracPartLen;
|
||||
memCopy(out, &temp[intPartLen], fracPartLen);
|
||||
}
|
||||
|
||||
int32_t group = 0;
|
||||
for (int32_t ii = intPartLen - 1; ii >= 0; --ii)
|
||||
{
|
||||
*--out = temp[ii];
|
||||
|
||||
if (3 == ++group
|
||||
&& 0 < ii)
|
||||
{
|
||||
*--out = ',';
|
||||
group = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static const char s_units[] = { 'B', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
|
||||
|
||||
template<uint32_t Kilo, char KiloCh0, char KiloCh1, CharFn fn>
|
||||
@@ -1295,7 +1359,10 @@ namespace bx
|
||||
++idx;
|
||||
}
|
||||
|
||||
return snprintf(_out, _count, "%0.2f %c%c%c", value
|
||||
char human[32];
|
||||
formatHumanNumber(human, sizeof(human), value, 2);
|
||||
|
||||
return snprintf(_out, _count, "%s %c%c%c", human
|
||||
, fn(s_units[idx])
|
||||
, idx > 0 ? KiloCh0 : '\0'
|
||||
, KiloCh1
|
||||
|
||||
@@ -24,10 +24,10 @@ TEST_CASE("prettify", "[string]")
|
||||
{
|
||||
char tmp[1024];
|
||||
prettify(tmp, BX_COUNTOF(tmp), 4000, bx::Units::Kilo);
|
||||
REQUIRE(0 == bx::strCmp(tmp, "4.00 kB") );
|
||||
REQUIRE(0 == bx::strCmp(tmp, "4 kB") );
|
||||
|
||||
prettify(tmp, BX_COUNTOF(tmp), 4096, bx::Units::Kibi);
|
||||
REQUIRE(0 == bx::strCmp(tmp, "4.00 KiB") );
|
||||
REQUIRE(0 == bx::strCmp(tmp, "4 KiB") );
|
||||
}
|
||||
|
||||
TEST_CASE("chars", "[string]")
|
||||
@@ -762,3 +762,37 @@ TEST(tinystl_string_assign)
|
||||
CHECK( other.size() == 0 );
|
||||
}
|
||||
}
|
||||
|
||||
bool testFormatHumanNumber(bx::StringView _expected, double _value, int32_t _numFrac, int32_t _bufferSize = 32)
|
||||
{
|
||||
char* tmp = (char*)BX_STACK_ALLOC(_bufferSize);
|
||||
int32_t total = bx::formatHumanNumber(tmp, _bufferSize, _value, _numFrac);
|
||||
|
||||
bx::StringView human(tmp, total);
|
||||
|
||||
const bool result = 0 == bx::strCmp(human, _expected);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
DBG(
|
||||
"expected: '%S' (len: %d), human: '%S' (len: %d)"
|
||||
, &_expected
|
||||
, _expected.getLength()
|
||||
, &human
|
||||
, human.getLength()
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST_CASE("formatHumanNumber", "[string]")
|
||||
{
|
||||
REQUIRE(testFormatHumanNumber("1,389,983,113.89", 1389983113.891389, 2) );
|
||||
REQUIRE(testFormatHumanNumber("13,899,831.1389", 13899831.1389, 4) );
|
||||
REQUIRE(testFormatHumanNumber("1,389.10", 1389.1, 2) );
|
||||
REQUIRE(testFormatHumanNumber("1,389", 1389.0, 8) );
|
||||
REQUIRE(testFormatHumanNumber("0", 0.0, 2) );
|
||||
|
||||
REQUIRE(testFormatHumanNumber("", 1389983113.891389, 2, 4) );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user