#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "php.h"
#include "php_string.h"
#if defined(__GNUC__)
# define UNUSED __attribute__((__unused__))
#else
# define UNUSED
#endif
#if 0
static char const *version UNUSED =
"$Id$";
#endif
static int
compare_right(char const **a, char const *aend, char const **b, char const *bend)
{
int bias = 0;
for(;; (*a)++, (*b)++) {
if ((*a == aend || !isdigit((int)(unsigned char)**a)) &&
(*b == bend || !isdigit((int)(unsigned char)**b)))
return bias;
else if (*a == aend || !isdigit((int)(unsigned char)**a))
return -1;
else if (*b == bend || !isdigit((int)(unsigned char)**b))
return +1;
else if (**a < **b) {
if (!bias)
bias = -1;
} else if (**a > **b) {
if (!bias)
bias = +1;
}
}
return 0;
}
static int
compare_left(char const **a, char const *aend, char const **b, char const *bend)
{
for(;; (*a)++, (*b)++) {
if ((*a == aend || !isdigit((int)(unsigned char)**a)) &&
(*b == bend || !isdigit((int)(unsigned char)**b)))
return 0;
else if (*a == aend || !isdigit((int)(unsigned char)**a))
return -1;
else if (*b == bend || !isdigit((int)(unsigned char)**b))
return +1;
else if (**a < **b)
return -1;
else if (**a > **b)
return +1;
}
return 0;
}
PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len, int fold_case)
{
unsigned char ca, cb;
char const *ap, *bp;
char const *aend = a + a_len,
*bend = b + b_len;
int fractional, result;
short leading = 1;
if (a_len == 0 || b_len == 0)
return a_len - b_len;
ap = a;
bp = b;
while (1) {
ca = *ap; cb = *bp;
while (leading && ca == '0' && (ap+1 < aend) && isdigit((int)(unsigned char)*(ap+1))) {
ca = *++ap;
}
while (leading && cb == '0' && (bp+1 < bend) && isdigit((int)(unsigned char)*(bp+1))) {
cb = *++bp;
}
leading = 0;
while (isspace((int)(unsigned char)ca)) {
ca = *++ap;
}
while (isspace((int)(unsigned char)cb)) {
cb = *++bp;
}
if (isdigit((int)(unsigned char)ca) && isdigit((int)(unsigned char)cb)) {
fractional = (ca == '0' || cb == '0');
if (fractional)
result = compare_left(&ap, aend, &bp, bend);
else
result = compare_right(&ap, aend, &bp, bend);
if (result != 0)
return result;
else if (ap == aend && bp == bend)
return 0;
else {
ca = *ap; cb = *bp;
}
}
if (fold_case) {
ca = toupper((int)(unsigned char)ca);
cb = toupper((int)(unsigned char)cb);
}
if (ca < cb)
return -1;
else if (ca > cb)
return +1;
++ap; ++bp;
if (ap >= aend && bp >= bend)
return 0;
else if (ap >= aend)
return -1;
else if (bp >= bend)
return 1;
}
}