colcomp.c revision 290001
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
36int
37colcomp (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
94static int  qcmp(   const void      *fi1,
95                    const void      *fi2)
96{
97    return colcomp(*(char**)fi1, *(char**)fi2);
98}
99
100int 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