#include <ctype.h>
#include <string.h>
#include "apr_strings.h"
#include "apr_lib.h"
#if defined(__GNUC__)
# define UNUSED __attribute__((__unused__))
#else
# define UNUSED
#endif
static int
compare_right(char const *a, char const *b)
{
int bias = 0;
for (;; a++, b++) {
if (!apr_isdigit(*a) && !apr_isdigit(*b))
break;
else if (!apr_isdigit(*a))
return -1;
else if (!apr_isdigit(*b))
return +1;
else if (*a < *b) {
if (!bias)
bias = -1;
} else if (*a > *b) {
if (!bias)
bias = +1;
} else if (!*a && !*b)
break;
}
return bias;
}
static int
compare_left(char const *a, char const *b)
{
for (;; a++, b++) {
if (!apr_isdigit(*a) && !apr_isdigit(*b))
break;
else if (!apr_isdigit(*a))
return -1;
else if (!apr_isdigit(*b))
return +1;
else if (*a < *b)
return -1;
else if (*a > *b)
return +1;
}
return 0;
}
static int strnatcmp0(char const *a, char const *b, int fold_case)
{
int ai, bi;
char ca, cb;
int fractional, result;
ai = bi = 0;
while (1) {
ca = a[ai]; cb = b[bi];
while (apr_isspace(ca))
ca = a[++ai];
while (apr_isspace(cb))
cb = b[++bi];
if (apr_isdigit(ca) && apr_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) {
return 0;
}
if (fold_case) {
ca = apr_toupper(ca);
cb = apr_toupper(cb);
}
if (ca < cb)
return -1;
else if (ca > cb)
return +1;
++ai; ++bi;
}
}
APR_DECLARE(int) apr_strnatcmp(char const *a, char const *b)
{
return strnatcmp0(a, b, 0);
}
APR_DECLARE(int) apr_strnatcasecmp(char const *a, char const *b)
{
return strnatcmp0(a, b, 1);
}