diff options
author | Maganty Rushyendra <mrushyendra@yahoo.com.sg> | 2020-07-03 23:47:24 +0800 |
---|---|---|
committer | Maganty Rushyendra <mrushyendra@yahoo.com.sg> | 2020-07-04 07:42:02 +0800 |
commit | de46c92711f83b14a532702060d17b4269b9e1e9 (patch) | |
tree | df5cdd1e041032fc674d57e57682b5d735388066 | |
parent | 73fddc623bdd58b762c8db328ee59055fc2a33ed (diff) |
Fix natural sort comparison for strings with large numbers
Fix errors when comparing strings with large numbers (> INT64_MAX).
Comparisons now occur by comparing individual digits, instead of
converting to int64_t first.
-rw-r--r-- | core/ustring.cpp | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/core/ustring.cpp b/core/ustring.cpp index 5d3cf5f1a4..309439aaf6 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -527,29 +527,46 @@ signed char String::naturalnocasecmp_to(const String &p_str) const { if (!*that_str) { return 1; } else if (IS_DIGIT(*this_str)) { - int64_t this_int, that_int; - if (!IS_DIGIT(*that_str)) { return -1; } - /* Compare the numbers */ - this_int = to_int(this_str, -1, true); - that_int = to_int(that_str, -1, true); + // Keep ptrs to start of numerical sequences + const CharType *this_substr = this_str; + const CharType *that_substr = that_str; - if (this_int < that_int) { - return -1; - } else if (this_int > that_int) { - return 1; - } - - /* Skip */ + // Compare lengths of both numerical sequences, ignoring leading zeros while (IS_DIGIT(*this_str)) { this_str++; } while (IS_DIGIT(*that_str)) { that_str++; } + while (*this_substr == '0') { + this_substr++; + } + while (*that_substr == '0') { + that_substr++; + } + int this_len = this_str - this_substr; + int that_len = that_str - that_substr; + + if (this_len < that_len) { + return -1; + } else if (this_len > that_len) { + return 1; + } + + // If lengths equal, compare lexicographically + while (this_substr != this_str && that_substr != that_str) { + if (*this_substr < *that_substr) { + return -1; + } else if (*this_substr > *that_substr) { + return 1; + } + this_substr++; + that_substr++; + } } else if (IS_DIGIT(*that_str)) { return 1; } else { |