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