diff --git a/src/openrct2/util/Util.cpp b/src/openrct2/util/Util.cpp index 8804b88a77..52c3aeb0a1 100644 --- a/src/openrct2/util/Util.cpp +++ b/src/openrct2/util/Util.cpp @@ -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; } } } diff --git a/test/tests/StringTest.cpp b/test/tests/StringTest.cpp index 825ecaa6d8..b4ea572316 100644 --- a/test/tests/StringTest.cpp +++ b/test/tests/StringTest.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -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); +}