Some improvements (hopefully) to the strnatcmp() function.
This commit is contained in:
parent
409117ec39
commit
11268cd5b1
@ -30,6 +30,12 @@ misrepresented as being the original software.
|
|||||||
* negative chars in their default char type.
|
* negative chars in their default char type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2013-08-23: Skip leading zero's for any run of digits, except
|
||||||
|
* when a decimal point was seen immediatley before.
|
||||||
|
* Patch by LoRd_MuldeR <mulder2@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -39,30 +45,26 @@ misrepresented as being the original software.
|
|||||||
|
|
||||||
/* These are defined as macros to make it easier to adapt this code to
|
/* These are defined as macros to make it easier to adapt this code to
|
||||||
* different characters types or comparison functions. */
|
* different characters types or comparison functions. */
|
||||||
static inline int
|
static inline int nat_isdigit(nat_char a)
|
||||||
nat_isdigit(nat_char a)
|
|
||||||
{
|
{
|
||||||
return iswdigit(a);
|
return iswdigit(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int nat_isspace(nat_char a)
|
||||||
static inline int
|
|
||||||
nat_isspace(nat_char a)
|
|
||||||
{
|
{
|
||||||
return iswspace(a);
|
return iswspace(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline nat_char nat_isdecpoint(nat_char a)
|
||||||
static inline nat_char
|
{
|
||||||
nat_toupper(nat_char a)
|
return (a == L'.') || (a == L',');
|
||||||
|
}
|
||||||
|
static inline nat_char nat_toupper(nat_char a)
|
||||||
{
|
{
|
||||||
return towupper(a);
|
return towupper(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int compare_right(nat_char const *a, nat_char const *b)
|
||||||
|
|
||||||
static int
|
|
||||||
compare_right(nat_char const *a, nat_char const *b)
|
|
||||||
{
|
{
|
||||||
int bias = 0;
|
int bias = 0;
|
||||||
|
|
||||||
@ -70,33 +72,37 @@ compare_right(nat_char const *a, nat_char const *b)
|
|||||||
value wins, but we can't know that it will until we've scanned
|
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
|
both numbers to know that they have the same magnitude, so we
|
||||||
remember it in BIAS. */
|
remember it in BIAS. */
|
||||||
for (;; a++, b++) {
|
for (;; a++, b++)
|
||||||
|
{
|
||||||
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||||
return bias;
|
return bias;
|
||||||
else if (!nat_isdigit(*a))
|
else if (!nat_isdigit(*a))
|
||||||
return -1;
|
return -1;
|
||||||
else if (!nat_isdigit(*b))
|
else if (!nat_isdigit(*b))
|
||||||
return +1;
|
return +1;
|
||||||
else if (*a < *b) {
|
else if (*a < *b)
|
||||||
|
{
|
||||||
if (!bias)
|
if (!bias)
|
||||||
bias = -1;
|
bias = -1;
|
||||||
} else if (*a > *b) {
|
}
|
||||||
|
else if (*a > *b)
|
||||||
|
{
|
||||||
if (!bias)
|
if (!bias)
|
||||||
bias = +1;
|
bias = +1;
|
||||||
} else if (!*a && !*b)
|
}
|
||||||
|
else if (!*a && !*b)
|
||||||
return bias;
|
return bias;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int compare_left(nat_char const *a, nat_char const *b)
|
||||||
static int
|
|
||||||
compare_left(nat_char const *a, nat_char const *b)
|
|
||||||
{
|
{
|
||||||
/* Compare two left-aligned numbers: the first to have a
|
/* Compare two left-aligned numbers: the first to have a
|
||||||
different value wins. */
|
different value wins. */
|
||||||
for (;; a++, b++) {
|
for (;; a++, b++)
|
||||||
|
{
|
||||||
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||||
return 0;
|
return 0;
|
||||||
else if (!nat_isdigit(*a))
|
else if (!nat_isdigit(*a))
|
||||||
@ -112,16 +118,20 @@ compare_left(nat_char const *a, nat_char const *b)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int strnatcmp0(nat_char const *a, nat_char const *b, const bool fold_case)
|
||||||
static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case)
|
|
||||||
{
|
{
|
||||||
int ai, bi;
|
int ai, bi;
|
||||||
nat_char ca, cb;
|
nat_char ca, cb;
|
||||||
int fractional, result;
|
int result;
|
||||||
|
bool fractional, skip_zeros;
|
||||||
|
int sa, sb;
|
||||||
|
|
||||||
assert(a && b);
|
assert(a && b);
|
||||||
ai = bi = 0;
|
ai = bi = 0;
|
||||||
while (1) {
|
skip_zeros = true;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
ca = a[ai]; cb = b[bi];
|
ca = a[ai]; cb = b[bi];
|
||||||
|
|
||||||
/* skip over leading spaces or zeros */
|
/* skip over leading spaces or zeros */
|
||||||
@ -132,25 +142,45 @@ static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case)
|
|||||||
cb = b[++bi];
|
cb = b[++bi];
|
||||||
|
|
||||||
/* process run of digits */
|
/* process run of digits */
|
||||||
if (nat_isdigit(ca) && nat_isdigit(cb)) {
|
if (nat_isdigit(ca) && nat_isdigit(cb))
|
||||||
fractional = (ca == '0' || cb == '0');
|
{
|
||||||
|
sa = sb = 0;
|
||||||
|
|
||||||
if (fractional) {
|
if(skip_zeros)
|
||||||
|
{
|
||||||
|
while (ca == L'0') { ca = a[++ai]; sa++; }
|
||||||
|
while (cb == L'0') { cb = b[++bi]; sb++; }
|
||||||
|
}
|
||||||
|
|
||||||
|
fractional = (ca == L'0' || cb == L'0');
|
||||||
|
|
||||||
|
if (fractional)
|
||||||
|
{
|
||||||
if ((result = compare_left(a+ai, b+bi)) != 0)
|
if ((result = compare_left(a+ai, b+bi)) != 0)
|
||||||
return result;
|
return result;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if ((result = compare_right(a+ai, b+bi)) != 0)
|
if ((result = compare_right(a+ai, b+bi)) != 0)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* on tie, the string with the longer leading zero's sequence wins */
|
||||||
|
if(sa < sb)
|
||||||
|
return -1;
|
||||||
|
else if(sa > sb)
|
||||||
|
return +1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ca && !cb) {
|
if (!ca && !cb)
|
||||||
|
{
|
||||||
/* The strings compare the same. Perhaps the caller
|
/* The strings compare the same. Perhaps the caller
|
||||||
will want to call strcmp to break the tie. */
|
will want to call strcmp to break the tie. */
|
||||||
return 0;
|
return (fold_case) ? _wcsicmp(a, b) : wcscmp(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fold_case) {
|
if (fold_case)
|
||||||
|
{
|
||||||
ca = nat_toupper(ca);
|
ca = nat_toupper(ca);
|
||||||
cb = nat_toupper(cb);
|
cb = nat_toupper(cb);
|
||||||
}
|
}
|
||||||
@ -160,18 +190,20 @@ static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case)
|
|||||||
else if (ca > cb)
|
else if (ca > cb)
|
||||||
return +1;
|
return +1;
|
||||||
|
|
||||||
|
/* skipp leading zero's, unless previously seen char was a decimal point */
|
||||||
|
skip_zeros = (!nat_isdecpoint(ca)) || (!nat_isdecpoint(cb));
|
||||||
|
|
||||||
++ai; ++bi;
|
++ai; ++bi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int strnatcmp(nat_char const *a, nat_char const *b)
|
||||||
|
{
|
||||||
int strnatcmp(nat_char const *a, nat_char const *b) {
|
return strnatcmp0(a, b, false);
|
||||||
return strnatcmp0(a, b, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Compare, recognizing numeric string and ignoring case. */
|
/* Compare, recognizing numeric string and ignoring case. */
|
||||||
int strnatcasecmp(nat_char const *a, nat_char const *b) {
|
int strnatcasecmp(nat_char const *a, nat_char const *b)
|
||||||
return strnatcmp0(a, b, 1);
|
{
|
||||||
|
return strnatcmp0(a, b, true);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#define VER_LAMEXP_MINOR_LO 8
|
#define VER_LAMEXP_MINOR_LO 8
|
||||||
#define VER_LAMEXP_TYPE RC
|
#define VER_LAMEXP_TYPE RC
|
||||||
#define VER_LAMEXP_PATCH 2
|
#define VER_LAMEXP_PATCH 2
|
||||||
#define VER_LAMEXP_BUILD 1329
|
#define VER_LAMEXP_BUILD 1332
|
||||||
#define VER_LAMEXP_CONFG 1288
|
#define VER_LAMEXP_CONFG 1288
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user