xref: /netbsd-src/external/bsd/ntp/dist/sntp/libpkgver/colcomp.c (revision cdfa2a7ef92791ba9db70a584a1d904730e6fb46)
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