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