mirror of
https://github.com/bkaradzic/bx.git
synced 2026-10-22 08:41:00 +00:00
Made strCmp, strCmpI and strCmpV constexpr. (#470)
This commit is contained in:
committed by
GitHub
parent
c500a9228e
commit
97aa6da7db
@@ -577,6 +577,133 @@ namespace bx
|
||||
return int32_t(ptr - _str);
|
||||
}
|
||||
|
||||
typedef char (*CharFn)(char _ch);
|
||||
|
||||
inline BX_CONSTEXPR_FUNC char toNoop(char _ch)
|
||||
{
|
||||
return _ch;
|
||||
}
|
||||
|
||||
template<CharFn fn>
|
||||
inline constexpr int32_t strCmp(const char* _lhs, int32_t _lhsMax, const char* _rhs, int32_t _rhsMax)
|
||||
{
|
||||
int32_t max = min(_lhsMax, _rhsMax);
|
||||
|
||||
for (
|
||||
; 0 < max && fn(*_lhs) == fn(*_rhs)
|
||||
; ++_lhs, ++_rhs, --max
|
||||
)
|
||||
{
|
||||
if (*_lhs == '\0'
|
||||
|| *_rhs == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == max)
|
||||
{
|
||||
return _lhsMax == _rhsMax ? 0 : _lhsMax > _rhsMax ? 1 : -1;
|
||||
}
|
||||
|
||||
return fn(*_lhs) - fn(*_rhs);
|
||||
}
|
||||
|
||||
inline constexpr int32_t strCmp(const StringView& _lhs, const StringView& _rhs, int32_t _max)
|
||||
{
|
||||
return strCmp<toNoop>(
|
||||
_lhs.getPtr()
|
||||
, min(_lhs.getLength(), _max)
|
||||
, _rhs.getPtr()
|
||||
, min(_rhs.getLength(), _max)
|
||||
);
|
||||
}
|
||||
|
||||
inline constexpr int32_t strCmpI(const StringView& _lhs, const StringView& _rhs, int32_t _max)
|
||||
{
|
||||
return strCmp<toLower>(
|
||||
_lhs.getPtr()
|
||||
, min(_lhs.getLength(), _max)
|
||||
, _rhs.getPtr()
|
||||
, min(_rhs.getLength(), _max)
|
||||
);
|
||||
}
|
||||
|
||||
inline constexpr int32_t strCmpV(const char* _lhs, int32_t _lhsMax, const char* _rhs, int32_t _rhsMax)
|
||||
{
|
||||
int32_t max = min(_lhsMax, _rhsMax);
|
||||
int32_t ii = 0;
|
||||
int32_t idx = 0;
|
||||
bool zero = true;
|
||||
|
||||
for (
|
||||
; 0 < max && _lhs[ii] == _rhs[ii]
|
||||
; ++ii, --max
|
||||
)
|
||||
{
|
||||
const uint8_t ch = _lhs[ii];
|
||||
if ('\0' == ch
|
||||
|| '\0' == _rhs[ii])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isNumeric(ch) )
|
||||
{
|
||||
idx = ii+1;
|
||||
zero = true;
|
||||
}
|
||||
else if ('0' != ch)
|
||||
{
|
||||
zero = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == max)
|
||||
{
|
||||
return _lhsMax == _rhsMax ? 0 : _lhs[ii] - _rhs[ii];
|
||||
}
|
||||
|
||||
if ('0' != _lhs[idx]
|
||||
&& '0' != _rhs[idx])
|
||||
{
|
||||
int32_t jj = 0;
|
||||
for (jj = ii
|
||||
; 0 < max && isNumeric(_lhs[jj])
|
||||
; ++jj, --max
|
||||
)
|
||||
{
|
||||
if (!isNumeric(_rhs[jj]) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNumeric(_rhs[jj]))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (zero
|
||||
&& idx < ii
|
||||
&& (isNumeric(_lhs[ii]) || isNumeric(_rhs[ii]) ) )
|
||||
{
|
||||
return (_lhs[ii] - '0') - (_rhs[ii] - '0');
|
||||
}
|
||||
|
||||
return 0 == max && _lhsMax == _rhsMax ? 0 : _lhs[ii] - _rhs[ii];
|
||||
}
|
||||
|
||||
inline constexpr int32_t strCmpV(const StringView& _lhs, const StringView& _rhs, int32_t _max)
|
||||
{
|
||||
return strCmpV(
|
||||
_lhs.getPtr()
|
||||
, min(_lhs.getLength(), _max)
|
||||
, _rhs.getPtr()
|
||||
, min(_rhs.getLength(), _max)
|
||||
);
|
||||
}
|
||||
|
||||
inline bool hasPrefix(const StringView& _str, const StringView& _prefix)
|
||||
{
|
||||
const int32_t len = _prefix.getLength();
|
||||
|
||||
@@ -375,13 +375,13 @@ namespace bx
|
||||
void toUpper(char* _inOutStr, int32_t _max = INT32_MAX);
|
||||
|
||||
/// String compare.
|
||||
int32_t strCmp(const StringView& _lhs, const StringView& _rhs, int32_t _max = INT32_MAX);
|
||||
constexpr int32_t strCmp(const StringView& _lhs, const StringView& _rhs, int32_t _max = INT32_MAX);
|
||||
|
||||
/// Case insensitive string compare.
|
||||
int32_t strCmpI(const StringView& _lhs, const StringView& _rhs, int32_t _max = INT32_MAX);
|
||||
constexpr int32_t strCmpI(const StringView& _lhs, const StringView& _rhs, int32_t _max = INT32_MAX);
|
||||
|
||||
// Compare as strings holding indices/version numbers.
|
||||
int32_t strCmpV(const StringView& _lhs, const StringView& _rhs, int32_t _max = INT32_MAX);
|
||||
constexpr int32_t strCmpV(const StringView& _lhs, const StringView& _rhs, int32_t _max = INT32_MAX);
|
||||
|
||||
/// Get string length.
|
||||
constexpr int32_t strLen(const char* _str, int32_t _max = INT32_MAX);
|
||||
|
||||
127
src/string.cpp
127
src/string.cpp
@@ -94,133 +94,6 @@ namespace bx
|
||||
toUpperUnsafe(_inOutStr, len);
|
||||
}
|
||||
|
||||
typedef char (*CharFn)(char _ch);
|
||||
|
||||
inline BX_CONSTEXPR_FUNC char toNoop(char _ch)
|
||||
{
|
||||
return _ch;
|
||||
}
|
||||
|
||||
template<CharFn fn>
|
||||
inline int32_t strCmp(const char* _lhs, int32_t _lhsMax, const char* _rhs, int32_t _rhsMax)
|
||||
{
|
||||
int32_t max = min(_lhsMax, _rhsMax);
|
||||
|
||||
for (
|
||||
; 0 < max && fn(*_lhs) == fn(*_rhs)
|
||||
; ++_lhs, ++_rhs, --max
|
||||
)
|
||||
{
|
||||
if (*_lhs == '\0'
|
||||
|| *_rhs == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == max)
|
||||
{
|
||||
return _lhsMax == _rhsMax ? 0 : _lhsMax > _rhsMax ? 1 : -1;
|
||||
}
|
||||
|
||||
return fn(*_lhs) - fn(*_rhs);
|
||||
}
|
||||
|
||||
int32_t strCmp(const StringView& _lhs, const StringView& _rhs, int32_t _max)
|
||||
{
|
||||
return strCmp<toNoop>(
|
||||
_lhs.getPtr()
|
||||
, min(_lhs.getLength(), _max)
|
||||
, _rhs.getPtr()
|
||||
, min(_rhs.getLength(), _max)
|
||||
);
|
||||
}
|
||||
|
||||
int32_t strCmpI(const StringView& _lhs, const StringView& _rhs, int32_t _max)
|
||||
{
|
||||
return strCmp<toLower>(
|
||||
_lhs.getPtr()
|
||||
, min(_lhs.getLength(), _max)
|
||||
, _rhs.getPtr()
|
||||
, min(_rhs.getLength(), _max)
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t strCmpV(const char* _lhs, int32_t _lhsMax, const char* _rhs, int32_t _rhsMax)
|
||||
{
|
||||
int32_t max = min(_lhsMax, _rhsMax);
|
||||
int32_t ii = 0;
|
||||
int32_t idx = 0;
|
||||
bool zero = true;
|
||||
|
||||
for (
|
||||
; 0 < max && _lhs[ii] == _rhs[ii]
|
||||
; ++ii, --max
|
||||
)
|
||||
{
|
||||
const uint8_t ch = _lhs[ii];
|
||||
if ('\0' == ch
|
||||
|| '\0' == _rhs[ii])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isNumeric(ch) )
|
||||
{
|
||||
idx = ii+1;
|
||||
zero = true;
|
||||
}
|
||||
else if ('0' != ch)
|
||||
{
|
||||
zero = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == max)
|
||||
{
|
||||
return _lhsMax == _rhsMax ? 0 : _lhs[ii] - _rhs[ii];
|
||||
}
|
||||
|
||||
if ('0' != _lhs[idx]
|
||||
&& '0' != _rhs[idx])
|
||||
{
|
||||
int32_t jj = 0;
|
||||
for (jj = ii
|
||||
; 0 < max && isNumeric(_lhs[jj])
|
||||
; ++jj, --max
|
||||
)
|
||||
{
|
||||
if (!isNumeric(_rhs[jj]) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNumeric(_rhs[jj]))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (zero
|
||||
&& idx < ii
|
||||
&& (isNumeric(_lhs[ii]) || isNumeric(_rhs[ii]) ) )
|
||||
{
|
||||
return (_lhs[ii] - '0') - (_rhs[ii] - '0');
|
||||
}
|
||||
|
||||
return 0 == max && _lhsMax == _rhsMax ? 0 : _lhs[ii] - _rhs[ii];
|
||||
}
|
||||
|
||||
int32_t strCmpV(const StringView& _lhs, const StringView& _rhs, int32_t _max)
|
||||
{
|
||||
return strCmpV(
|
||||
_lhs.getPtr()
|
||||
, min(_lhs.getLength(), _max)
|
||||
, _rhs.getPtr()
|
||||
, min(_rhs.getLength(), _max)
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t strCopy(char* _dst, int32_t _dstSize, const char* _src, int32_t _num)
|
||||
{
|
||||
BX_ASSERT(NULL != _dst, "_dst can't be NULL!");
|
||||
|
||||
@@ -174,6 +174,23 @@ TEST_CASE("isEqual constexpr", "[string]")
|
||||
STATIC_REQUIRE( bx::isEqual(bx::StringLiteral("pod"), bx::StringView("POD"), false) );
|
||||
}
|
||||
|
||||
TEST_CASE("strCmp constexpr", "[string]")
|
||||
{
|
||||
STATIC_REQUIRE(0 == bx::strCmp("abvgd", "abvgd") );
|
||||
STATIC_REQUIRE(0 < bx::strCmp("abvgd", "abv") );
|
||||
STATIC_REQUIRE(0 > bx::strCmp("", "abvgd") );
|
||||
STATIC_REQUIRE(0 == bx::strCmp("abvgd", "abvgx", 4) );
|
||||
|
||||
STATIC_REQUIRE(0 == bx::strCmpI("abvgd", "ABVGD") );
|
||||
STATIC_REQUIRE(0 > bx::strCmpI("abvgd", "ABVGX") );
|
||||
|
||||
STATIC_REQUIRE(0 > bx::strCmpV("test_2.txt", "test_10.txt") );
|
||||
|
||||
constexpr bx::StringLiteral sorted[] = { "dds", "exr", "ktx", "ktx2", "png" };
|
||||
STATIC_REQUIRE( bx::isSorted(sorted, BX_COUNTOF(sorted), [](const bx::StringLiteral& _lhs, const bx::StringLiteral& _rhs) { return 0 > bx::strCmp(_lhs, _rhs); }) );
|
||||
STATIC_REQUIRE(!bx::isSorted(sorted, BX_COUNTOF(sorted), [](const bx::StringLiteral& _lhs, const bx::StringLiteral& _rhs) { return 0 < bx::strCmp(_lhs, _rhs); }) );
|
||||
}
|
||||
|
||||
TEST_CASE("strCmpV", "[string]")
|
||||
{
|
||||
REQUIRE(0 == bx::strCmpV("test", "test") );
|
||||
|
||||
Reference in New Issue
Block a user