1*276da39aSCy Schubert /* COLLATE COMPARE, COMPARES DIGITS NUMERICALLY AND OTHERS IN ASCII */ 2*276da39aSCy Schubert 3*276da39aSCy Schubert /* 4*276da39aSCy Schubert * Copyright 2001, 2015, Harlan Stenn. Used by NTP with permission. 5*276da39aSCy Schubert * 6*276da39aSCy Schubert * Author: Harlan Stenn <harlan@pfcs.com> 7*276da39aSCy Schubert * 8*276da39aSCy Schubert * Copying and distribution of this file, with or without modification, 9*276da39aSCy Schubert * are permitted in any medium without royalty provided the copyright 10*276da39aSCy Schubert * notice and this notice are preserved. This file is offered as-is, 11*276da39aSCy Schubert * without any warranty. 12*276da39aSCy Schubert */ 13*276da39aSCy Schubert 14*276da39aSCy Schubert /* 15*276da39aSCy Schubert * Expected collate order for numeric "pieces" is: 16*276da39aSCy Schubert * 0 - 9 followed by 17*276da39aSCy Schubert * 00 - 99 followed by 18*276da39aSCy Schubert * 000 - 999 followed by 19*276da39aSCy Schubert * ... 20*276da39aSCy Schubert */ 21*276da39aSCy Schubert 22*276da39aSCy Schubert #include <ctype.h> 23*276da39aSCy Schubert 24*276da39aSCy Schubert /* 25*276da39aSCy Schubert * Older versions of isdigit() require the argument be isascii() 26*276da39aSCy Schubert */ 27*276da39aSCy Schubert 28*276da39aSCy Schubert #if 0 29*276da39aSCy Schubert # define MyIsDigit(x) \ 30*276da39aSCy Schubert (isascii ((unsigned char) (x)) && isdigit ((unsigned char) (x))) 31*276da39aSCy Schubert #else 32*276da39aSCy Schubert # define MyIsDigit(x) isdigit ((unsigned char) (x)) 33*276da39aSCy Schubert #endif 34*276da39aSCy Schubert 35*276da39aSCy Schubert 36*276da39aSCy Schubert int 37*276da39aSCy Schubert colcomp (s1, s2) 38*276da39aSCy Schubert register char *s1; 39*276da39aSCy Schubert register char *s2; 40*276da39aSCy Schubert { 41*276da39aSCy Schubert int hilo = 0; /* comparison value */ 42*276da39aSCy Schubert 43*276da39aSCy Schubert while (*s1 && *s2) 44*276da39aSCy Schubert { 45*276da39aSCy Schubert if ( MyIsDigit(*s1) 46*276da39aSCy Schubert && MyIsDigit(*s2)) 47*276da39aSCy Schubert { 48*276da39aSCy Schubert hilo = (*s1 < *s2) ? -1 : (*s1 > *s2) ? 1 : 0; 49*276da39aSCy Schubert ++s1; 50*276da39aSCy Schubert ++s2; 51*276da39aSCy Schubert while (MyIsDigit(*s1) 52*276da39aSCy Schubert && MyIsDigit(*s2)) 53*276da39aSCy Schubert { 54*276da39aSCy Schubert if (!hilo) 55*276da39aSCy Schubert hilo = (*s1 < *s2) ? -1 : (*s1 > *s2) ? 1 : 0; 56*276da39aSCy Schubert ++s1; 57*276da39aSCy Schubert ++s2; 58*276da39aSCy Schubert } 59*276da39aSCy Schubert if (MyIsDigit(*s1)) 60*276da39aSCy Schubert hilo = 1; /* s2 is first */ 61*276da39aSCy Schubert if (MyIsDigit(*s2)) 62*276da39aSCy Schubert hilo = -1; /* s1 is first */ 63*276da39aSCy Schubert if (hilo) 64*276da39aSCy Schubert break; 65*276da39aSCy Schubert continue; 66*276da39aSCy Schubert } 67*276da39aSCy Schubert if (MyIsDigit(*s1)) 68*276da39aSCy Schubert { 69*276da39aSCy Schubert hilo = -1; /* s1 must come first */ 70*276da39aSCy Schubert break; 71*276da39aSCy Schubert } 72*276da39aSCy Schubert if (MyIsDigit(*s2)) 73*276da39aSCy Schubert { 74*276da39aSCy Schubert hilo = 1; /* s2 must come first */ 75*276da39aSCy Schubert break; 76*276da39aSCy Schubert } 77*276da39aSCy Schubert hilo = (*s1 < *s2) ? -1 : (*s1 > *s2) ? 1 : 0; 78*276da39aSCy Schubert if (hilo) 79*276da39aSCy Schubert break; 80*276da39aSCy Schubert ++s1; 81*276da39aSCy Schubert ++s2; 82*276da39aSCy Schubert } 83*276da39aSCy Schubert if (*s1 && *s2) 84*276da39aSCy Schubert return (hilo); 85*276da39aSCy Schubert if (hilo) 86*276da39aSCy Schubert return (hilo); 87*276da39aSCy Schubert return ((*s1 < *s2) ? -1 : (*s1 > *s2) ? 1 : 0); 88*276da39aSCy Schubert } 89*276da39aSCy Schubert 90*276da39aSCy Schubert #ifdef TEST 91*276da39aSCy Schubert 92*276da39aSCy Schubert #include <stdlib.h> 93*276da39aSCy Schubert 94*276da39aSCy Schubert static int qcmp( const void *fi1, 95*276da39aSCy Schubert const void *fi2) 96*276da39aSCy Schubert { 97*276da39aSCy Schubert return colcomp(*(char**)fi1, *(char**)fi2); 98*276da39aSCy Schubert } 99*276da39aSCy Schubert 100*276da39aSCy Schubert int main( int argc, char *argv[], char *environ[]) { 101*276da39aSCy Schubert void *base; 102*276da39aSCy Schubert size_t nmemb = 0; 103*276da39aSCy Schubert size_t size = sizeof(char *); 104*276da39aSCy Schubert char *ca[] = { 105*276da39aSCy Schubert "999", "0", "10", "1", "01", "100", "010", "99", "00", "001", "099", "9" 106*276da39aSCy Schubert }; 107*276da39aSCy Schubert char **cp; 108*276da39aSCy Schubert int i; 109*276da39aSCy Schubert 110*276da39aSCy Schubert if (argc > 1) { 111*276da39aSCy Schubert /* Sort use-provided list */ 112*276da39aSCy Schubert } else { 113*276da39aSCy Schubert base = (void *) ca; 114*276da39aSCy Schubert nmemb = sizeof ca / size; 115*276da39aSCy Schubert } 116*276da39aSCy Schubert printf("argc is <%d>, nmemb = <%d>\n", argc, nmemb); 117*276da39aSCy Schubert 118*276da39aSCy Schubert printf("Before:\n"); 119*276da39aSCy Schubert cp = (char **)base; 120*276da39aSCy Schubert for (i = 0; i < nmemb; ++i) { 121*276da39aSCy Schubert printf("%s\n", *cp++); 122*276da39aSCy Schubert } 123*276da39aSCy Schubert 124*276da39aSCy Schubert qsort((void *)base, nmemb, size, qcmp); 125*276da39aSCy Schubert 126*276da39aSCy Schubert printf("After:\n"); 127*276da39aSCy Schubert cp = (char **)base; 128*276da39aSCy Schubert for (i = 0; i < nmemb; ++i) { 129*276da39aSCy Schubert printf("%s\n", *cp++); 130*276da39aSCy Schubert } 131*276da39aSCy Schubert 132*276da39aSCy Schubert exit(0); 133*276da39aSCy Schubert } 134*276da39aSCy Schubert 135*276da39aSCy Schubert #endif 136