vsnprintf: Implemented length sub-specifier.

This commit is contained in:
Branimir Karadžić
2017-02-11 21:08:56 -08:00
parent 954ee9914f
commit 3930149a77
4 changed files with 173 additions and 6 deletions

View File

@@ -223,9 +223,15 @@ namespace bx
///
int32_t toString(char* _out, size_t _max, int32_t _value, uint32_t _base = 10);
///
int32_t toString(char* _out, size_t _max, int64_t _value, uint32_t _base = 10);
///
int32_t toString(char* _out, size_t _max, uint32_t _value, uint32_t _base = 10);
///
int32_t toString(char* _out, size_t _max, uint64_t _value, uint32_t _base = 10);
///
uint32_t hashMurmur2A(const StringView& _data);

View File

@@ -153,6 +153,7 @@ namespace bx
, base(10)
, prec(6)
, fill(' ')
, bits(0)
, left(false)
, upper(false)
, spec(false)
@@ -164,6 +165,7 @@ namespace bx
uint32_t base;
uint32_t prec;
char fill;
uint8_t bits;
bool left;
bool upper;
bool spec;
@@ -235,7 +237,7 @@ namespace bx
return write(_writer, str, len, _param, _err);
}
static int32_t write(WriterI* _writer, uint32_t _i, const Param& _param, Error* _err)
static int32_t write(WriterI* _writer, int64_t _i, const Param& _param, Error* _err)
{
char str[33];
int32_t len = toString(str, sizeof(str), _i, _param.base);
@@ -248,6 +250,32 @@ namespace bx
return write(_writer, str, len, _param, _err);
}
static int32_t write(WriterI* _writer, uint32_t _u, const Param& _param, Error* _err)
{
char str[33];
int32_t len = toString(str, sizeof(str), _u, _param.base);
if (len == 0)
{
return 0;
}
return write(_writer, str, len, _param, _err);
}
static int32_t write(WriterI* _writer, uint64_t _u, const Param& _param, Error* _err)
{
char str[33];
int32_t len = toString(str, sizeof(str), _u, _param.base);
if (len == 0)
{
return 0;
}
return write(_writer, str, len, _param, _err);
}
static int32_t write(WriterI* _writer, double _d, const Param& _param, Error* _err)
{
char str[1024];
@@ -323,9 +351,10 @@ namespace bx
{
switch (ch)
{
default:
case ' ': param.fill = ' '; break;
case '-': param.left = true; break;
case '+': param.sign = true; break;
case ' ': param.fill = ' '; break;
case '0': param.fill = '0'; break;
case '#': param.spec = true; break;
}
@@ -379,6 +408,48 @@ namespace bx
}
}
// length sub-specifier
while ('h' == ch
|| 'I' == ch
|| 'l' == ch
|| 'j' == ch
|| 't' == ch
|| 'z' == ch)
{
switch (ch)
{
default: break;
case 'j': param.bits = sizeof(intmax_t )*8; break;
case 't': param.bits = sizeof(size_t )*8; break;
case 'z': param.bits = sizeof(ptrdiff_t)*8; break;
case 'h': case 'I': case 'l':
switch (ch)
{
case 'h': param.bits = sizeof(short int)*8; break;
case 'l': param.bits = sizeof(long int )*8; break;
default: break;
}
read(&reader, ch);
switch (ch)
{
case 'h': param.bits = sizeof(signed char )*8; break;
case 'l': param.bits = sizeof(long long int)*8; break;
case '6':
read(&reader, ch);
if ('4' == ch) { param.bits = sizeof(int64_t)*8; }
break;
default: seek(&reader, -1); break;
}
break;
}
read(&reader, ch);
}
switch (toLower(ch) )
{
case 'c':
@@ -391,13 +462,21 @@ namespace bx
case 'o':
param.base = 8;
size += write(_writer, va_arg(_argList, int32_t), param, _err);
switch (param.bits)
{
default: size += write(_writer, va_arg(_argList, int32_t), param, _err); break;
case 64: size += write(_writer, va_arg(_argList, int64_t), param, _err); break;
}
break;
case 'i':
case 'd':
param.base = 10;
size += write(_writer, va_arg(_argList, int32_t), param, _err);
switch (param.bits)
{
default: size += write(_writer, va_arg(_argList, int32_t), param, _err); break;
case 64: size += write(_writer, va_arg(_argList, int64_t), param, _err); break;
};
break;
case 'f':
@@ -411,12 +490,20 @@ namespace bx
case 'x':
param.base = 16;
param.upper = isUpper(ch);
size += write(_writer, va_arg(_argList, uint32_t), param, _err);
switch (param.bits)
{
default: size += write(_writer, va_arg(_argList, uint32_t), param, _err); break;
case 64: size += write(_writer, va_arg(_argList, uint64_t), param, _err); break;
}
break;
case 'u':
param.base = 10;
size += write(_writer, va_arg(_argList, uint32_t), param, _err);
switch (param.bits)
{
default: size += write(_writer, va_arg(_argList, uint32_t), param, _err); break;
case 64: size += write(_writer, va_arg(_argList, uint64_t), param, _err); break;
}
break;
default:

View File

@@ -487,6 +487,29 @@ namespace bx
return toString(_dst, _max, uint32_t(_value), _base);
}
int32_t toString(char* _dst, size_t _max, int64_t _value, uint32_t _base)
{
if (_base == 10
&& _value < 0)
{
if (_max < 1)
{
return 0;
}
_max = toString(_dst + 1, _max - 1, uint64_t(-_value), _base);
if (_max == 0)
{
return 0;
}
*_dst = '-';
return int32_t(_max + 1);
}
return toString(_dst, _max, uint64_t(_value), _base);
}
int32_t toString(char* _dst, size_t _max, uint32_t _value, uint32_t _base)
{
char data[32];
@@ -525,4 +548,42 @@ namespace bx
return int32_t(len);
}
int32_t toString(char* _dst, size_t _max, uint64_t _value, uint32_t _base)
{
char data[32];
size_t len = 0;
if (_base > 16
|| _base < 2)
{
return 0;
}
do
{
const uint64_t rem = _value % _base;
_value /= _base;
if (rem < 10)
{
data[len++] = char('0' + rem);
}
else
{
data[len++] = char('a' + rem - 10);
}
} while (_value != 0);
if (_max < len + 1)
{
return 0;
}
reverse(data, len);
memCopy(_dst, data, len);
_dst[len] = '\0';
return int32_t(len);
}
} // namespace bx

View File

@@ -5,6 +5,7 @@
#include "test.h"
#include <bx/string.h>
#include <inttypes.h>
TEST_CASE("vsnprintf NULL buffer", "No output buffer provided.")
{
@@ -81,6 +82,18 @@ TEST_CASE("vsnprintf d/i/o/u/x", "")
REQUIRE(test("0000000000001234ABCD", "%020X", 0x1234abcd) );
REQUIRE(test("000000000000edcb5433", "%020x", -0x1234abcd) );
REQUIRE(test("000000000000EDCB5433", "%020X", -0x1234abcd) );
if (BX_ENABLED(BX_ARCH_32BIT) )
{
REQUIRE(test("2147483647", "%jd", INTMAX_MAX) );
}
else
{
REQUIRE(test("9223372036854775807", "%jd", INTMAX_MAX) );
}
REQUIRE(test("18446744073709551615", "%" PRIu64, UINT64_MAX) );
REQUIRE(test("ffffffffffffffff", "%016" PRIx64, UINT64_MAX) );
}
TEST_CASE("vsnprintf modifiers", "")