summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaganty Rushyendra <mrushyendra@yahoo.com.sg>2020-07-03 23:47:24 +0800
committerMaganty Rushyendra <mrushyendra@yahoo.com.sg>2020-07-04 07:42:02 +0800
commitde46c92711f83b14a532702060d17b4269b9e1e9 (patch)
treedf5cdd1e041032fc674d57e57682b5d735388066
parent73fddc623bdd58b762c8db328ee59055fc2a33ed (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.cpp41
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 {