1 /* -*- buffer-read-only: t -*- vi: set ro: */ 2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */ 3 /* Compare strings while treating digits characters numerically. 4 Copyright (C) 1997, 2000, 2002, 2004, 2006 Free Software Foundation, Inc. 5 This file is part of the GNU C Library. 6 Contributed by Jean-Franois Bignolles <bignolle (at) ecoledoc.ibp.fr>, 1997. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3, or (at your option) 11 any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License along 19 with this program; if not, write to the Free Software Foundation, 20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 21 22 #if !_LIBC 23 # include <config.h> 24 #endif 25 26 #include <string.h> 27 #include <ctype.h> 28 29 /* states: S_N: normal, S_I: comparing integral part, S_F: comparing 30 fractional parts, S_Z: idem but with leading Zeroes only */ 31 #define S_N 0x0 32 #define S_I 0x4 33 #define S_F 0x8 34 #define S_Z 0xC 35 36 /* result_type: CMP: return diff; LEN: compare using len_diff/diff */ 37 #define CMP 2 38 #define LEN 3 39 40 41 /* ISDIGIT differs from isdigit, as follows: 42 - Its arg may be any int or unsigned int; it need not be an unsigned char 43 or EOF. 44 - It's typically faster. 45 POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to 46 isdigit unless it's important to use the locale's definition 47 of `digit' even when the host does not conform to POSIX. */ 48 #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) 49 50 #undef __strverscmp 51 #undef strverscmp 52 53 #ifndef weak_alias 54 # define __strverscmp strverscmp 55 #endif 56 57 /* Compare S1 and S2 as strings holding indices/version numbers, 58 returning less than, equal to or greater than zero if S1 is less than, 59 equal to or greater than S2 (for more info, see the texinfo doc). 60 */ 61 62 int 63 __strverscmp (const char *s1, const char *s2) 64 { 65 const unsigned char *p1 = (const unsigned char *) s1; 66 const unsigned char *p2 = (const unsigned char *) s2; 67 unsigned char c1, c2; 68 int state; 69 int diff; 70 71 /* Symbol(s) 0 [1-9] others (padding) 72 Transition (10) 0 (01) d (00) x (11) - */ 73 static const unsigned int next_state[] = 74 { 75 /* state x d 0 - */ 76 /* S_N */ S_N, S_I, S_Z, S_N, 77 /* S_I */ S_N, S_I, S_I, S_I, 78 /* S_F */ S_N, S_F, S_F, S_F, 79 /* S_Z */ S_N, S_F, S_Z, S_Z 80 }; 81 82 static const int result_type[] = 83 { 84 /* state x/x x/d x/0 x/- d/x d/d d/0 d/- 85 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */ 86 87 /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, 88 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, 89 /* S_I */ CMP, -1, -1, CMP, 1, LEN, LEN, CMP, 90 1, LEN, LEN, CMP, CMP, CMP, CMP, CMP, 91 /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, 92 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, 93 /* S_Z */ CMP, 1, 1, CMP, -1, CMP, CMP, CMP, 94 -1, CMP, CMP, CMP 95 }; 96 97 if (p1 == p2) 98 return 0; 99 100 c1 = *p1++; 101 c2 = *p2++; 102 /* Hint: '0' is a digit too. */ 103 state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0)); 104 105 while ((diff = c1 - c2) == 0 && c1 != '\0') 106 { 107 state = next_state[state]; 108 c1 = *p1++; 109 c2 = *p2++; 110 state |= (c1 == '0') + (ISDIGIT (c1) != 0); 111 } 112 113 state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))]; 114 115 switch (state) 116 { 117 case CMP: 118 return diff; 119 120 case LEN: 121 while (ISDIGIT (*p1++)) 122 if (!ISDIGIT (*p2++)) 123 return 1; 124 125 return ISDIGIT (*p2) ? -1 : diff; 126 127 default: 128 return state; 129 } 130 } 131 #ifdef weak_alias 132 weak_alias (__strverscmp, strverscmp) 133 #endif 134