xref: /freebsd/contrib/ntp/sntp/libpkgver/colcomp.c (revision 2008043f386721d58158e37e0d7e50df8095942d)
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
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 
94 static int  qcmp(   const void      *fi1,
95                     const void      *fi2)
96 {
97     return colcomp(*(char**)fi1, *(char**)fi2);
98 }
99 
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