Index: firmware/common/strnatcmp.c =================================================================== --- firmware/common/strnatcmp.c (Revision 20347) +++ firmware/common/strnatcmp.c (Arbeitskopie) @@ -67,11 +67,16 @@ static inline int -nat_toupper(int a) +nat_tolower(int a) { - return toupper(a); + return tolower(a); } +static inline int +nat_iszero(int a) +{ + return a == '0'; +} static int @@ -81,26 +86,26 @@ int ca, cb; /* The longest run of digits wins. That aside, the greatest - value wins, but we can't know that it will until we've scanned - both numbers to know that they have the same magnitude, so we - remember it in BIAS. */ + value wins, but we can't know that it will until we've scanned + both numbers to know that they have the same magnitude, so we + remember it in BIAS. */ for (;; a++, b++) { ca = to_int(*a); cb = to_int(*b); - if (!nat_isdigit(ca) && !nat_isdigit(cb)) - return bias; - else if (!nat_isdigit(ca)) - return -1; - else if (!nat_isdigit(cb)) - return +1; - else if (ca < cb) { - if (!bias) - bias = -1; - } else if (ca > cb) { - if (!bias) - bias = +1; - } else if (!ca && !cb) - return bias; + if (!nat_isdigit(ca) && !nat_isdigit(cb)) + return bias; + else if (!nat_isdigit(ca)) + return -1; + else if (!nat_isdigit(cb)) + return +1; + else if (ca < cb) { + if (!bias) + bias = -1; + } else if (ca > cb) { + if (!bias) + bias = +1; + } else if (!ca && !cb) + return bias; } return 0; @@ -110,21 +115,22 @@ static int compare_left(char const *a, char const *b) { + int ca, cb; /* Compare two left-aligned numbers: the first to have a different value wins. */ for (;; a++, b++) { - if (!nat_isdigit(*a) && !nat_isdigit(*b)) - return 0; - else if (!nat_isdigit(*a)) - return -1; - else if (!nat_isdigit(*b)) - return +1; - else if (*a < *b) - return -1; - else if (*a > *b) - return +1; + ca = to_int(*a); + cb = to_int(*b); + if (!nat_isdigit(ca) && !nat_isdigit(cb)) + return 0; + else if (!nat_isdigit(ca)) + return -1; + else if (!nat_isdigit(cb)) + return +1; + else if (ca != cb) + return ca-cb; } - + return 0; } @@ -133,53 +139,67 @@ int ai, bi; int ca, cb; int fractional, result; - assert(a && b); ai = bi = 0; + + ca = to_int(*a); + cb = to_int(*b); + + /* collapse leading zeros to 1, if a non-digit follows */ + while (nat_iszero(ca)) + ca = to_int(a[++ai]); + while (nat_iszero(cb)) + cb = to_int(b[++bi]); + + + /* We indirectly counted zeros (and spaces). if ai/bi is not zero, and a + * non-digit follows, we collapse all zeros except the + * the final one, if the previous was a space, it will be killed in + * the while loop again */ + if (ai > 0 && !nat_isdigit(ca)) + ai--; + if (bi > 0 && !nat_isdigit(ca)) + bi--; while (1) { ca = to_int(a[ai]); cb = to_int(b[bi]); - /* skip over leading spaces or zeros */ - while (nat_isspace(ca)) - ca = to_int(a[++ai]); + /* skip over spaces */ + while (nat_isspace(ca)) + ca = to_int(a[++ai]); - while (nat_isspace(cb)) - cb = to_int(b[++bi]); + while (nat_isspace(cb)) + cb = to_int(b[++bi]); + /* process run of digits */ + if (nat_isdigit(ca) && nat_isdigit(cb)) { + fractional = (nat_iszero(ca) || nat_iszero(cb)); + if (fractional) { + if ((result = compare_left(a+ai, b+bi)) != 0) + return result; + } else { + if ((result = compare_right(a+ai, b+bi)) != 0) + return result; + } + } - /* process run of digits */ - if (nat_isdigit(ca) && nat_isdigit(cb)) { - fractional = (ca == '0' || cb == '0'); - - if (fractional) { - if ((result = compare_left(a+ai, b+bi)) != 0) - return result; - } else { - if ((result = compare_right(a+ai, b+bi)) != 0) - return result; - } - } - - if (!ca && !cb) { - /* The strings compare the same. Call str[case]cmp() to ensure + if (!ca && !cb) { + /* The strings compare the same. Call str[case]cmp() to ensure consistent results. */ if(fold_case) return strcasecmp(a,b); else return strcmp(a,b); - } + } - if (fold_case) { - ca = nat_toupper(ca); - cb = nat_toupper(cb); - } - - if (ca < cb) - return -1; - else if (ca > cb) - return +1; + if (fold_case) { + ca = nat_tolower(ca); + cb = nat_tolower(cb); + } + + if (ca != cb) + return ca-cb; - ++ai; ++bi; + ++ai; ++bi; } }