diff options
| -rw-r--r-- | src/string/strverscmp.c | 57 | 
1 files changed, 25 insertions, 32 deletions
| diff --git a/src/string/strverscmp.c b/src/string/strverscmp.c index 6f37cc68..4daf276d 100644 --- a/src/string/strverscmp.c +++ b/src/string/strverscmp.c @@ -2,40 +2,33 @@  #include <ctype.h>  #include <string.h> -int strverscmp(const char *l, const char *r) +int strverscmp(const char *l0, const char *r0)  { -	int haszero=1; -	while (*l==*r) { -		if (!*l) return 0; +	const unsigned char *l = (const void *)l0; +	const unsigned char *r = (const void *)r0; +	size_t i, dp, j; +	int z = 1; -		if (*l=='0') { -			if (haszero==1) { -				haszero=0; -			} -		} else if (isdigit(*l)) { -			if (haszero==1) { -				haszero=2; -			} -		} else { -			haszero=1; -		} -		l++; r++; +	/* Find maximal matching prefix and track its maximal digit +	 * suffix and whether those digits are all zeros. */ +	for (dp=i=0; l[i]==r[i]; i++) { +		int c = l[i]; +		if (!c) return 0; +		if (!isdigit(c)) dp=i+1, z=1; +		else if (c!='0') z=0;  	} -	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); + +	if (l[dp]!='0' && r[dp]!='0') { +		/* If we're not looking at a digit sequence that began +		 * with a zero, longest digit string is greater. */ +		for (j=i; isdigit(l[j]); j++) +			if (!isdigit(r[j])) return 1; +		if (isdigit(r[j])) return -1; +	} else if (z && dp<i && (isdigit(l[i]) || isdigit(r[i]))) { +		/* Otherwise, if common prefix of digit sequence is +		 * all zeros, digits order less than non-digits. */ +		return (unsigned char)(l[i]-'0') - (unsigned char)(r[i]-'0');  	} + +	return l[i] - r[i];  } | 
