lenl-lenr is not a valid expression for a signed int return value from strverscmp, since after implicit conversion from size_t to int this difference could have the wrong sign or might even be zero. using the difference for char values works since they're bounded well within the range of differences representable by int, but it does not work for size_t values.
43 lines
708 B
C
43 lines
708 B
C
#define _GNU_SOURCE
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
|
|
int strverscmp(const char *l, const char *r)
|
|
{
|
|
int haszero=1;
|
|
while (*l==*r) {
|
|
if (!*l) return 0;
|
|
|
|
if (*l=='0') {
|
|
if (haszero==1) {
|
|
haszero=0;
|
|
}
|
|
} else if (isdigit(*l)) {
|
|
if (haszero==1) {
|
|
haszero=2;
|
|
}
|
|
} else {
|
|
haszero=1;
|
|
}
|
|
l++; r++;
|
|
}
|
|
if (haszero==1 && (*l=='0' || *r=='0')) {
|
|
haszero=0;
|
|
}
|
|
if ((isdigit(*l) && isdigit(*r) ) && haszero) {
|
|
size_t lenl=0, lenr=0;
|
|
while (isdigit(l[lenl]) ) lenl++;
|
|
while (isdigit(r[lenr]) ) lenr++;
|
|
if (lenl==lenr) {
|
|
return (*l - *r);
|
|
} else if (lenl>lenr) {
|
|
return 1;
|
|
} else {
|
|
return -1;
|
|
}
|
|
} else {
|
|
return (*l - *r);
|
|
}
|
|
}
|