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