xref: /aosp_15_r20/external/musl/src/string/strverscmp.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1*c9945492SAndroid Build Coastguard Worker #define _GNU_SOURCE
2*c9945492SAndroid Build Coastguard Worker #include <ctype.h>
3*c9945492SAndroid Build Coastguard Worker #include <string.h>
4*c9945492SAndroid Build Coastguard Worker 
strverscmp(const char * l0,const char * r0)5*c9945492SAndroid Build Coastguard Worker int strverscmp(const char *l0, const char *r0)
6*c9945492SAndroid Build Coastguard Worker {
7*c9945492SAndroid Build Coastguard Worker 	const unsigned char *l = (const void *)l0;
8*c9945492SAndroid Build Coastguard Worker 	const unsigned char *r = (const void *)r0;
9*c9945492SAndroid Build Coastguard Worker 	size_t i, dp, j;
10*c9945492SAndroid Build Coastguard Worker 	int z = 1;
11*c9945492SAndroid Build Coastguard Worker 
12*c9945492SAndroid Build Coastguard Worker 	/* Find maximal matching prefix and track its maximal digit
13*c9945492SAndroid Build Coastguard Worker 	 * suffix and whether those digits are all zeros. */
14*c9945492SAndroid Build Coastguard Worker 	for (dp=i=0; l[i]==r[i]; i++) {
15*c9945492SAndroid Build Coastguard Worker 		int c = l[i];
16*c9945492SAndroid Build Coastguard Worker 		if (!c) return 0;
17*c9945492SAndroid Build Coastguard Worker 		if (!isdigit(c)) dp=i+1, z=1;
18*c9945492SAndroid Build Coastguard Worker 		else if (c!='0') z=0;
19*c9945492SAndroid Build Coastguard Worker 	}
20*c9945492SAndroid Build Coastguard Worker 
21*c9945492SAndroid Build Coastguard Worker 	if (l[dp]-'1'<9U && r[dp]-'1'<9U) {
22*c9945492SAndroid Build Coastguard Worker 		/* If we're looking at non-degenerate digit sequences starting
23*c9945492SAndroid Build Coastguard Worker 		 * with nonzero digits, longest digit string is greater. */
24*c9945492SAndroid Build Coastguard Worker 		for (j=i; isdigit(l[j]); j++)
25*c9945492SAndroid Build Coastguard Worker 			if (!isdigit(r[j])) return 1;
26*c9945492SAndroid Build Coastguard Worker 		if (isdigit(r[j])) return -1;
27*c9945492SAndroid Build Coastguard Worker 	} else if (z && dp<i && (isdigit(l[i]) || isdigit(r[i]))) {
28*c9945492SAndroid Build Coastguard Worker 		/* Otherwise, if common prefix of digit sequence is
29*c9945492SAndroid Build Coastguard Worker 		 * all zeros, digits order less than non-digits. */
30*c9945492SAndroid Build Coastguard Worker 		return (unsigned char)(l[i]-'0') - (unsigned char)(r[i]-'0');
31*c9945492SAndroid Build Coastguard Worker 	}
32*c9945492SAndroid Build Coastguard Worker 
33*c9945492SAndroid Build Coastguard Worker 	return l[i] - r[i];
34*c9945492SAndroid Build Coastguard Worker }
35