Improve strlogicalcmp for strings of unequal lengths

This version actually works and doesn't overrun provided buffers
This commit is contained in:
Michał Janiszewski 2020-03-27 12:54:14 +01:00
parent d2565af867
commit 16d8c64cea
2 changed files with 31 additions and 28 deletions

View file

@ -323,37 +323,32 @@ int32_t strcicmp(char const* a, char const* b)
// - Guest 100
// - John v2.0
// - John v2.1
int32_t strlogicalcmp(char const* a, char const* b)
int32_t strlogicalcmp(const char* s1, const char* s2)
{
for (;; a++, b++)
for (;;)
{
int32_t result = tolower(*a) - tolower(*b);
bool both_numeric = *a >= '0' && *a <= '9' && *b >= '0' && *b <= '9';
if (result != 0 || !*a || both_numeric)
{ // difference found || end of string
if (both_numeric)
{ // a and b both start with a number
// Get the numbers in the string at current positions
int32_t na = 0, nb = 0;
for (; *a >= '0' && *a <= '9'; a++)
{
na *= 10;
na += *a - '0';
}
for (; *b >= '0' && *b <= '9'; b++)
{
nb *= 10;
nb += *b - '0';
}
// In case the numbers are the same
if (na == nb)
continue;
return na - nb;
}
if (*s2 == '\0')
return *s1 != '\0';
else if (*s1 == '\0')
return -1;
else if (!(isdigit(*s1) && isdigit(*s2)))
{
if (*s1 != *s2)
return (int)*s1 - (int)*s2;
else
{
return result;
}
(++s1, ++s2);
}
else
{
char *lim1, *lim2;
unsigned long n1 = strtoul(s1, &lim1, 10);
unsigned long n2 = strtoul(s2, &lim2, 10);
if (n1 > n2)
return 1;
else if (n1 < n2)
return -1;
s1 = lim1;
s2 = lim2;
}
}
}

View file

@ -12,6 +12,7 @@
#include <gtest/gtest.h>
#include <openrct2/core/String.hpp>
#include <openrct2/util/Util.h>
#include <string>
#include <tuple>
#include <utility>
@ -147,3 +148,10 @@ TEST_F(StringTest, ToUpper_Japanese)
auto actual = String::ToUpper(u8"日本語で大文字がなし");
ASSERT_STREQ(actual.c_str(), u8"日本語で大文字がなし");
}
TEST_F(StringTest, strlogicalcmp)
{
auto res1 = strlogicalcmp("foo1", "foo1_2");
auto res2 = strlogicalcmp("foo1_2", "foo1");
ASSERT_NE(res1, res2);
}