mirror of
https://github.com/OpenRCT2/OpenRCT2.git
synced 2026-05-06 07:56:46 -04:00
Commit 43f7d2d91 introduced a regression where logicalCmp compared digit starting strings lexicographically instead of numerically, causing folders to sort as "1, 10, 11, 2..." instead of "1, 2... 10, 11". This commit removes the broken special case, the main loop already handles
numeric comparison correctly
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
- Feature: [#22704] Rides can be made invisible more easily.
|
||||
- Improved: [#25941] The command line sprite build command is now faster.
|
||||
- Fix: [#25237] Wrong colours on the Knight costume.
|
||||
- Fix: [#25910] Folders starting with numbers are sorted incorrectly (e.g. 1, 10, 2 instead of 1, 2, 10).
|
||||
|
||||
0.4.31 (2026-02-01)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
@@ -721,13 +721,8 @@ namespace OpenRCT2::String
|
||||
return escaped.str();
|
||||
}
|
||||
|
||||
/* Case insensitive logical compare, produces the same output as Notepad++ lexicographical sort */
|
||||
// Example:
|
||||
// - Guest 10
|
||||
// - Guest 99
|
||||
// - Guest 100
|
||||
// - John v2.0
|
||||
// - John v2.1
|
||||
// Case insensitive natural sort (numbers compared numerically).
|
||||
// Strings starting with digits sort before alphabetic strings.
|
||||
int32_t logicalCmp(const char* s1, const char* s2)
|
||||
{
|
||||
const auto isDigit = [](char c) { return std::isdigit(static_cast<unsigned char>(c)); };
|
||||
@@ -737,30 +732,9 @@ namespace OpenRCT2::String
|
||||
bool s1StartsDigit = isDigit(*s1);
|
||||
bool s2StartsDigit = isDigit(*s2);
|
||||
if (s1StartsDigit && !s2StartsDigit)
|
||||
{
|
||||
return -1; // s1 (starts with digit) comes before s2
|
||||
}
|
||||
return -1;
|
||||
if (!s1StartsDigit && s2StartsDigit)
|
||||
{
|
||||
return 1; // s2 (starts with digit) comes before s1
|
||||
}
|
||||
|
||||
// If both start with digits, compare lexicographically
|
||||
if (s1StartsDigit && s2StartsDigit)
|
||||
{
|
||||
while (*s1 != '\0' && *s2 != '\0')
|
||||
{
|
||||
char c1 = toUpper(*s1);
|
||||
char c2 = toUpper(*s2);
|
||||
if (c1 != c2)
|
||||
{
|
||||
return c1 - c2;
|
||||
}
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *s1 == '\0' ? (*s2 == '\0' ? 0 : -1) : 1;
|
||||
}
|
||||
return 1;
|
||||
|
||||
while (*s1 != '\0' && *s2 != '\0')
|
||||
{
|
||||
|
||||
@@ -255,10 +255,12 @@ TEST_F(CodepointViewTest, CodepointView_iterate)
|
||||
|
||||
TEST_F(StringTest, LogicalCompare)
|
||||
{
|
||||
// Strings starting with digits come first, sorted numerically
|
||||
// Then alphabetic strings sorted case-insensitively
|
||||
std::vector<std::string> expected = {
|
||||
"1001 Troubles", "3D Cinema 1", "Aerial Cycles", "Batflyer", "bpb",
|
||||
"bpb.sv6", "Drive-by", "foo", "foobar", "Guest 10",
|
||||
"Guest 99", "Guest 100", "John v2.0", "John v2.1", "River of the Damned",
|
||||
"3D Cinema 1", "1001 Troubles", "Aerial Cycles", "Batflyer", "bpb",
|
||||
"bpb.sv6", "Drive-by", "foo", "foobar", "Guest 10",
|
||||
"Guest 99", "Guest 100", "John v2.0", "John v2.1", "River of the Damned",
|
||||
"Terror-dactyl",
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user