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