Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
string.c
Go to the documentation of this file.
1 #include "util.h"
2 #include "linux/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 
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 
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 
280 bool strglobmatch(const char *str, const char *pat)
281 {
282  return __match_glob(str, pat, false);
283 }
284 
293 bool strlazymatch(const char *str, const char *pat)
294 {
295  return __match_glob(str, pat, true);
296 }
297 
305 int strtailcmp(const char *s1, const char *s2)
306 {
307  int i1 = strlen(s1);
308  int i2 = strlen(s2);
309  while (--i1 >= 0 && --i2 >= 0) {
310  if (s1[i1] != s2[i2])
311  return s1[i1] - s2[i2];
312  }
313  return 0;
314 }
315 
323 char *rtrim(char *s)
324 {
325  size_t size = strlen(s);
326  char *end;
327 
328  if (!size)
329  return s;
330 
331  end = s + size - 1;
332  while (end >= s && isspace(*end))
333  end--;
334  *(end + 1) = '\0';
335 
336  return s;
337 }
338 
344 void *memdup(const void *src, size_t len)
345 {
346  void *p;
347 
348  p = malloc(len);
349  if (p)
350  memcpy(p, src, len);
351 
352  return p;
353 }