Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2013-05-10 18:52:23 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2013-05-10 18:52:23 +0400
commit65ed588c8b68b4bbea0e48a0222f5e8844774bd9 (patch)
tree7f57fe941e77981bc6fbedf8837a742764b83db1 /source/blender/blenlib/intern/string.c
parent384adf39b9b75f08aee1a399ff81e5671b06794c (diff)
Fix #35270: files with numbers higher than 2147483648 or with different numbers
of leading zeros but otherwise the same would show in random order in the file browser. Selecting an item would change the order of all the items. Problem was that it was comparing by parsing the number into an int, which has only limited precision and does not care about the number of leading zeros. Now do the comparison directly on the string.
Diffstat (limited to 'source/blender/blenlib/intern/string.c')
-rw-r--r--source/blender/blenlib/intern/string.c62
1 files changed, 50 insertions, 12 deletions
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 0982670eb5a..ed11d122e93 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -433,13 +433,57 @@ int BLI_strncasecmp(const char *s1, const char *s2, size_t len)
return 0;
}
+/* compare number on the left size of the string */
+static int left_number_strcmp(const char *s1, const char *s2, int *tiebreaker)
+{
+ const char *p1 = s1, *p2 = s2;
+ int numdigit, numzero1, numzero2;
+
+ /* count and skip leading zeros */
+ for (numzero1 = 0; *p1 && (*p1 == '0'); numzero1++)
+ p1++;
+ for (numzero2 = 0; *p2 && (*p2 == '0'); numzero2++)
+ p2++;
+
+ /* find number of consecutive digits */
+ for (numdigit = 0; ; numdigit++) {
+ if (isdigit(*(p1 + numdigit)) && isdigit(*(p2 + numdigit)))
+ continue;
+ else if (isdigit(*(p1 + numdigit)))
+ return 1; /* s2 is bigger */
+ else if (isdigit(*(p2 + numdigit)))
+ return -1; /* s1 is bigger */
+ else
+ break;
+ }
+
+ /* same number of digits, compare size of number */
+ if (numdigit > 0) {
+ int compare = strncmp(p1, p2, numdigit);
+
+ if (compare != 0)
+ return compare;
+ }
+
+ /* use number of leading zeros as tie breaker if still equal */
+ if (*tiebreaker == 0) {
+ if (numzero1 > numzero2)
+ *tiebreaker = 1;
+ else if (numzero1 < numzero2)
+ *tiebreaker = -1;
+ }
+
+ return 0;
+}
+
/* natural string compare, keeping numbers in order */
int BLI_natstrcmp(const char *s1, const char *s2)
{
register int d1 = 0, d2 = 0;
register char c1, c2;
+ int tiebreaker = 0;
- /* if both chars are numeric, to a strtol().
+ /* if both chars are numeric, to a left_number_strcmp().
* then increase string deltas as long they are
* numeric, else do a tolower and char compare */
@@ -448,17 +492,11 @@ int BLI_natstrcmp(const char *s1, const char *s2)
c2 = tolower(s2[d2]);
if (isdigit(c1) && isdigit(c2) ) {
- int val1, val2;
-
- val1 = (int)strtol(s1 + d1, (char **)NULL, 10);
- val2 = (int)strtol(s2 + d2, (char **)NULL, 10);
+ int numcompare = left_number_strcmp(s1 + d1, s2 + d2, &tiebreaker);
- if (val1 < val2) {
- return -1;
- }
- else if (val1 > val2) {
- return 1;
- }
+ if (numcompare != 0)
+ return numcompare;
+
d1++;
while (isdigit(s1[d1]) )
d1++;
@@ -487,7 +525,7 @@ int BLI_natstrcmp(const char *s1, const char *s2)
d1++;
d2++;
}
- return 0;
+ return tiebreaker;
}
void BLI_timestr(double _time, char *str, size_t maxlen)