chiark / gitweb /
Initial push
[termux-packages] / packages / procps / strverscmp.c.patch
1 diff -N -u -r ../procps-ng-3.3.9/top/strverscmp.c ./top/strverscmp.c
2 --- ../procps-ng-3.3.9/top/strverscmp.c 1970-01-01 01:00:00.000000000 +0100
3 +++ ./top/strverscmp.c  2014-07-06 07:26:13.650946884 +0200
4 @@ -0,0 +1,156 @@
5 +/* Compare strings while treating digits characters numerically.\r
6 +   Copyright (C) 1997, 2002, 2005 Free Software Foundation, Inc.\r
7 +   This file is part of the libiberty library.\r
8 +   Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.\r
9 +\r
10 +   Libiberty is free software; you can redistribute it and/or\r
11 +   modify it under the terms of the GNU Lesser General Public\r
12 +   License as published by the Free Software Foundation; either\r
13 +   version 2.1 of the License, or (at your option) any later version.\r
14 +\r
15 +   Libiberty is distributed in the hope that it will be useful,\r
16 +   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
17 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
18 +   Lesser General Public License for more details.\r
19 +\r
20 +   You should have received a copy of the GNU Lesser General Public\r
21 +   License along with the GNU C Library; if not, write to the Free\r
22 +   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\r
23 +   02110-1301 USA.  */\r
24 +\r
25 +#include <ctype.h>\r
26 +\r
27 +/*\r
28 +@deftypefun int strverscmp (const char *@var{s1}, const char *@var{s2})\r
29 +The @code{strverscmp} function compares the string @var{s1} against\r
30 +@var{s2}, considering them as holding indices/version numbers.  Return\r
31 +value follows the same conventions as found in the @code{strverscmp}\r
32 +function.  In fact, if @var{s1} and @var{s2} contain no digits,\r
33 +@code{strverscmp} behaves like @code{strcmp}.\r
34 +\r
35 +Basically, we compare strings normally (character by character), until\r
36 +we find a digit in each string - then we enter a special comparison\r
37 +mode, where each sequence of digits is taken as a whole.  If we reach the\r
38 +end of these two parts without noticing a difference, we return to the\r
39 +standard comparison mode.  There are two types of numeric parts:\r
40 +"integral" and "fractional" (those  begin with a '0'). The types\r
41 +of the numeric parts affect the way we sort them:\r
42 +\r
43 +@itemize @bullet\r
44 +@item\r
45 +integral/integral: we compare values as you would expect.\r
46 +\r
47 +@item\r
48 +fractional/integral: the fractional part is less than the integral one.\r
49 +Again, no surprise.\r
50 +\r
51 +@item\r
52 +fractional/fractional: the things become a bit more complex.\r
53 +If the common prefix contains only leading zeroes, the longest part is less\r
54 +than the other one; else the comparison behaves normally.\r
55 +@end itemize\r
56 +\r
57 +@smallexample\r
58 +strverscmp ("no digit", "no digit")\r
59 +    @result{} 0    // @r{same behavior as strcmp.}\r
60 +strverscmp ("item#99", "item#100")\r
61 +    @result{} <0   // @r{same prefix, but 99 < 100.}\r
62 +strverscmp ("alpha1", "alpha001")\r
63 +    @result{} >0   // @r{fractional part inferior to integral one.}\r
64 +strverscmp ("part1_f012", "part1_f01")\r
65 +    @result{} >0   // @r{two fractional parts.}\r
66 +strverscmp ("foo.009", "foo.0")\r
67 +    @result{} <0   // @r{idem, but with leading zeroes only.}\r
68 +@end smallexample\r
69 +\r
70 +This function is especially useful when dealing with filename sorting,\r
71 +because filenames frequently hold indices/version numbers.\r
72 +@end deftypefun\r
73 +\r
74 +*/\r
75 +\r
76 +/* states: S_N: normal, S_I: comparing integral part, S_F: comparing\r
77 +           fractional parts, S_Z: idem but with leading Zeroes only */\r
78 +#define  S_N    0x0\r
79 +#define  S_I    0x4\r
80 +#define  S_F    0x8\r
81 +#define  S_Z    0xC\r
82 +\r
83 +/* result_type: CMP: return diff; LEN: compare using len_diff/diff */\r
84 +#define  CMP    2\r
85 +#define  LEN    3\r
86 +\r
87 +\r
88 +/* Compare S1 and S2 as strings holding indices/version numbers,\r
89 +   returning less than, equal to or greater than zero if S1 is less than,\r
90 +   equal to or greater than S2 (for more info, see the Glibc texinfo doc).  */\r
91 +\r
92 +int\r
93 +strverscmp (const char *s1, const char *s2)\r
94 +{\r
95 +  const unsigned char *p1 = (const unsigned char *) s1;\r
96 +  const unsigned char *p2 = (const unsigned char *) s2;\r
97 +  unsigned char c1, c2;\r
98 +  int state;\r
99 +  int diff;\r
100 +\r
101 +  /* Symbol(s)    0       [1-9]   others  (padding)\r
102 +     Transition   (10) 0  (01) d  (00) x  (11) -   */\r
103 +  static const unsigned int next_state[] =\r
104 +    {\r
105 +      /* state    x    d    0    - */\r
106 +      /* S_N */  S_N, S_I, S_Z, S_N,\r
107 +      /* S_I */  S_N, S_I, S_I, S_I,\r
108 +      /* S_F */  S_N, S_F, S_F, S_F,\r
109 +      /* S_Z */  S_N, S_F, S_Z, S_Z\r
110 +    };\r
111 +\r
112 +  static const int result_type[] =\r
113 +    {\r
114 +      /* state   x/x  x/d  x/0  x/-  d/x  d/d  d/0  d/-\r
115 +                 0/x  0/d  0/0  0/-  -/x  -/d  -/0  -/- */\r
116 +\r
117 +      /* S_N */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,\r
118 +                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,\r
119 +      /* S_I */  CMP, -1,  -1,  CMP, +1,  LEN, LEN, CMP,\r
120 +                 +1,  LEN, LEN, CMP, CMP, CMP, CMP, CMP,\r
121 +      /* S_F */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,\r
122 +                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,\r
123 +      /* S_Z */  CMP, +1,  +1,  CMP, -1,  CMP, CMP, CMP,\r
124 +                 -1,  CMP, CMP, CMP\r
125 +    };\r
126 +\r
127 +  if (p1 == p2)\r
128 +    return 0;\r
129 +\r
130 +  c1 = *p1++;\r
131 +  c2 = *p2++;\r
132 +  /* Hint: '0' is a digit too.  */\r
133 +  state = S_N | ((c1 == '0') + (isdigit (c1) != 0));\r
134 +\r
135 +  while ((diff = c1 - c2) == 0 && c1 != '\0')\r
136 +    {\r
137 +      state = next_state[state];\r
138 +      c1 = *p1++;\r
139 +      c2 = *p2++;\r
140 +      state |= (c1 == '0') + (isdigit (c1) != 0);\r
141 +    }\r
142 +\r
143 +  state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))];\r
144 +\r
145 +  switch (state)\r
146 +    {\r
147 +    case CMP:\r
148 +      return diff;\r
149 +\r
150 +    case LEN:\r
151 +      while (isdigit (*p1++))\r
152 +        if (!isdigit (*p2++))\r
153 +          return 1;\r
154 +\r
155 +      return isdigit (*p2) ? -1 : diff;\r
156 +\r
157 +    default:\r
158 +      return state;\r
159 +    }\r
160 +}\r