Added FixedStringT.

This commit is contained in:
Branimir Karadžić
2025-09-19 20:36:42 -07:00
parent eda38395dd
commit 2fe4b15234
3 changed files with 197 additions and 17 deletions

View File

@@ -187,17 +187,93 @@ namespace bx
return m_0terminated; return m_0terminated;
} }
template<uint16_t MaxCapacityT>
inline FixedStringT<MaxCapacityT>::FixedStringT()
: m_len(0)
{
}
template<uint16_t MaxCapacityT>
inline FixedStringT<MaxCapacityT>::FixedStringT(const char* _str)
: FixedStringT<MaxCapacityT>()
{
set(_str);
}
template<uint16_t MaxCapacityT>
inline FixedStringT<MaxCapacityT>::FixedStringT(const StringView& _str)
: FixedStringT<MaxCapacityT>()
{
set(_str);
}
template<uint16_t MaxCapacityT>
inline FixedStringT<MaxCapacityT>::~FixedStringT()
{
}
template<uint16_t MaxCapacityT>
inline void FixedStringT<MaxCapacityT>::set(const char* _str)
{
set(StringView(_str) );
}
template<uint16_t MaxCapacityT>
inline void FixedStringT<MaxCapacityT>::set(const StringView& _str)
{
int32_t copied = strCopy(m_storage, MaxCapacityT, _str);
m_len = copied;
}
template<uint16_t MaxCapacityT>
inline void FixedStringT<MaxCapacityT>::append(const StringView& _str)
{
m_len += strCopy(&m_storage[m_len], MaxCapacityT-m_len, _str);
}
template<uint16_t MaxCapacityT>
inline void FixedStringT<MaxCapacityT>::clear()
{
m_len = 0;
m_storage[0] = '\0';
}
template<uint16_t MaxCapacityT>
inline bool FixedStringT<MaxCapacityT>::isEmpty() const
{
return 0 == m_len;
}
template<uint16_t MaxCapacityT>
inline int32_t FixedStringT<MaxCapacityT>::getLength() const
{
return m_len;
}
template<uint16_t MaxCapacityT>
inline const char* FixedStringT<MaxCapacityT>::getCPtr() const
{
return m_storage;
}
template<uint16_t MaxCapacityT>
inline FixedStringT<MaxCapacityT>::operator StringView() const
{
return StringView(m_storage, m_len);
}
template<AllocatorI** AllocatorT> template<AllocatorI** AllocatorT>
inline StringT<AllocatorT>::StringT() inline StringT<AllocatorT>::StringT()
: StringView() : m_ptr("")
, m_len(0)
, m_capacity(0) , m_capacity(0)
{ {
clear();
} }
template<AllocatorI** AllocatorT> template<AllocatorI** AllocatorT>
inline StringT<AllocatorT>::StringT(const StringT<AllocatorT>& _rhs) inline StringT<AllocatorT>::StringT(const StringT<AllocatorT>& _rhs)
: StringView() : m_ptr("")
, m_len(0)
, m_capacity(0) , m_capacity(0)
{ {
set(_rhs); set(_rhs);
@@ -205,7 +281,8 @@ namespace bx
template<AllocatorI** AllocatorT> template<AllocatorI** AllocatorT>
inline StringT<AllocatorT>::StringT(const StringView& _rhs) inline StringT<AllocatorT>::StringT(const StringView& _rhs)
: StringView() : m_ptr("")
, m_len(0)
, m_capacity(0) , m_capacity(0)
{ {
set(_rhs); set(_rhs);
@@ -264,21 +341,38 @@ namespace bx
template<AllocatorI** AllocatorT> template<AllocatorI** AllocatorT>
inline void StringT<AllocatorT>::clear() inline void StringT<AllocatorT>::clear()
{ {
m_0terminated = true;
if (0 != m_capacity) if (0 != m_capacity)
{ {
free(*AllocatorT, const_cast<char*>(m_ptr) ); free(*AllocatorT, const_cast<char*>(m_ptr) );
StringView::clear(); m_ptr = "";
m_len = 0;
m_capacity = 0; m_capacity = 0;
} }
} }
template<AllocatorI** AllocatorT>
inline bool StringT<AllocatorT>::isEmpty() const
{
return 0 == m_len;
}
template<AllocatorI** AllocatorT>
inline int32_t StringT<AllocatorT>::getLength() const
{
return m_len;
}
template<AllocatorI** AllocatorT> template<AllocatorI** AllocatorT>
inline const char* StringT<AllocatorT>::getCPtr() const inline const char* StringT<AllocatorT>::getCPtr() const
{ {
return getPtr(); return m_ptr;
}
template<AllocatorI** AllocatorT>
inline StringT<AllocatorT>::operator StringView() const
{
return StringView(m_ptr, m_len);
} }
inline StringView strSubstr(const StringView& _str, int32_t _start, int32_t _len) inline StringView strSubstr(const StringView& _str, int32_t _start, int32_t _len)

View File

@@ -137,9 +137,66 @@ namespace bx
bool m_0terminated; bool m_0terminated;
}; };
/// ASCII string /// Fixed capacity string.
///
template<uint16_t MaxCapacityT>
class FixedStringT
{
public:
///
FixedStringT();
///
FixedStringT(const char* _str);
///
FixedStringT(const StringView& _str);
///
~FixedStringT();
///
void set(const char* _str);
///
void set(const StringView& _str);
///
void append(const StringView& _str);
///
void clear();
/// Returns `true` if string is empty.
///
bool isEmpty() const;
/// Returns string length.
///
int32_t getLength() const;
/// Returns zero-terminated C string pointer.
///
const char* getCPtr() const;
/// Implicitly converts FixedStringT to StringView.
///
operator StringView() const;
private:
char m_storage[MaxCapacityT];
int32_t m_len;
};
///
using FixedString64 = FixedStringT<64>;
using FixedString256 = FixedStringT<256>;
using FixedString1024 = FixedStringT<1024>;
/// Dynamic string
///
template<AllocatorI** AllocatorT> template<AllocatorI** AllocatorT>
class StringT : public StringView class StringT
{ {
public: public:
/// ///
@@ -169,11 +226,25 @@ namespace bx
/// ///
void clear(); void clear();
/// Returns `true` if string is empty.
///
bool isEmpty() const;
/// Returns string length.
///
int32_t getLength() const;
/// Returns zero-terminated C string pointer. /// Returns zero-terminated C string pointer.
/// ///
const char* getCPtr() const; const char* getCPtr() const;
/// Implicitly converts StringT to StringView.
///
operator StringView() const;
protected: protected:
const char* m_ptr;
int32_t m_len;
int32_t m_capacity; int32_t m_capacity;
}; };

View File

@@ -498,7 +498,7 @@ TEST_CASE("StringView", "[string]")
st.append(bx::StringView("test", 2) ); st.append(bx::StringView("test", 2) );
REQUIRE(10 == st.getLength() ); REQUIRE(10 == st.getLength() );
REQUIRE(0 == bx::strCmp(st.getPtr(), "testtestte") ); REQUIRE(0 == bx::strCmp(st.getCPtr(), "testtestte") );
st.clear(); st.clear();
REQUIRE(0 == st.getLength() ); REQUIRE(0 == st.getLength() );
@@ -628,18 +628,32 @@ TEST_CASE("0terminated", "[string]")
typedef bx::StringT<&g_allocator> String; typedef bx::StringT<&g_allocator> String;
String st; String st;
REQUIRE(st.is0Terminated() );
st = strTrimPrefix(t0, "13"); st = strTrimPrefix(t0, "13");
REQUIRE(2 == st.getLength() ); REQUIRE(2 == st.getLength() );
REQUIRE(st.is0Terminated() );
st = strTrimSuffix(t0, "89"); st = strTrimSuffix(t0, "89");
REQUIRE(2 == st.getLength() ); REQUIRE(2 == st.getLength() );
REQUIRE(st.is0Terminated() );
} }
TEST(tinystl_string_constructor) { TEST_CASE("FixedStringT", "[string]")
{
bx::FixedString64 fs64("1389");
bx::FixedString256 fs256(fs64);
REQUIRE(0 == strCmp(fs64, fs256) );
REQUIRE(0 == strCmp(fs64, "1389") );
REQUIRE(0 == strCmp(fs256, "1389") );
fs64.append("9831");
REQUIRE(8 == fs64.getLength() );
REQUIRE(0 != strCmp(fs64, fs256) );
REQUIRE(0 != strCmp(fs64, "13899831") );
}
TEST(tinystl_string_constructor)
{
using tinystl::string; using tinystl::string;
{ {
string s; string s;
@@ -672,7 +686,8 @@ TEST(tinystl_string_constructor) {
} }
} }
TEST(tinystl_string_assign) { TEST(tinystl_string_assign)
{
using tinystl::string; using tinystl::string;
{ {
const string other("hello"); const string other("hello");