vsnprintf now can take StringView as argument.

This commit is contained in:
Бранимир Караџић
2021-10-03 16:11:27 -07:00
parent 70f998ba19
commit f5c797a03a
5 changed files with 133 additions and 27 deletions

View File

@@ -124,6 +124,7 @@ namespace bx
{
m_len = INT32_MAX == _len ? strLen(_ptr) : _len;
m_ptr = _ptr;
m_0terminated = INT32_MAX == _len;
}
}
@@ -149,6 +150,7 @@ namespace bx
{
m_ptr = "";
m_len = 0;
m_0terminated = true;
}
inline const char* StringView::getPtr() const
@@ -171,28 +173,31 @@ namespace bx
return m_len;
}
inline bool StringView::is0Terminated() const
{
return m_0terminated;
}
template<bx::AllocatorI** AllocatorT>
inline StringT<AllocatorT>::StringT()
: StringView()
, m_capacity(0)
{
clear();
}
template<bx::AllocatorI** AllocatorT>
inline StringT<AllocatorT>::StringT(const StringT<AllocatorT>& _rhs)
: StringView()
, m_capacity(0)
{
set(_rhs);
}
template<bx::AllocatorI** AllocatorT>
inline StringT<AllocatorT>& StringT<AllocatorT>::operator=(const StringT<AllocatorT>& _rhs)
{
set(_rhs);
return *this;
}
template<bx::AllocatorI** AllocatorT>
inline StringT<AllocatorT>::StringT(const StringView& _rhs)
: StringView()
, m_capacity(0)
{
set(_rhs);
}
@@ -203,6 +208,13 @@ namespace bx
clear();
}
template<bx::AllocatorI** AllocatorT>
inline StringT<AllocatorT>& StringT<AllocatorT>::operator=(const StringT<AllocatorT>& _rhs)
{
set(_rhs);
return *this;
}
template<bx::AllocatorI** AllocatorT>
inline void StringT<AllocatorT>::set(const StringView& _str)
{
@@ -215,13 +227,22 @@ namespace bx
{
if (0 != _str.getLength() )
{
int32_t old = m_len;
int32_t len = m_len + strLen(_str);
char* ptr = (char*)BX_REALLOC(*AllocatorT, 0 != m_len ? const_cast<char*>(m_ptr) : NULL, len+1);
const int32_t old = m_len;
const int32_t len = m_len + _str.getLength();
char* ptr = const_cast<char*>(m_ptr);
if (len+1 > m_capacity)
{
const int32_t capacity = alignUp(len+1, 256);
ptr = (char*)BX_REALLOC(*AllocatorT, 0 != m_capacity ? ptr : NULL, capacity);
*const_cast<char**>(&m_ptr) = ptr;
m_capacity = capacity;
}
m_len = len;
strCopy(ptr + old, len-old+1, _str);
*const_cast<char**>(&m_ptr) = ptr;
}
}
@@ -234,11 +255,14 @@ namespace bx
template<bx::AllocatorI** AllocatorT>
inline void StringT<AllocatorT>::clear()
{
if (0 != m_len)
m_0terminated = true;
if (0 != m_capacity)
{
BX_FREE(*AllocatorT, const_cast<char*>(m_ptr) );
StringView::clear();
m_capacity = 0;
}
}

View File

@@ -91,15 +91,19 @@ namespace bx
///
const char* getTerm() const;
///
/// Returns `true` if string is empty.
bool isEmpty() const;
///
/// Returns string length.
int32_t getLength() const;
/// Returns `true` if string is zero terminated.
bool is0Terminated() const;
protected:
const char* m_ptr;
int32_t m_len;
bool m_0terminated;
};
/// ASCII string
@@ -113,15 +117,15 @@ namespace bx
///
StringT(const StringT<AllocatorT>& _rhs);
///
StringT<AllocatorT>& operator=(const StringT<AllocatorT>& _rhs);
///
StringT(const StringView& _rhs);
///
~StringT();
///
StringT<AllocatorT>& operator=(const StringT<AllocatorT>& _rhs);
///
void set(const StringView& _str);
@@ -137,6 +141,9 @@ namespace bx
/// Returns zero-terminated C string pointer.
///
const char* getCPtr() const;
protected:
int32_t m_capacity;
};
/// Retruns true if character is part of space set.

View File

