mirror of
https://github.com/bkaradzic/bx.git
synced 2026-06-08 03:03:48 +00:00
bx::vsnprintf fixes. Added more unit tests. (#372)
This commit is contained in:
committed by
GitHub
parent
fa641d8581
commit
1e0ee96b8d
130
src/string.cpp
130
src/string.cpp
@@ -722,11 +722,13 @@ namespace bx
|
||||
, base(10)
|
||||
, prec(INT32_MAX)
|
||||
, fill(' ')
|
||||
, fmt('f')
|
||||
, bits(0)
|
||||
, left(false)
|
||||
, upper(false)
|
||||
, spec(false)
|
||||
, sign(false)
|
||||
, space(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -734,11 +736,13 @@ namespace bx
|
||||
int32_t base;
|
||||
int32_t prec;
|
||||
char fill;
|
||||
char fmt;
|
||||
uint8_t bits;
|
||||
bool left;
|
||||
bool upper;
|
||||
bool spec;
|
||||
bool sign;
|
||||
bool space;
|
||||
};
|
||||
|
||||
static int32_t write(WriterI* _writer, const char* _str, int32_t _len, const Param& _param, Error* _err)
|
||||
@@ -746,14 +750,12 @@ namespace bx
|
||||
int32_t size = 0;
|
||||
int32_t len = (int32_t)strLen(_str, _len);
|
||||
|
||||
if (_param.width > 0)
|
||||
{
|
||||
len = min(_param.width, len);
|
||||
}
|
||||
|
||||
const bool hasMinus = (NULL != _str && '-' == _str[0]);
|
||||
const bool hasSign = _param.sign || hasMinus;
|
||||
char sign = hasSign ? hasMinus ? '-' : '+' : '\0';
|
||||
const bool hasSign = _param.sign || _param.space || hasMinus;
|
||||
char sign = '\0';
|
||||
if (hasMinus) { sign = '-'; }
|
||||
else if (_param.sign) { sign = '+'; }
|
||||
else if (_param.space) { sign = ' '; }
|
||||
|
||||
const char* str = _str;
|
||||
if (hasMinus)
|
||||
@@ -837,6 +839,64 @@ namespace bx
|
||||
return write(_writer, _str.getPtr(), min(_param.prec, _str.getLength() ), _param, _err);
|
||||
}
|
||||
|
||||
static int32_t writeInteger(WriterI* _writer, const char* _str, int32_t _len, const Param& _param, Error* _err)
|
||||
{
|
||||
Param param = _param;
|
||||
|
||||
char str[64];
|
||||
memCopy(str, _str, _len + 1);
|
||||
|
||||
int32_t len = _len;
|
||||
|
||||
if (param.prec != INT32_MAX)
|
||||
{
|
||||
param.fill = ' ';
|
||||
|
||||
const int32_t signLen = (len > 0 && '-' == str[0]) ? 1 : 0;
|
||||
const int32_t digitLen = len - signLen;
|
||||
|
||||
if (param.prec > digitLen)
|
||||
{
|
||||
const int32_t zeros = min(param.prec - digitLen, int32_t(sizeof(str)) - len - 1);
|
||||
memMove(&str[signLen + zeros], &str[signLen], digitLen + 1);
|
||||
|
||||
for (int32_t ii = 0; ii < zeros; ++ii)
|
||||
{
|
||||
str[signLen + ii] = '0';
|
||||
}
|
||||
|
||||
len += zeros;
|
||||
}
|
||||
|
||||
param.prec = INT32_MAX;
|
||||
}
|
||||
|
||||
if (param.spec
|
||||
&& 0 < len)
|
||||
{
|
||||
if (8 == param.base)
|
||||
{
|
||||
if (str[0] != '0')
|
||||
{
|
||||
memMove(&str[1], &str[0], len + 1);
|
||||
str[0] = '0';
|
||||
len++;
|
||||
}
|
||||
}
|
||||
else if (16 == param.base)
|
||||
{
|
||||
memMove(&str[2], &str[0], len + 1);
|
||||
str[0] = '0';
|
||||
str[1] = param.upper ? 'X' : 'x';
|
||||
len += 2;
|
||||
}
|
||||
|
||||
param.spec = false;
|
||||
}
|
||||
|
||||
return write(_writer, str, len, param, _err);
|
||||
}
|
||||
|
||||
static int32_t write(WriterI* _writer, int32_t _i, const Param& _param, Error* _err)
|
||||
{
|
||||
char str[33];
|
||||
@@ -847,7 +907,14 @@ namespace bx
|
||||
return 0;
|
||||
}
|
||||
|
||||
return write(_writer, str, len, _param, _err);
|
||||
if (0 == _param.prec
|
||||
&& 0 == _i)
|
||||
{
|
||||
str[0] = '\0';
|
||||
len = 0;
|
||||
}
|
||||
|
||||
return writeInteger(_writer, str, len, _param, _err);
|
||||
}
|
||||
|
||||
static int32_t write(WriterI* _writer, int64_t _i, const Param& _param, Error* _err)
|
||||
@@ -860,7 +927,14 @@ namespace bx
|
||||
return 0;
|
||||
}
|
||||
|
||||
return write(_writer, str, len, _param, _err);
|
||||
if (0 == _param.prec
|
||||
&& 0 == _i)
|
||||
{
|
||||
str[0] = '\0';
|
||||
len = 0;
|
||||
}
|
||||
|
||||
return writeInteger(_writer, str, len, _param, _err);
|
||||
}
|
||||
|
||||
static int32_t write(WriterI* _writer, uint32_t _u, const Param& _param, Error* _err)
|
||||
@@ -873,7 +947,14 @@ namespace bx
|
||||
return 0;
|
||||
}
|
||||
|
||||
return write(_writer, str, len, _param, _err);
|
||||
if (0 == _param.prec
|
||||
&& 0 == _u)
|
||||
{
|
||||
str[0] = '\0';
|
||||
len = 0;
|
||||
}
|
||||
|
||||
return writeInteger(_writer, str, len, _param, _err);
|
||||
}
|
||||
|
||||
static int32_t write(WriterI* _writer, uint64_t _u, const Param& _param, Error* _err)
|
||||
@@ -886,7 +967,14 @@ namespace bx
|
||||
return 0;
|
||||
}
|
||||
|
||||
return write(_writer, str, len, _param, _err);
|
||||
if (0 == _param.prec
|
||||
&& 0 == _u)
|
||||
{
|
||||
str[0] = '\0';
|
||||
len = 0;
|
||||
}
|
||||
|
||||
return writeInteger(_writer, str, len, _param, _err);
|
||||
}
|
||||
|
||||
static int32_t write(WriterI* _writer, double _d, const Param& _param, Error* _err)
|
||||
@@ -902,7 +990,9 @@ namespace bx
|
||||
const char* dot = strFind(str, INT32_MAX, '.');
|
||||
if (NULL != dot)
|
||||
{
|
||||
const int32_t prec = INT32_MAX == _param.prec ? 6 : _param.prec;
|
||||
const int32_t defaultPrec = ('g' == _param.fmt) ? 6 : 6;
|
||||
int32_t prec = INT32_MAX == _param.prec ? defaultPrec : _param.prec;
|
||||
|
||||
const char* strEnd = str + len;
|
||||
const char* exponent = strFind(str, INT32_MAX, 'e');
|
||||
const char* fracEnd = NULL != exponent ? exponent : strEnd;
|
||||
@@ -992,11 +1082,11 @@ namespace bx
|
||||
switch (ch)
|
||||
{
|
||||
default:
|
||||
case ' ': param.fill = ' '; break;
|
||||
case '-': param.left = true; break;
|
||||
case '+': param.sign = true; break;
|
||||
case '0': param.fill = '0'; break;
|
||||
case '#': param.spec = true; break;
|
||||
case ' ': param.space = true; break;
|
||||
case '-': param.left = true; break;
|
||||
case '+': param.sign = true; break;
|
||||
case '0': param.fill = '0'; break;
|
||||
case '#': param.spec = true; break;
|
||||
}
|
||||
|
||||
read(&reader, ch, &err);
|
||||
@@ -1043,7 +1133,8 @@ namespace bx
|
||||
if ('*' == ch)
|
||||
{
|
||||
read(&reader, ch, &err);
|
||||
param.prec = va_arg(_argList, int32_t);
|
||||
int32_t prec = va_arg(_argList, int32_t);
|
||||
param.prec = prec >= 0 ? prec : INT32_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1150,10 +1241,11 @@ namespace bx
|
||||
};
|
||||
break;
|
||||
|
||||
case 'e': case 'E':
|
||||
case 'e': case 'E':
|
||||
case 'f': case 'F':
|
||||
case 'g': case 'G':
|
||||
param.upper = isUpper(ch);
|
||||
param.fmt = toLower(ch);
|
||||
size += write(_writer, va_arg(_argList, double), param, _err);
|
||||
break;
|
||||
|
||||
|
||||
@@ -79,11 +79,13 @@ int runAllTests(int32_t _argc, const char* _argv[])
|
||||
ConfigData config;
|
||||
config.defaultColourMode = BX_PLATFORM_EMSCRIPTEN
|
||||
? ColourMode::None
|
||||
: ColourMode::PlatformDefault
|
||||
: ColourMode::PlatformDefault
|
||||
;
|
||||
config.showDurations = ShowDurations::Always;
|
||||
|
||||
session.useConfigData(config);
|
||||
|
||||
return session.run(_argc, _argv);
|
||||
const int32_t result = session.run(_argc, _argv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -159,67 +159,78 @@ TEST_CASE("Format %f", "[string][printf]")
|
||||
REQUIRE(test("0.0039", "%.4f", 0.00390625) );
|
||||
|
||||
REQUIRE(test("0.003906", "%f", 0.00390625) );
|
||||
REQUIRE(testNotStdCompliant("-1.234567e-9", "%f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.234567e-9", "%f", -1.234567e-9) );
|
||||
|
||||
REQUIRE(testNotStdCompliant("-1e-9", "%.0f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.2e-9", "%.1f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.23e-9", "%.2f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.234e-9", "%.3f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.2345e-9", "%.4f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.23456e-9", "%.5f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.234567e-9", "%.6f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.2345670e-9", "%.7f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.23456700e-9", "%.8f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.234567000e-9", "%.9f", -1.234567e-9) );
|
||||
REQUIRE(testNotStdCompliant("-1.2345670000e-9", "%.10f", -1.234567e-9) );
|
||||
REQUIRE(test("-1e-9", "%.0f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.2e-9", "%.1f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.23e-9", "%.2f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.234e-9", "%.3f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.2345e-9", "%.4f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.23456e-9", "%.5f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.234567e-9", "%.6f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.2345670e-9", "%.7f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.23456700e-9", "%.8f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.234567000e-9", "%.9f", -1.234567e-9) );
|
||||
REQUIRE(test("-1.2345670000e-9", "%.10f", -1.234567e-9) );
|
||||
|
||||
REQUIRE(testNotStdCompliant("3.141592", "%f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.141592", "%F", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3", "%.0f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.1", "%.1f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.14", "%.2f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.141", "%.3f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.1415", "%.4f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.14159", "%.5f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.141592", "%.6f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.1415926", "%.7f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.14159265", "%.8f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.141592653", "%.9f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.1415926535", "%.10f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.14159265358", "%.11f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.141592653589", "%.12f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.1415926535897", "%.13f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.14159265358979", "%.14f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.141592653589793", "%.15f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.1415926535897930", "%.16f", 3.1415926535897932) );
|
||||
REQUIRE(testNotStdCompliant("3.1415926535897930", "%.16F", 3.1415926535897932) );
|
||||
REQUIRE(test("3.141592", "%f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.141592", "%F", 3.1415926535897932) );
|
||||
REQUIRE(test("3", "%.0f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.1", "%.1f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.14", "%.2f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.141", "%.3f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.1415", "%.4f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.14159", "%.5f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.141592", "%.6f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.1415926", "%.7f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.14159265", "%.8f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.141592653", "%.9f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.1415926535", "%.10f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.14159265358", "%.11f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.141592653589", "%.12f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.1415926535897", "%.13f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.14159265358979", "%.14f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.141592653589793", "%.15f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.1415926535897930", "%.16f", 3.1415926535897932) );
|
||||
REQUIRE(test("3.1415926535897930", "%.16F", 3.1415926535897932) );
|
||||
|
||||
REQUIRE(testNotStdCompliant("-3.141592e-9", "%f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.141592E-9", "%F", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3e-9", "%.0f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.1e-9", "%.1f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.14e-9", "%.2f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.141e-9", "%.3f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.1415e-9", "%.4f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.14159e-9", "%.5f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.141592e-9", "%.6f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.1415926e-9", "%.7f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.14159265e-9", "%.8f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.141592653e-9", "%.9f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.1415926535e-9", "%.10f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.14159265358e-9", "%.11f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.141592653589e-9", "%.12f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.1415926535897e-9", "%.13f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.14159265358979e-9", "%.14f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.141592653589793e-9", "%.15f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.1415926535897930e-9", "%.16f", -3.1415926535897932e-9) );
|
||||
REQUIRE(testNotStdCompliant("-3.1415926535897930E-9", "%.16F", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.141592e-9", "%f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.141592E-9", "%F", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3e-9", "%.0f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.1e-9", "%.1f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.14e-9", "%.2f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.141e-9", "%.3f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.1415e-9", "%.4f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.14159e-9", "%.5f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.141592e-9", "%.6f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.1415926e-9", "%.7f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.14159265e-9", "%.8f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.141592653e-9", "%.9f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.1415926535e-9", "%.10f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.14159265358e-9", "%.11f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.141592653589e-9", "%.12f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.1415926535897e-9", "%.13f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.14159265358979e-9", "%.14f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.141592653589793e-9", "%.15f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.1415926535897930e-9", "%.16f", -3.1415926535897932e-9) );
|
||||
REQUIRE(test("-3.1415926535897930E-9", "%.16F", -3.1415926535897932e-9) );
|
||||
|
||||
REQUIRE(testNotStdCompliant("1e-12", "%f", 1e-12));
|
||||
REQUIRE(test("1e-12", "%f", 1e-12));
|
||||
|
||||
REQUIRE(test("0.00390625", "%.8f", 0.00390625) );
|
||||
REQUIRE(test("-0.00390625", "%.8f", -0.00390625) );
|
||||
REQUIRE(test("1.50000000000000000", "%.17f", 1.5) );
|
||||
|
||||
REQUIRE(test("-3.000000", "%f", -3.0) );
|
||||
REQUIRE(test("-0.000000", "%f", -0.) );
|
||||
REQUIRE(test("4.1", "%.1f", 4.1) );
|
||||
REQUIRE(test("0.00", "%.2f", 1e-4) );
|
||||
REQUIRE(test("-5.20", "%+4.2f", -5.2) );
|
||||
REQUIRE(test("0.0 ", "%-10.1f", 0.) );
|
||||
REQUIRE(test("-8.8888888800", "%.10f", -8.88888888) );
|
||||
REQUIRE(test("880.0888888800", "%.10f", 880.08888888) );
|
||||
REQUIRE(test("100056789.0", "%.1f", 100056789.0) );
|
||||
REQUIRE(test(" 0", "% .0f", 0.1) );
|
||||
}
|
||||
|
||||
TEST_CASE("Format %d, %i, %o, %u, %x", "[string][printf]")
|
||||
@@ -259,22 +270,15 @@ TEST_CASE("Format %d, %i, %o, %u, %x", "[string][printf]")
|
||||
REQUIRE(test("000000000000edcb5433", "%020x", -0x1234abcd) );
|
||||
REQUIRE(test("000000000000EDCB5433", "%020X", -0x1234abcd) );
|
||||
|
||||
REQUIRE(testNotStdCompliant("0xf", "0x%01x", -1) );
|
||||
REQUIRE(testNotStdCompliant("0xff", "0x%02x", -1) );
|
||||
REQUIRE(testNotStdCompliant("0xfff", "0x%03x", -1) );
|
||||
REQUIRE(testNotStdCompliant("0xffff", "0x%04x", -1) );
|
||||
REQUIRE(testNotStdCompliant("0xfffff", "0x%05x", -1) );
|
||||
REQUIRE(testNotStdCompliant("0xffffff", "0x%06x", -1) );
|
||||
REQUIRE(testNotStdCompliant("0xfffffff", "0x%07x", -1) );
|
||||
REQUIRE(testNotStdCompliant("0xffffffff", "0x%08x", -1) );
|
||||
REQUIRE(test("0xffffffff", "0x%01x", -1) );
|
||||
REQUIRE(test("0xffffffff", "0x%08x", -1) );
|
||||
|
||||
REQUIRE(test(" -1", "% 4i", -1) );
|
||||
REQUIRE(test(" -1", "% 4i", -1) );
|
||||
REQUIRE(test(" 0", "% 4i", 0) );
|
||||
REQUIRE(test(" 1", "% 4i", 1) );
|
||||
REQUIRE(test(" 1", "% 4o", 1) );
|
||||
REQUIRE(test(" +1", "%+4i", 1) );
|
||||
REQUIRE(testNotStdCompliant(" +1", "%+4o", 1) );
|
||||
REQUIRE(test(" +1", "%+4o", 1) );
|
||||
REQUIRE(test(" +0", "%+4i", 0) );
|
||||
REQUIRE(test(" -1", "%+4i", -1) );
|
||||
REQUIRE(test("0001", "%04i", 1) );
|
||||
@@ -295,6 +299,13 @@ TEST_CASE("Format %d, %i, %o, %u, %x", "[string][printf]")
|
||||
|
||||
REQUIRE(test("18446744073709551615", "%" PRIu64, UINT64_MAX) );
|
||||
REQUIRE(test("ffffffffffffffff", "%016" PRIx64, UINT64_MAX) );
|
||||
|
||||
REQUIRE(test("33 555", "%hi %ld", (short)33, 555l) );
|
||||
REQUIRE(test("20 0020", "%u %04u", 20u, 20u) );
|
||||
|
||||
REQUIRE(test("012 0x1e 0X3C", "%#o %#x %#X", 10u, 30u, 60u) );
|
||||
REQUIRE(test(" 12 1e 3C ", "%3o %2x %-3X", 10u, 30u, 60u) );
|
||||
REQUIRE(test("12 1e 3C", "%o %x %X", 10u, 30u, 60u) );
|
||||
}
|
||||
|
||||
TEST_CASE("Format modifiers", "[string][printf]")
|
||||
@@ -363,23 +374,15 @@ TEST_CASE("Format %g", "[string][printf]")
|
||||
REQUIRE(test(" 0.0123", "%7.4G", .0123) );
|
||||
// REQUIRE(test("1.23e+05", "%.3g", 123000.25) );
|
||||
// REQUIRE(test("1e+05", "%.0g", 123000.25) );
|
||||
REQUIRE(test("1", "%.0g", 1.2) );
|
||||
}
|
||||
|
||||
TEST_CASE("Format %c, %s, %S", "[string][printf]")
|
||||
{
|
||||
REQUIRE(test("x", "%c", 'x') );
|
||||
REQUIRE(test("x ", "%-20c", 'x') );
|
||||
|
||||
REQUIRE(test("hello ", "%-20s", "hello") );
|
||||
REQUIRE(test(" hello", "%10s", "hello") );
|
||||
REQUIRE(test("hello, world!", "%s, %s!", "hello", "world") );
|
||||
|
||||
REQUIRE(testNotStdCompliant("h", "%1s", "hello") );
|
||||
REQUIRE(testNotStdCompliant("he", "%2s", "hello") );
|
||||
REQUIRE(testNotStdCompliant("hel", "%3s", "hello") );
|
||||
REQUIRE(testNotStdCompliant("hell", "%4s", "hello") );
|
||||
REQUIRE(testNotStdCompliant("hello", "%5s", "hello") );
|
||||
|
||||
bx::StringView str("0hello1world2");
|
||||
bx::StringView hello(str, 1, 5);
|
||||
bx::StringView world(str, 7, 5);
|
||||
@@ -420,3 +423,288 @@ TEST_CASE("Invalid", "[string][printf]")
|
||||
REQUIRE(0 == bx::snprintf(temp, sizeof(temp), "%-03.0", 1) );
|
||||
REQUIRE(0 == bx::snprintf(temp, sizeof(temp), "%-03.0t", 1) );
|
||||
}
|
||||
|
||||
TEST_CASE("Format %s width does not truncate", "[string][printf]")
|
||||
{
|
||||
SECTION("Width smaller than string length must NOT truncate")
|
||||
{
|
||||
REQUIRE(test("hello", "%1s", "hello") );
|
||||
REQUIRE(test("hello", "%5s", "hello") );
|
||||
REQUIRE(test(" hello", "%6s", "hello") );
|
||||
REQUIRE(test(" hello", "%7s", "hello") );
|
||||
}
|
||||
|
||||
SECTION("Left-aligned, width smaller than string length")
|
||||
{
|
||||
REQUIRE(test("hello", "%-1s", "hello") );
|
||||
REQUIRE(test("hello ", "%-6s", "hello") );
|
||||
REQUIRE(test("hello ", "%-7s", "hello") );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Format %s precision truncates", "[string][printf]")
|
||||
{
|
||||
SECTION("Precision DOES truncate strings")
|
||||
{
|
||||
REQUIRE(test("", "%.0s", "hello") );
|
||||
REQUIRE(test("h", "%.1s", "hello") );
|
||||
REQUIRE(test("he", "%.2s", "hello") );
|
||||
REQUIRE(test("hel", "%.3s", "hello") );
|
||||
REQUIRE(test("hell", "%.4s", "hello") );
|
||||
REQUIRE(test("hello", "%.5s", "hello") );
|
||||
REQUIRE(test("hello", "%.10s", "hello") );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Format %s width and precision combined", "[string][printf]")
|
||||
{
|
||||
SECTION("Width pads, precision truncates")
|
||||
{
|
||||
REQUIRE(test(" h", "%10.1s", "hello") );
|
||||
REQUIRE(test(" he", "%10.2s", "hello") );
|
||||
REQUIRE(test(" hel", "%10.3s", "hello") );
|
||||
REQUIRE(test(" hello", "%10.5s", "hello") );
|
||||
}
|
||||
|
||||
SECTION("Left-aligned with width and precision")
|
||||
{
|
||||
REQUIRE(test("h ", "%-10.1s", "hello") );
|
||||
REQUIRE(test("he ", "%-10.2s", "hello") );
|
||||
REQUIRE(test("hel ", "%-10.3s", "hello") );
|
||||
REQUIRE(test("hello ", "%-10.5s", "hello") );
|
||||
}
|
||||
|
||||
SECTION("Width smaller than precision and string")
|
||||
{
|
||||
REQUIRE(test("hel", "%1.3s", "hello") );
|
||||
REQUIRE(test("hel", "%-1.3s", "hello") );
|
||||
}
|
||||
|
||||
SECTION("Precision with * wildcard")
|
||||
{
|
||||
REQUIRE(test("hel", "%.*s", 3, "hello") );
|
||||
REQUIRE(test("hello", "%.*s", 10, "hello") );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Format %s empty string", "[string][printf]")
|
||||
{
|
||||
REQUIRE(test("", "%s", "") );
|
||||
REQUIRE(test(" ", "%10s", "") );
|
||||
REQUIRE(test(" ", "%-10s", "") );
|
||||
REQUIRE(test("", "%.0s", "hello") );
|
||||
REQUIRE(test(" ", "%10.0s", "hello") );
|
||||
}
|
||||
|
||||
TEST_CASE("Format %d width does not truncate", "[string][printf]")
|
||||
{
|
||||
SECTION("Width smaller than number of digits must NOT truncate")
|
||||
{
|
||||
REQUIRE(test("1337", "%1d", 1337) );
|
||||
REQUIRE(test("1337", "%4d", 1337) );
|
||||
REQUIRE(test(" 1337", "%5d", 1337) );
|
||||
REQUIRE(test(" 1337", "%6d", 1337) );
|
||||
|
||||
REQUIRE(test("-1337", "%1d", -1337) );
|
||||
REQUIRE(test("-1337", "%5d", -1337) );
|
||||
REQUIRE(test(" -1337", "%6d", -1337) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Format %x width does not truncate", "[string][printf]")
|
||||
{
|
||||
REQUIRE(test("abcd", "%1x", 0xabcd) );
|
||||
REQUIRE(test("abcd", "%4x", 0xabcd) );
|
||||
REQUIRE(test(" abcd", "%5x", 0xabcd) );
|
||||
REQUIRE(test("ABCD", "%1X", 0xabcd) );
|
||||
}
|
||||
|
||||
TEST_CASE("Format %% percent literal", "[string][printf]")
|
||||
{
|
||||
REQUIRE(test("%", "%%") );
|
||||
REQUIRE(test("100%", "100%%") );
|
||||
REQUIRE(test("%%", "%%%%") );
|
||||
REQUIRE(test("a%b", "a%%b") );
|
||||
REQUIRE(test("%42%", "%%%d%%", 42) );
|
||||
}
|
||||
|
||||
TEST_CASE("Format %d edge values", "[string][printf]")
|
||||
{
|
||||
REQUIRE(test("0", "%d", 0) );
|
||||
REQUIRE(test("2147483647", "%d", INT32_MAX) );
|
||||
REQUIRE(test("-2147483648", "%d", INT32_MIN) );
|
||||
REQUIRE(test("+2147483647", "%+d", INT32_MAX) );
|
||||
|
||||
REQUIRE(test("0", "%u", 0u) );
|
||||
REQUIRE(test("4294967295", "%u", UINT32_MAX) );
|
||||
|
||||
REQUIRE(test("0", "%x", 0) );
|
||||
REQUIRE(test("ffffffff", "%x", UINT32_MAX) );
|
||||
REQUIRE(test("FFFFFFFF", "%X", UINT32_MAX) );
|
||||
|
||||
REQUIRE(test("-100006789", "%d", -100006789) );
|
||||
}
|
||||
|
||||
TEST_CASE("Format mixed specifiers", "[string][printf]")
|
||||
{
|
||||
REQUIRE(test("hello 42 3.14 world", "%s %d %.2f %s", "hello", 42, 3.14, "world") );
|
||||
REQUIRE(test("a1b2c3", "a%db%dc%d", 1, 2, 3) );
|
||||
REQUIRE(test("0xff = 255", "0x%x = %u", 255, 255u) );
|
||||
}
|
||||
|
||||
TEST_CASE("Format %c edge cases", "[string][printf]")
|
||||
{
|
||||
REQUIRE(test("A", "%c", 'A') );
|
||||
REQUIRE(test(" A", "%2c", 'A') );
|
||||
REQUIRE(test(" A", "%10c", 'A') );
|
||||
REQUIRE(test("A ", "%-10c", 'A') );
|
||||
}
|
||||
|
||||
TEST_CASE("misc", "[string][printf]")
|
||||
{
|
||||
REQUIRE(test("53000atest-20 bit", "%u%u%ctest%d %s", 5, 3000, 'a', -20, "bit") );
|
||||
REQUIRE(test("0.33", "%.*f", 2, 0.33333333) );
|
||||
REQUIRE(test("1", "%.*d", -1, 1) );
|
||||
REQUIRE(test(" ", "% .0d", 0) );
|
||||
REQUIRE(test(" 00004", "%10.5d", 4) );
|
||||
REQUIRE(test("hi x", "%*sx", -3, "hi") );
|
||||
REQUIRE(test("0.33", "%.*g", 2, 0.33333333) );
|
||||
// REQUIRE(test("3.33e-01", "%.*e", 2, 0.33333333) );
|
||||
REQUIRE(test("", "") );
|
||||
}
|
||||
|
||||
TEST_CASE("Integer precision", "[string][printf]")
|
||||
{
|
||||
SECTION("Precision zero suppresses zero-value output")
|
||||
{
|
||||
REQUIRE(test("", "%.0d", 0) );
|
||||
REQUIRE(test("", "%.0i", 0) );
|
||||
REQUIRE(test("", "%.0u", 0u) );
|
||||
REQUIRE(test("", "%.0x", 0) );
|
||||
REQUIRE(test("", "%.0o", 0) );
|
||||
REQUIRE(test("", "%.d", 0) );
|
||||
REQUIRE(test("", "%.i", 0) );
|
||||
REQUIRE(test("", "%.u", 0u) );
|
||||
REQUIRE(test("", "%.x", 0) );
|
||||
REQUIRE(test("", "%.o", 0) );
|
||||
}
|
||||
|
||||
SECTION("Precision pads with leading zeros")
|
||||
{
|
||||
REQUIRE(test("00042", "%.5d", 42) );
|
||||
REQUIRE(test("-00042", "%.5d", -42) );
|
||||
REQUIRE(test("00042", "%.5i", 42) );
|
||||
REQUIRE(test("-00042", "%.5i", -42) );
|
||||
REQUIRE(test("00042", "%.5u", 42u) );
|
||||
REQUIRE(test("000ff", "%.5x", 255) );
|
||||
REQUIRE(test("000FF", "%.5X", 255) );
|
||||
REQUIRE(test("00777", "%.5o", 511) );
|
||||
}
|
||||
|
||||
SECTION("Precision with sign flags")
|
||||
{
|
||||
REQUIRE(test("+", "%+.0d", 0) );
|
||||
REQUIRE(test("+", "%+.0i", 0) );
|
||||
REQUIRE(test("+01", "%+.2i", 1) );
|
||||
}
|
||||
|
||||
SECTION("Width + precision combined")
|
||||
{
|
||||
REQUIRE(test(" 01024", "%20.5d", 1024) );
|
||||
REQUIRE(test(" -01024", "%20.5d", -1024) );
|
||||
REQUIRE(test(" 01024", "%20.5u", 1024u) );
|
||||
REQUIRE(test(" ", "%20.d", 0) );
|
||||
REQUIRE(test(" ", "%20.u", 0u) );
|
||||
REQUIRE(test(" ", "%20.x", 0) );
|
||||
REQUIRE(test("00123 ", "%-20.5i", 123) );
|
||||
}
|
||||
|
||||
SECTION("Precision overrides 0 flag")
|
||||
{
|
||||
REQUIRE(test(" 042", "%05.3d", 42) );
|
||||
REQUIRE(test(" -042", "%05.3d", -42) );
|
||||
REQUIRE(test(" 042", "%05.3i", 42) );
|
||||
REQUIRE(test(" -042", "%05.3i", -42) );
|
||||
REQUIRE(test(" 00042", "%07.5u", 42u) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Space and plus flag", "[string][printf]")
|
||||
{
|
||||
SECTION("Space flag without width")
|
||||
{
|
||||
REQUIRE(test(" 42", "% d", 42) );
|
||||
REQUIRE(test("-42", "% d", -42) );
|
||||
REQUIRE(test(" 0", "% d", 0) );
|
||||
REQUIRE(test(" 0", "% i", 0) );
|
||||
}
|
||||
|
||||
SECTION("Plus flag without width")
|
||||
{
|
||||
REQUIRE(test("+42", "%+d", 42) );
|
||||
REQUIRE(test("-42", "%+d", -42) );
|
||||
REQUIRE(test("+0", "%+i", 0) );
|
||||
}
|
||||
|
||||
SECTION("Plus overrides space")
|
||||
{
|
||||
REQUIRE(test("+42", "%+ d", 42) );
|
||||
REQUIRE(test("+42", "% +d", 42) );
|
||||
REQUIRE(test("-42", "%+ d", -42) );
|
||||
REQUIRE(test("+0", "%+ d", 0) );
|
||||
}
|
||||
|
||||
SECTION("Space flag on float")
|
||||
{
|
||||
REQUIRE(test(" 1.500000", "% f", 1.5) );
|
||||
REQUIRE(test("-1.500000", "% f", -1.5) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Zero-padding negative numbers", "[string][printf]")
|
||||
{
|
||||
REQUIRE(test("-5", "%01d", -5) );
|
||||
REQUIRE(test("-5", "%02d", -5) );
|
||||
REQUIRE(test("-05", "%03d", -5) );
|
||||
REQUIRE(test("-005", "%04d", -5) );
|
||||
}
|
||||
|
||||
TEST_CASE("Star args", "[string][printf]")
|
||||
{
|
||||
SECTION("Star width")
|
||||
{
|
||||
REQUIRE(test(" Z", "%*c", 10, 'Z') );
|
||||
REQUIRE(test(" Hello", "%*s", 20, "Hello") );
|
||||
}
|
||||
|
||||
SECTION("Negative star width = left-justify")
|
||||
{
|
||||
REQUIRE(test("42 ", "%*d", -10, 42) );
|
||||
REQUIRE(test("-42 ", "%*d", -10, -42) );
|
||||
REQUIRE(test("x ", "%*c", -10, 'x') );
|
||||
REQUIRE(test("hello ", "%*s", -10, "hello") );
|
||||
}
|
||||
|
||||
SECTION("Star precision")
|
||||
{
|
||||
REQUIRE(test("01", "%.*i", 2, 1) );
|
||||
REQUIRE(test("h", "%.*s", 1, "hello world") );
|
||||
}
|
||||
|
||||
SECTION("Negative star precision = precision omitted")
|
||||
{
|
||||
REQUIRE(test("42", "%.*d", -1, 42) );
|
||||
REQUIRE(test("0", "%.*d", -1, 0) );
|
||||
REQUIRE(test("hello", "%.*s", -1, "hello") );
|
||||
}
|
||||
|
||||
SECTION("Star width + star precision")
|
||||
{
|
||||
REQUIRE(test(" 07", "%*.*i", 10, 2, 7) );
|
||||
}
|
||||
|
||||
SECTION("Star width/precision with %%")
|
||||
{
|
||||
REQUIRE(test(" 1.23 %", "%*.*f %%", 5, 2, 1.23) );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user