1*276da39aSCy Schubert /* COLLATE COMPARE, COMPARES DIGITS NUMERICALLY AND OTHERS IN ASCII */
2*276da39aSCy Schubert
3*276da39aSCy Schubert /*
4*276da39aSCy Schubert * Copyright 2001, 2015, Harlan Stenn. Used by NTP with permission.
5*276da39aSCy Schubert *
6*276da39aSCy Schubert * Author: Harlan Stenn <harlan@pfcs.com>
7*276da39aSCy Schubert *
8*276da39aSCy Schubert * Copying and distribution of this file, with or without modification,
9*276da39aSCy Schubert * are permitted in any medium without royalty provided the copyright
10*276da39aSCy Schubert * notice and this notice are preserved. This file is offered as-is,
11*276da39aSCy Schubert * without any warranty.
12*276da39aSCy Schubert */
13*276da39aSCy Schubert
14*276da39aSCy Schubert /*
15*276da39aSCy Schubert * Expected collate order for numeric "pieces" is:
16*276da39aSCy Schubert * 0 - 9 followed by
17*276da39aSCy Schubert * 00 - 99 followed by
18*276da39aSCy Schubert * 000 - 999 followed by
19*276da39aSCy Schubert * ...
20*276da39aSCy Schubert */
21*276da39aSCy Schubert
22*276da39aSCy Schubert #include <ctype.h>
23*276da39aSCy Schubert
24*276da39aSCy Schubert /*
25*276da39aSCy Schubert * Older versions of isdigit() require the argument be isascii()
26*276da39aSCy Schubert */
27*276da39aSCy Schubert
28*276da39aSCy Schubert #if 0
29*276da39aSCy Schubert # define MyIsDigit(x) \
30*276da39aSCy Schubert (isascii ((unsigned char) (x)) && isdigit ((unsigned char) (x)))
31*276da39aSCy Schubert #else
32*276da39aSCy Schubert # define MyIsDigit(x) isdigit ((unsigned char) (x))
33*276da39aSCy Schubert #endif
34*276da39aSCy Schubert
35*276da39aSCy Schubert
36*276da39aSCy Schubert int
colcomp(s1,s2)37*276da39aSCy Schubert colcomp (s1, s2)
38*276da39aSCy Schubert register char *s1;
39*276da39aSCy Schubert register char *s2;
40*276da39aSCy Schubert {
41*276da39aSCy Schubert int hilo = 0; /* comparison value */
42*276da39aSCy Schubert
43*276da39aSCy Schubert while (*s1 && *s2)
44*276da39aSCy Schubert {
45*276da39aSCy Schubert if ( MyIsDigit(*s1)
46*276da39aSCy Schubert && MyIsDigit(*s2))
47*276da39aSCy Schubert {
48*276da39aSCy Schubert hilo = (*s1 < *s2) ? -1 : (*s1 > *s2) ? 1 : 0;
49*276da39aSCy Schubert ++s1;
50*276da39aSCy Schubert ++s2;
51*276da39aSCy Schubert while (MyIsDigit(*s1)
52*276da39aSCy Schubert && MyIsDigit(*s2))
53*276da39aSCy Schubert {
54*276da39aSCy Schubert if (!hilo)
55*276da39aSCy Schubert hilo = (*s1 < *s2) ? -1 : (*s1 > *s2) ? 1 : 0;
56*276da39aSCy Schubert ++s1;
57*276da39aSCy Schubert ++s2;
58*276da39aSCy Schubert }
59*276da39aSCy Schubert if (MyIsDigit(*s1))
60*276da39aSCy Schubert hilo = 1; /* s2 is first */
61*276da39aSCy Schubert if (MyIsDigit(*s2))
62*276da39aSCy Schubert hilo = -1; /* s1 is first */
63*276da39aSCy Schubert if (hilo)
64*276da39aSCy Schubert break;
65*276da39aSCy Schubert continue;
66*276da39aSCy Schubert }
67*276da39aSCy Schubert if (MyIsDigit(*s1))
68*276da39aSCy Schubert {
69*276da39aSCy Schubert hilo = -1; /* s1 must come first */
70*276da39aSCy Schubert break;
71*276da39aSCy Schubert }
72*276da39aSCy Schubert if (MyIsDigit(*s2))
73*276da39aSCy Schubert {
74*276da39aSCy Schubert hilo = 1; /* s2 must come first */
75*276da39aSCy Schubert break;
76*276da39aSCy Schubert }
77*276da39aSCy Schubert hilo = (*s1 < *s2) ? -1 : (*s1 > *s2) ? 1 : 0;
78*276da39aSCy Schubert if (hilo)
79*276da39aSCy Schubert break;
80*276da39aSCy Schubert ++s1;
81*276da39aSCy Schubert ++s2;
82*276da39aSCy Schubert }
83*276da39aSCy Schubert if (*s1 && *s2)
84*276da39aSCy Schubert return (hilo);
85*276da39aSCy Schubert if (hilo)
86*276da39aSCy Schubert return (hilo);
87*276da39aSCy Schubert return ((*s1 < *s2) ? -1 : (*s1 > *s2) ? 1 : 0);
88*276da39aSCy Schubert }
89*276da39aSCy Schubert
90*276da39aSCy Schubert #ifdef TEST
91*276da39aSCy Schubert
92*276da39aSCy Schubert #include <stdlib.h>
93*276da39aSCy Schubert
qcmp(const void * fi1,const void * fi2)94*276da39aSCy Schubert static int qcmp( const void *fi1,
95*276da39aSCy Schubert const void *fi2)
96*276da39aSCy Schubert {
97*276da39aSCy Schubert return colcomp(*(char**)fi1, *(char**)fi2);
98*276da39aSCy Schubert }
99*276da39aSCy Schubert
main(int argc,char * argv[],char * environ[])100*276da39aSCy Schubert int main( int argc, char *argv[], char *environ[]) {
101*276da39aSCy Schubert void *base;
102*276da39aSCy Schubert size_t nmemb = 0;
103*276da39aSCy Schubert size_t size = sizeof(char *);
104*276da39aSCy Schubert char *ca[] = {
105*276da39aSCy Schubert "999", "0", "10", "1", "01", "100", "010", "99", "00", "001", "099", "9"
106*276da39aSCy Schubert };
107*276da39aSCy Schubert char **cp;
108*276da39aSCy Schubert int i;
109*276da39aSCy Schubert
110*276da39aSCy Schubert if (argc > 1) {
111*276da39aSCy Schubert /* Sort use-provided list */
112*276da39aSCy Schubert } else {
113*276da39aSCy Schubert base = (void *) ca;
114*276da39aSCy Schubert nmemb = sizeof ca / size;
115*276da39aSCy Schubert }
116*276da39aSCy Schubert printf("argc is <%d>, nmemb = <%d>\n", argc, nmemb);
117*276da39aSCy Schubert
118*276da39aSCy Schubert printf("Before:\n");
119*276da39aSCy Schubert cp = (char **)base;
120*276da39aSCy Schubert for (i = 0; i < nmemb; ++i) {
121*276da39aSCy Schubert printf("%s\n", *cp++);
122*276da39aSCy Schubert }
123*276da39aSCy Schubert
124*276da39aSCy Schubert qsort((void *)base, nmemb, size, qcmp);
125*276da39aSCy Schubert
126*276da39aSCy Schubert printf("After:\n");
127*276da39aSCy Schubert cp = (char **)base;
128*276da39aSCy Schubert for (i = 0; i < nmemb; ++i) {
129*276da39aSCy Schubert printf("%s\n", *cp++);
130*276da39aSCy Schubert }
131*276da39aSCy Schubert
132*276da39aSCy Schubert exit(0);
133*276da39aSCy Schubert }
134*276da39aSCy Schubert
135*276da39aSCy Schubert #endif
136