소스 검색

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.

(cherry picked from commit de46c92711f83b14a532702060d17b4269b9e1e9)
Maganty Rushyendra 5 년 전
부모
커밋
a46fd28ae3
1개의 변경된 파일38개의 추가작업 그리고 19개의 파일을 삭제
  1. 38 19
      core/ustring.cpp

+ 38 - 19
core/ustring.cpp

@@ -535,33 +535,52 @@ signed char String::naturalnocasecmp_to(const String &p_str) const {
 		}
 		}
 
 
 		while (*this_str) {
 		while (*this_str) {
-
-			if (!*that_str)
+			if (!*that_str) {
 				return 1;
 				return 1;
-			else if (IS_DIGIT(*this_str)) {
-
-				int64_t this_int, that_int;
-
-				if (!IS_DIGIT(*that_str))
+			} else if (IS_DIGIT(*this_str)) {
+				if (!IS_DIGIT(*that_str)) {
 					return -1;
 					return -1;
+				}
 
 
-				/* Compare the numbers */
-				this_int = to_int(this_str);
-				that_int = to_int(that_str);
+				// Keep ptrs to start of numerical sequences
+				const CharType *this_substr = this_str;
+				const CharType *that_substr = that_str;
 
 
-				if (this_int < that_int)
+				// 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;
 					return -1;
-				else if (this_int > that_int)
+				} else if (this_len > that_len) {
 					return 1;
 					return 1;
+				}
 
 
-				/* Skip */
-				while (IS_DIGIT(*this_str))
-					this_str++;
-				while (IS_DIGIT(*that_str))
-					that_str++;
-			} else if (IS_DIGIT(*that_str))
+				// 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;
 				return 1;
-			else {
+			} else {
 				if (_find_upper(*this_str) < _find_upper(*that_str)) //more than
 				if (_find_upper(*this_str) < _find_upper(*that_str)) //more than
 					return -1;
 					return -1;
 				else if (_find_upper(*this_str) > _find_upper(*that_str)) //less than
 				else if (_find_upper(*this_str) > _find_upper(*that_str)) //less than