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