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