summaryrefslogtreecommitdiff
path: root/string/strverscmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'string/strverscmp.c')
-rw-r--r--string/strverscmp.c59
1 files changed, 31 insertions, 28 deletions
diff --git a/string/strverscmp.c b/string/strverscmp.c
index 2b7ebcb8a8..2e6c96a657 100644
--- a/string/strverscmp.c
+++ b/string/strverscmp.c
@@ -18,16 +18,15 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#include <stdint.h>
#include <string.h>
#include <ctype.h>
/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
fractionnal parts, S_Z: idem but with leading Zeroes only */
#define S_N 0x0
-#define S_I 0x3
-#define S_F 0x6
-#define S_Z 0x9
+#define S_I 0x4
+#define S_F 0x8
+#define S_Z 0xC
/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
#define CMP 2
@@ -46,49 +45,53 @@ __strverscmp (s1, s2)
{
const unsigned char *p1 = (const unsigned char *) s1;
const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+ int state;
+ int diff;
- /* Symbol(s) 0 [1-9] others
- Transition (10) 0 (01) d (00) x */
- static const uint8_t next_state[] =
+ /* Symbol(s) 0 [1-9] others (padding)
+ Transition (10) 0 (01) d (00) x (11) - */
+ static const unsigned int next_state[] =
{
- /* state x d 0 */
- /* S_N */ S_N, S_I, S_Z,
- /* S_I */ S_N, S_I, S_I,
- /* S_F */ S_N, S_F, S_F,
- /* S_Z */ S_N, S_F, S_Z
+ /* state x d 0 - */
+ /* S_N */ S_N, S_I, S_Z, S_N,
+ /* S_I */ S_N, S_I, S_I, S_I,
+ /* S_F */ S_N, S_F, S_F, S_F,
+ /* S_Z */ S_N, S_F, S_Z, S_Z
};
- static const int8_t result_type[] =
+ static const int result_type[] =
{
- /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
-
- /* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP,
- /* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN,
- /* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
- /* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP
+ /* state x/x x/d x/0 x/- d/x d/d d/0 d/-
+ 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */
+
+ /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_I */ CMP, -1, -1, CMP, +1, LEN, LEN, CMP,
+ +1, LEN, LEN, CMP, CMP, CMP, CMP, CMP,
+ /* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP,
+ -1, CMP, CMP, CMP
};
if (p1 == p2)
return 0;
- unsigned char c1 = *p1++;
- unsigned char c2 = *p2++;
+ c1 = *p1++;
+ c2 = *p2++;
/* Hint: '0' is a digit too. */
- int state = S_N | ((c1 == '0') + (isdigit (c1) != 0));
+ state = S_N | ((c1 == '0') + (isdigit (c1) != 0));
- int diff;
- while ((diff = c1 - c2) == 0)
+ while ((diff = c1 - c2) == 0 && c1 != '\0')
{
- if (c1 == '\0')
- return diff;
-
state = next_state[state];
c1 = *p1++;
c2 = *p2++;
state |= (c1 == '0') + (isdigit (c1) != 0);
}
- state = result_type[state * 3 | (((c2 == '0') + (isdigit (c2) != 0)))];
+ state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))];
switch (state)
{