colcomp.c revision 1.1.1.4
1/*	$NetBSD: colcomp.c,v 1.1.1.4 2016/01/08 21:21:33 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
38int
39colcomp (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
96static int  qcmp(   const void      *fi1,
97                    const void      *fi2)
98{
99    return colcomp(*(char**)fi1, *(char**)fi2);
100}
101
102int 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