]> git.ipfire.org Git - thirdparty/glibc.git/blame - string/strverscmp.c
build-many-glibcs.py: Add openrisc hard float glibc variant
[thirdparty/glibc.git] / string / strverscmp.c
CommitLineData
1f205a47 1/* Compare strings while treating digits characters numerically.
dff8da6b 2 Copyright (C) 1997-2024 Free Software Foundation, Inc.
1f205a47 3 This file is part of the GNU C Library.
e6855a3b 4 Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
1f205a47
UD
5
6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
1f205a47
UD
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
1f205a47 15
41bdb6e2 16 You should have received a copy of the GNU Lesser General Public
59ba27a6 17 License along with the GNU C Library; if not, see
5a82c748 18 <https://www.gnu.org/licenses/>. */
1f205a47 19
45466462 20#include <stdint.h>
1f205a47
UD
21#include <string.h>
22#include <ctype.h>
23
24/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
bfbc5754 25 fractionnal parts, S_Z: idem but with leading Zeroes only */
1f205a47 26#define S_N 0x0
45466462
UD
27#define S_I 0x3
28#define S_F 0x6
29#define S_Z 0x9
1f205a47
UD
30
31/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
32#define CMP 2
33#define LEN 3
34
35
36/* Compare S1 and S2 as strings holding indices/version numbers,
37 returning less than, equal to or greater than zero if S1 is less than,
38 equal to or greater than S2 (for more info, see the texinfo doc).
39*/
40
41int
9d46370c 42__strverscmp (const char *s1, const char *s2)
1f205a47
UD
43{
44 const unsigned char *p1 = (const unsigned char *) s1;
45 const unsigned char *p2 = (const unsigned char *) s2;
1f205a47 46
45466462
UD
47 /* Symbol(s) 0 [1-9] others
48 Transition (10) 0 (01) d (00) x */
49 static const uint8_t next_state[] =
1f205a47 50 {
45466462
UD
51 /* state x d 0 */
52 /* S_N */ S_N, S_I, S_Z,
53 /* S_I */ S_N, S_I, S_I,
54 /* S_F */ S_N, S_F, S_F,
55 /* S_Z */ S_N, S_F, S_Z
1f205a47
UD
56 };
57
45466462 58 static const int8_t result_type[] =
1f205a47 59 {
45466462
UD
60 /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
61
62 /* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP,
63 /* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN,
64 /* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
65 /* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP
1f205a47
UD
66 };
67
68 if (p1 == p2)
69 return 0;
70
45466462
UD
71 unsigned char c1 = *p1++;
72 unsigned char c2 = *p2++;
1f205a47 73 /* Hint: '0' is a digit too. */
4bcb2658 74 int state = S_N + ((c1 == '0') + (isdigit (c1) != 0));
1f205a47 75
45466462
UD
76 int diff;
77 while ((diff = c1 - c2) == 0)
1f205a47 78 {
45466462
UD
79 if (c1 == '\0')
80 return diff;
81
1f205a47
UD
82 state = next_state[state];
83 c1 = *p1++;
84 c2 = *p2++;
4bcb2658 85 state += (c1 == '0') + (isdigit (c1) != 0);
1f205a47
UD
86 }
87
4bcb2658 88 state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))];
1f205a47
UD
89
90 switch (state)
91 {
92 case CMP:
93 return diff;
94
95 case LEN:
96 while (isdigit (*p1++))
97 if (!isdigit (*p2++))
98 return 1;
99
100 return isdigit (*p2) ? -1 : diff;
101
102 default:
103 return state;
104 }
105}
a20d8dbe 106libc_hidden_def (__strverscmp)
cbdee279 107weak_alias (__strverscmp, strverscmp)