alsa-lib/patches/002-versionsort.patch |
1 | | +++ alsa-lib-1.0.24.1/src/ucm/parser.c 2011-03-13 21:26:24.705183404 +0300 |
2 | | @@ -32,6 +32,9 @@ |
3 | | |
4 | | #include "ucm_local.h" |
5 | | #include <dirent.h> |
6 | | +#include <string.h> |
7 | | +#include <ctype.h> |
8 | | +#include <stdint.h> |
9 | | |
10 | | /** The name of the environment variable containing the UCM directory */ |
11 | | #define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM" |
12 | | @@ -40,6 +43,100 @@ |
13 | | struct list_head *base, |
14 | | snd_config_t *cfg); |
15 | | |
16 | | + /* states: S_N: normal, S_I: comparing integral part, S_F: comparing |
17 | | + fractional parts, S_Z: idem but with leading Zeroes only */ |
18 | | + #define S_N 0x0 |
19 | | + #define S_I 0x4 |
20 | | + #define S_F 0x8 |
21 | | + #define S_Z 0xC |
22 | | + |
23 | | + /* result_type: CMP: return diff; LEN: compare using len_diff/diff */ |
24 | | + #define CMP 2 |
25 | | + #define LEN 3 |
26 | | + |
27 | | + /* using more efficient isdigit() */ |
28 | | + #undef isdigit |
29 | | + #define isdigit(a) ((unsigned)((a) - '0') <= 9) |
30 | | + |
31 | | + /* Compare S1 and S2 as strings holding indices/version numbers, |
32 | | + returning less than, equal to or greater than zero if S1 is less than, |
33 | | + equal to or greater than S2 (for more info, see the texinfo doc). |
34 | | + */ |
35 | | + int strverscmp (const char *s1, const char *s2) |
36 | | + { |
37 | | + const unsigned char *p1 = (const unsigned char *) s1; |
38 | | + const unsigned char *p2 = (const unsigned char *) s2; |
39 | | + unsigned char c1, c2; |
40 | | + int state; |
41 | | + int diff; |
42 | | + |
43 | | + /* Symbol(s) 0 [1-9] others (padding) |
44 | | + Transition (10) 0 (01) d (00) x (11) - */ |
45 | | + static const uint8_t next_state[] = |
46 | | + { |
47 | | + /* state x d 0 - */ |
48 | | + /* S_N */ S_N, S_I, S_Z, S_N, |
49 | | + /* S_I */ S_N, S_I, S_I, S_I, |
50 | | + /* S_F */ S_N, S_F, S_F, S_F, |
51 | | + /* S_Z */ S_N, S_F, S_Z, S_Z |
52 | | + }; |
53 | | + |
54 | | + static const int8_t result_type[] = |
55 | | + { |
56 | | + /* state x/x x/d x/0 x/- d/x d/d d/0 d/- |
57 | | + 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */ |
58 | | + |
59 | | + /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, |
60 | | + CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, |
61 | | + /* S_I */ CMP, -1, -1, CMP, +1, LEN, LEN, CMP, |
62 | | + +1, LEN, LEN, CMP, CMP, CMP, CMP, CMP, |
63 | | + /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, |
64 | | + CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, |
65 | | + /* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP, |
66 | | + -1, CMP, CMP, CMP |
67 | | + }; |
68 | | + |
69 | | + if (p1 == p2) |
70 | | + return 0; |
71 | | + |
72 | | + c1 = *p1++; |
73 | | + c2 = *p2++; |
74 | | + /* Hint: '0' is a digit too. */ |
75 | | + state = S_N | ((c1 == '0') + (isdigit (c1) != 0)); |
76 | | + |
77 | | + while ((diff = c1 - c2) == 0 && c1 != '\0') |
78 | | + { |
79 | | + state = next_state[state]; |
80 | | + c1 = *p1++; |
81 | | + c2 = *p2++; |
82 | | + state |= (c1 == '0') + (isdigit (c1) != 0); |
83 | | + } |
84 | | + |
85 | | + state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))]; |
86 | | + |
87 | | + switch (state) |
88 | | + { |
89 | | + case CMP: |
90 | | + return diff; |
91 | | + |
92 | | + case LEN: |
93 | | + while (isdigit (*p1++)) |
94 | | + if (!isdigit (*p2++)) |
95 | | + return 1; |
96 | | + |
97 | | + return isdigit (*p2) ? -1 : diff; |
98 | | + |
99 | | + default: |
100 | | + return state; |
101 | | + } |
102 | | + } |
103 | | + |
104 | | +int versionsort(const void *a, const void *b) |
105 | | +{ |
106 | | + return strverscmp((*(const struct dirent **) a)->d_name, |
107 | | + (*(const struct dirent **) b)->d_name); |
108 | | +} |
109 | | + |
110 | | /* |
111 | | * Parse string |
112 | | */ |