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,64 +139,81 @@ 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, 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. if ai/bi is not zero, and the index + * points to a non-digit, we collapse all zeros except the + * the final one, if it's a digit, we ignore all zeros */ + 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 (!ca && !cb) { + return 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 (fold_case) { + ca = nat_tolower(ca); + cb = nat_tolower(cb); + } + + if (ca != cb) + return ca-cb; - 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; - - ++ai; ++bi; + ++ai; ++bi; } } -int strnatcmp(const char *a, const char *b) { - return strnatcmp0(a, b, 0); +int strnatcmp(const char *a, const char *b) +{ + int ret = strnatcmp0(a, b, 0); + if (ret != 0) + return ret; + return strcmp(a,b); } /* Compare, recognizing numeric string and ignoring case. */ -int strnatcasecmp(const char *a, const char *b) { - return strnatcmp0(a, b, 1); +int strnatcasecmp(const char *a, const char *b) +{ + int ret = strnatcmp0(a, b, 1); + if (ret != 0) + return ret; + return strcasecmp(a,b); }