@@ -813,6 +813,11 @@ namespace bx
return write(_writer, _str, _param.prec, _param, _err);
}
static int32_t write(WriterI* _writer, const StringView& _str, const Param& _param, Error* _err)
{
return write(_writer, _str.getPtr(), min(_param.prec, _str.getLength() ), _param, _err);
}
static int32_t write(WriterI* _writer, int32_t _i, const Param& _param, Error* _err)
{
char str[33];
@@ -939,12 +944,15 @@ namespace bx
}
else if ('%' == ch)
{
// %[flags][width][.precision][length sub-specifier]specifier
// %[Flags][Width][.Precision][Leegth]Type
read(&reader, ch, &err);
Param param;
// flags
// Reference(s):
// - Flags field
// https://en.wikipedia.org/wiki/Printf_format_string#Flags_field
//
while (err.isOk()
&& ( ' ' == ch
|| '-' == ch
@@ -971,7 +979,10 @@ namespace bx
param.fill = ' ';
}
// width
// Reference(s):
// - Width field
// https://en.wikipedia.org/wiki/Printf_format_string#Width_field
//
if ('*' == ch)
{
read(&reader, ch, &err);
@@ -994,7 +1005,9 @@ namespace bx
}
}
// .precision
// Reference(s):
// - Precision field
// https://en.wikipedia.org/wiki/Printf_format_string#Precision_field
if ('.' == ch)
{
read(&reader, ch, &err);
@@ -1016,7 +1029,9 @@ namespace bx
}
}
// length sub-specifier
// Reference(s):
// - Length field
// https://en.wikipedia.org/wiki/Printf_format_string#Length_field
while (err.isOk()
&& ( 'h' == ch
|| 'I' == ch
@@ -1031,8 +1046,8 @@ namespace bx
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 't': param.bits = sizeof(ptrdiff_t)*8; break;
case 'z': param.bits = sizeof(size_t )*8; break;
case 'h': case 'I': case 'l':
switch (ch)
@@ -1071,7 +1086,9 @@ namespace bx
break;
}
// specifier
// Reference(s):
// - Type field
// https://en.wikipedia.org/wiki/Printf_format_string#Type_field
switch (toLower(ch) )
{
case 'c':
@@ -1079,7 +1096,14 @@ namespace bx
break;
case 's':
size += write(_writer, va_arg(_argList, const char*), param, _err);
if (isUpper(ch) )
{
size += write(_writer, va_arg(_argList, const StringView), param, _err);
}
else
{
size += write(_writer, va_arg(_argList, const char*), param, _err);
}
break;
case 'o':
@@ -1131,6 +1155,10 @@ namespace bx
}
break;
case 'n':
*va_arg(_argList, int32_t*) = size;
break;
default:
size += write(_writer, ch, _err);
break;

View File

@@ -555,3 +555,29 @@ TEST_CASE("suffix", "")
REQUIRE(0 == bx::strCmp(bx::strTrimSuffix("abvgd-1389.0", "389.0"), "abvgd-1") );
REQUIRE(0 == bx::strCmp(bx::strTrimSuffix("abvgd-1389.0", "xyz"), "abvgd-1389.0") );
}
TEST_CASE("0terminated", "")
{
const bx::StringView t0("1389");
REQUIRE(t0.is0Terminated() );
const bx::StringView t1(strTrimPrefix(t0, "13") );
REQUIRE(!t1.is0Terminated() );
const bx::StringView t2(strTrimSuffix(t0, "89") );
REQUIRE(!t2.is0Terminated() );
bx::DefaultAllocator crt;
g_allocator = &crt;
typedef bx::StringT<&g_allocator> String;
String st;
REQUIRE(st.is0Terminated() );
st = strTrimPrefix(t0, "13");
REQUIRE(2 == st.getLength() );
REQUIRE(st.is0Terminated() );
st = strTrimSuffix(t0, "89");
REQUIRE(2 == st.getLength() );
REQUIRE(st.is0Terminated() );
}

View File

@@ -184,6 +184,22 @@ TEST_CASE("vsnprintf t")
size_t size = -1;
REQUIRE(test("-1", "%td", size) );
REQUIRE(test("3221225472", "%td", size_t(3221225472) ) );
}
TEST_CASE("vsnprintf n")
{
char temp[64];
int32_t p0, p1, p2;
bx::snprintf(temp, sizeof(temp), "%n", &p0);
REQUIRE(0 == p0);
bx::snprintf(temp, sizeof(temp), "01%n23%n45%n", &p0, &p1, &p2);
REQUIRE(2 == p0);
REQUIRE(4 == p1);
REQUIRE(6 == p2);
}
TEST_CASE("vsnprintf g")
@@ -215,6 +231,11 @@ TEST_CASE("vsnprintf")
, hello.getLength(), hello.getPtr()
, world.getLength(), world.getPtr()
) );
REQUIRE(test("hello, world!", "%S, %S!"
, hello
, world
) );
}
TEST_CASE("vsnprintf write")