Root/
1 | #include "util.h" |
2 | #include "string.h" |
3 | |
4 | #define K 1024LL |
5 | /* |
6 | * perf_atoll() |
7 | * Parse (\d+)(b|B|kb|KB|mb|MB|gb|GB|tb|TB) (e.g. "256MB") |
8 | * and return its numeric value |
9 | */ |
10 | s64 perf_atoll(const char *str) |
11 | { |
12 | unsigned int i; |
13 | s64 length = -1, unit = 1; |
14 | |
15 | if (!isdigit(str[0])) |
16 | goto out_err; |
17 | |
18 | for (i = 1; i < strlen(str); i++) { |
19 | switch (str[i]) { |
20 | case 'B': |
21 | case 'b': |
22 | break; |
23 | case 'K': |
24 | if (str[i + 1] != 'B') |
25 | goto out_err; |
26 | else |
27 | goto kilo; |
28 | case 'k': |
29 | if (str[i + 1] != 'b') |
30 | goto out_err; |
31 | kilo: |
32 | unit = K; |
33 | break; |
34 | case 'M': |
35 | if (str[i + 1] != 'B') |
36 | goto out_err; |
37 | else |
38 | goto mega; |
39 | case 'm': |
40 | if (str[i + 1] != 'b') |
41 | goto out_err; |
42 | mega: |
43 | unit = K * K; |
44 | break; |
45 | case 'G': |
46 | if (str[i + 1] != 'B') |
47 | goto out_err; |
48 | else |
49 | goto giga; |
50 | case 'g': |
51 | if (str[i + 1] != 'b') |
52 | goto out_err; |
53 | giga: |
54 | unit = K * K * K; |
55 | break; |
56 | case 'T': |
57 | if (str[i + 1] != 'B') |
58 | goto out_err; |
59 | else |
60 | goto tera; |
61 | case 't': |
62 | if (str[i + 1] != 'b') |
63 | goto out_err; |
64 | tera: |
65 | unit = K * K * K * K; |
66 | break; |
67 | case '\0': /* only specified figures */ |
68 | unit = 1; |
69 | break; |
70 | default: |
71 | if (!isdigit(str[i])) |
72 | goto out_err; |
73 | break; |
74 | } |
75 | } |
76 | |
77 | length = atoll(str) * unit; |
78 | goto out; |
79 | |
80 | out_err: |
81 | length = -1; |
82 | out: |
83 | return length; |
84 | } |
85 | |
86 | /* |
87 | * Helper function for splitting a string into an argv-like array. |
88 | * originally copied from lib/argv_split.c |
89 | */ |
90 | static const char *skip_sep(const char *cp) |
91 | { |
92 | while (*cp && isspace(*cp)) |
93 | cp++; |
94 | |
95 | return cp; |
96 | } |
97 | |
98 | static const char *skip_arg(const char *cp) |
99 | { |
100 | while (*cp && !isspace(*cp)) |
101 | cp++; |
102 | |
103 | return cp; |
104 | } |
105 | |
106 | static int count_argc(const char *str) |
107 | { |
108 | int count = 0; |
109 | |
110 | while (*str) { |
111 | str = skip_sep(str); |
112 | if (*str) { |
113 | count++; |
114 | str = skip_arg(str); |
115 | } |
116 | } |
117 | |
118 | return count; |
119 | } |
120 | |
121 | /** |
122 | * argv_free - free an argv |
123 | * @argv - the argument vector to be freed |
124 | * |
125 | * Frees an argv and the strings it points to. |
126 | */ |
127 | void argv_free(char **argv) |
128 | { |
129 | char **p; |
130 | for (p = argv; *p; p++) |
131 | free(*p); |
132 | |
133 | free(argv); |
134 | } |
135 | |
136 | /** |
137 | * argv_split - split a string at whitespace, returning an argv |
138 | * @str: the string to be split |
139 | * @argcp: returned argument count |
140 | * |
141 | * Returns an array of pointers to strings which are split out from |
142 | * @str. This is performed by strictly splitting on white-space; no |
143 | * quote processing is performed. Multiple whitespace characters are |
144 | * considered to be a single argument separator. The returned array |
145 | * is always NULL-terminated. Returns NULL on memory allocation |
146 | * failure. |
147 | */ |
148 | char **argv_split(const char *str, int *argcp) |
149 | { |
150 | int argc = count_argc(str); |
151 | char **argv = zalloc(sizeof(*argv) * (argc+1)); |
152 | char **argvp; |
153 | |
154 | if (argv == NULL) |
155 | goto out; |
156 | |
157 | if (argcp) |
158 | *argcp = argc; |
159 | |
160 | argvp = argv; |
161 | |
162 | while (*str) { |
163 | str = skip_sep(str); |
164 | |
165 | if (*str) { |
166 | const char *p = str; |
167 | char *t; |
168 | |
169 | str = skip_arg(str); |
170 | |
171 | t = strndup(p, str-p); |
172 | if (t == NULL) |
173 | goto fail; |
174 | *argvp++ = t; |
175 | } |
176 | } |
177 | *argvp = NULL; |
178 | |
179 | out: |
180 | return argv; |
181 | |
182 | fail: |
183 | argv_free(argv); |
184 | return NULL; |
185 | } |
186 | |
187 | /* Character class matching */ |
188 | static bool __match_charclass(const char *pat, char c, const char **npat) |
189 | { |
190 | bool complement = false, ret = true; |
191 | |
192 | if (*pat == '!') { |
193 | complement = true; |
194 | pat++; |
195 | } |
196 | if (*pat++ == c) /* First character is special */ |
197 | goto end; |
198 | |
199 | while (*pat && *pat != ']') { /* Matching */ |
200 | if (*pat == '-' && *(pat + 1) != ']') { /* Range */ |
201 | if (*(pat - 1) <= c && c <= *(pat + 1)) |
202 | goto end; |
203 | if (*(pat - 1) > *(pat + 1)) |
204 | goto error; |
205 | pat += 2; |
206 | } else if (*pat++ == c) |
207 | goto end; |
208 | } |
209 | if (!*pat) |
210 | goto error; |
211 | ret = false; |
212 | |
213 | end: |
214 | while (*pat && *pat != ']') /* Searching closing */ |
215 | pat++; |
216 | if (!*pat) |
217 | goto error; |
218 | *npat = pat + 1; |
219 | return complement ? !ret : ret; |
220 | |
221 | error: |
222 | return false; |
223 | } |
224 | |
225 | /* Glob/lazy pattern matching */ |
226 | static bool __match_glob(const char *str, const char *pat, bool ignore_space) |
227 | { |
228 | while (*str && *pat && *pat != '*') { |
229 | if (ignore_space) { |
230 | /* Ignore spaces for lazy matching */ |
231 | if (isspace(*str)) { |
232 | str++; |
233 | continue; |
234 | } |
235 | if (isspace(*pat)) { |
236 | pat++; |
237 | continue; |
238 | } |
239 | } |
240 | if (*pat == '?') { /* Matches any single character */ |
241 | str++; |
242 | pat++; |
243 | continue; |
244 | } else if (*pat == '[') /* Character classes/Ranges */ |
245 | if (__match_charclass(pat + 1, *str, &pat)) { |
246 | str++; |
247 | continue; |
248 | } else |
249 | return false; |
250 | else if (*pat == '\\') /* Escaped char match as normal char */ |
251 | pat++; |
252 | if (*str++ != *pat++) |
253 | return false; |
254 | } |
255 | /* Check wild card */ |
256 | if (*pat == '*') { |
257 | while (*pat == '*') |
258 | pat++; |
259 | if (!*pat) /* Tail wild card matches all */ |
260 | return true; |
261 | while (*str) |
262 | if (__match_glob(str++, pat, ignore_space)) |
263 | return true; |
264 | } |
265 | return !*str && !*pat; |
266 | } |
267 | |
268 | /** |
269 | * strglobmatch - glob expression pattern matching |
270 | * @str: the target string to match |
271 | * @pat: the pattern string to match |
272 | * |
273 | * This returns true if the @str matches @pat. @pat can includes wildcards |
274 | * ('*','?') and character classes ([CHARS], complementation and ranges are |
275 | * also supported). Also, this supports escape character ('\') to use special |
276 | * characters as normal character. |
277 | * |
278 | * Note: if @pat syntax is broken, this always returns false. |
279 | */ |
280 | bool strglobmatch(const char *str, const char *pat) |
281 | { |
282 | return __match_glob(str, pat, false); |
283 | } |
284 | |
285 | /** |
286 | * strlazymatch - matching pattern strings lazily with glob pattern |
287 | * @str: the target string to match |
288 | * @pat: the pattern string to match |
289 | * |
290 | * This is similar to strglobmatch, except this ignores spaces in |
291 | * the target string. |
292 | */ |
293 | bool strlazymatch(const char *str, const char *pat) |
294 | { |
295 | return __match_glob(str, pat, true); |
296 | } |
297 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9