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