mirror of
https://github.com/bkaradzic/bx.git
synced 2026-02-17 20:52:37 +01:00
vsnprintf now can take StringView as argument.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() );
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user