cmdlib: fix broken Q_strcasecmp and Q_strncasecmp
string_view isn't null terminated, can't use C string functions
This commit is contained in:
parent
638076ffb2
commit
d7eca5f317
|
|
@ -41,34 +41,47 @@
|
|||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#if defined(__has_include) && __has_include(<strings.h>)
|
||||
#include <strings.h>
|
||||
#endif
|
||||
char Q_tolower(char x)
|
||||
{
|
||||
if (x >= 'A' && x <= 'Z') {
|
||||
x += 'a' - 'A';
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
int32_t Q_strncasecmp(std::string_view a, std::string_view b, size_t maxcount)
|
||||
{
|
||||
return
|
||||
#ifdef _WIN32
|
||||
_strnicmp
|
||||
#elif defined(__has_include) && __has_include(<strings.h>)
|
||||
strncasecmp
|
||||
#else
|
||||
strnicmp
|
||||
#endif
|
||||
(a.data(), b.data(), maxcount);
|
||||
return Q_strcasecmp(
|
||||
a.substr(0, maxcount),
|
||||
b.substr(0, maxcount));
|
||||
}
|
||||
|
||||
int32_t Q_strcasecmp(std::string_view a, std::string_view b)
|
||||
{
|
||||
return
|
||||
#ifdef _WIN32
|
||||
_stricmp
|
||||
#elif defined(__has_include) && __has_include(<strings.h>)
|
||||
strcasecmp
|
||||
#else
|
||||
stricmp
|
||||
#endif
|
||||
(a.data(), b.data());
|
||||
const char *a_ptr = a.data();
|
||||
const char *b_ptr = b.data();
|
||||
const size_t common_size = std::min(a.size(), b.size());
|
||||
|
||||
for (size_t i = 0; i < common_size; ++i) {
|
||||
char achar = Q_tolower(a_ptr[i]);
|
||||
char bchar = Q_tolower(b_ptr[i]);
|
||||
|
||||
if (achar < bchar) {
|
||||
return -1;
|
||||
}
|
||||
if (achar > bchar) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// the first common_size chars are the same
|
||||
if (a.size() < b.size()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.size() > b.size()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void // mxd
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <ostream>
|
||||
#include <tuple> // for std::apply()
|
||||
|
||||
char Q_tolower(char x);
|
||||
int32_t Q_strncasecmp(std::string_view a, std::string_view b, size_t maxcount);
|
||||
int32_t Q_strcasecmp(std::string_view a, std::string_view b);
|
||||
bool string_iequals(std::string_view a, std::string_view b); // mxd
|
||||
|
|
|
|||
|
|
@ -382,3 +382,33 @@ TEST(qmat, transpose)
|
|||
|
||||
EXPECT_EQ(in.transpose(), exp);
|
||||
}
|
||||
|
||||
TEST(string, strcasecmp)
|
||||
{
|
||||
EXPECT_EQ('x', Q_tolower('X'));
|
||||
EXPECT_EQ('"', Q_tolower('"'));
|
||||
|
||||
const char *test = "abcA**";
|
||||
|
||||
// lhs < rhs
|
||||
EXPECT_LT(Q_strcasecmp("a", "aa"), 0);
|
||||
EXPECT_LT(Q_strcasecmp("aaa", "BBB"), 0);
|
||||
EXPECT_LT(Q_strcasecmp("AAA", "bbb"), 0);
|
||||
|
||||
// lhs == rhs
|
||||
EXPECT_EQ(Q_strcasecmp(std::string_view(&test[0], 1), std::string_view(&test[3], 1)), 0);
|
||||
EXPECT_EQ(Q_strcasecmp("test", "TEST"), 0);
|
||||
EXPECT_EQ(Q_strcasecmp("test", "test"), 0);
|
||||
|
||||
// lhs > rhs
|
||||
EXPECT_GT(Q_strcasecmp("test", "aaaa"), 0);
|
||||
EXPECT_GT(Q_strcasecmp("test", "AAAA"), 0);
|
||||
EXPECT_GT(Q_strcasecmp("test", "tes"), 0);
|
||||
EXPECT_GT(Q_strcasecmp("TEST", "T"), 0);
|
||||
}
|
||||
|
||||
TEST(string, strncasecmp)
|
||||
{
|
||||
EXPECT_EQ(Q_strncasecmp("*lava123", "*LAVA", 5), 0);
|
||||
EXPECT_EQ(Q_strncasecmp("*lava123", "*LAVA", 8), 1);
|
||||
}
|
||||
Loading…
Reference in New Issue