Skip to content

Commit

Permalink
[BZ #9913]
Browse files Browse the repository at this point in the history
	* string/strverscmp.c (__strverscmp): Fix case of different digits
	in fractional part of string.
	Patch by Jingyu Liu <jyliu@fortinet.com>.
	* string/Makefile (tests): Add tst-svc2.
	* string/tst-svc2.c: New file.

	* string/strverscmp.c (__strverscmp): Optimize size of tables.
  • Loading branch information
Ulrich Drepper committed Mar 14, 2009
1 parent 878b72c commit 4546646
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 34 deletions.
9 changes: 9 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
2009-03-14 Ulrich Drepper <drepper@redhat.com>

[BZ #9913]
* string/strverscmp.c (__strverscmp): Fix case of different digits
in fractional part of string.
Patch by Jingyu Liu <jyliu@fortinet.com>.
* string/Makefile (tests): Add tst-svc2.
* string/tst-svc2.c: New file.

* string/strverscmp.c (__strverscmp): Optimize size of tables.

* locale/iso-639.def: Add Min Nan.

2009-03-11 Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>
Expand Down
4 changes: 2 additions & 2 deletions string/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 1991-2002, 2005-2007, 2008 Free Software Foundation, Inc.
# Copyright (C) 1991-2002, 2005-2008, 2009 Free Software Foundation, Inc.
# This file is part of the GNU C Library.

# The GNU C Library is free software; you can redistribute it and/or
Expand Down Expand Up @@ -54,7 +54,7 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \
bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \
tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \
bug-strtok1 $(addprefix test-,$(strop-tests)) \
bug-envz1 tst-strxfrm2 tst-endian
bug-envz1 tst-strxfrm2 tst-endian tst-svc2
distribute := memcopy.h pagecopy.h tst-svc.expect test-string.h \
str-two-way.h

Expand Down
61 changes: 29 additions & 32 deletions string/strverscmp.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Compare strings while treating digits characters numerically.
Copyright (C) 1997, 2002 Free Software Foundation, Inc.
Copyright (C) 1997, 2002, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
Expand All @@ -18,15 +18,16 @@
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 0x4
#define S_F 0x8
#define S_Z 0xC
#define S_I 0x3
#define S_F 0x6
#define S_Z 0x9

/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
#define CMP 2
Expand All @@ -45,53 +46,49 @@ __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 (padding)
Transition (10) 0 (01) d (00) x (11) - */
static const unsigned int next_state[] =
/* Symbol(s) 0 [1-9] others
Transition (10) 0 (01) d (00) x */
static const uint8_t next_state[] =
{
/* 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
/* 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
};

static const int result_type[] =
static const int8_t result_type[] =
{
/* 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, LEN, CMP, CMP,
CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
/* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP,
-1, CMP, CMP, CMP
/* 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
};

if (p1 == p2)
return 0;

c1 = *p1++;
c2 = *p2++;
unsigned char c1 = *p1++;
unsigned char c2 = *p2++;
/* Hint: '0' is a digit too. */
state = S_N | ((c1 == '0') + (isdigit (c1) != 0));
int state = S_N | ((c1 == '0') + (isdigit (c1) != 0));

while ((diff = c1 - c2) == 0 && c1 != '\0')
int diff;
while ((diff = c1 - c2) == 0)
{
if (c1 == '\0')
return diff;

state = next_state[state];
c1 = *p1++;
c2 = *p2++;
state |= (c1 == '0') + (isdigit (c1) != 0);
}

state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))];
state = result_type[state * 3 | (((c2 == '0') + (isdigit (c2) != 0)))];

switch (state)
{
Expand Down

0 comments on commit 4546646

Please sign in to comment.