• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   */
perf_atoll(const char * str)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   */
skip_sep(const char * cp)90  static const char *skip_sep(const char *cp)
91  {
92  	while (*cp && isspace(*cp))
93  		cp++;
94  
95  	return cp;
96  }
97  
skip_arg(const char * cp)98  static const char *skip_arg(const char *cp)
99  {
100  	while (*cp && !isspace(*cp))
101  		cp++;
102  
103  	return cp;
104  }
105  
count_argc(const char * str)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   */
argv_free(char ** argv)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   */
argv_split(const char * str,int * argcp)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 */
__match_charclass(const char * pat,char c,const char ** npat)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 */
__match_glob(const char * str,const char * pat,bool ignore_space)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   */
strglobmatch(const char * str,const char * pat)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   */
strlazymatch(const char * str,const char * pat)293  bool strlazymatch(const char *str, const char *pat)
294  {
295  	return __match_glob(str, pat, true);
296  }
297  
298  /**
299   * strtailcmp - Compare the tail of two strings
300   * @s1: 1st string to be compared
301   * @s2: 2nd string to be compared
302   *
303   * Return 0 if whole of either string is same as another's tail part.
304   */
strtailcmp(const char * s1,const char * s2)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  
316  /**
317   * strxfrchar - Locate and replace character in @s
318   * @s:    The string to be searched/changed.
319   * @from: Source character to be replaced.
320   * @to:   Destination character.
321   *
322   * Return pointer to the changed string.
323   */
strxfrchar(char * s,char from,char to)324  char *strxfrchar(char *s, char from, char to)
325  {
326  	char *p = s;
327  
328  	while ((p = strchr(p, from)) != NULL)
329  		*p++ = to;
330  
331  	return s;
332  }
333  
334  /**
335   * ltrim - Removes leading whitespace from @s.
336   * @s: The string to be stripped.
337   *
338   * Return pointer to the first non-whitespace character in @s.
339   */
ltrim(char * s)340  char *ltrim(char *s)
341  {
342  	int len = strlen(s);
343  
344  	while (len && isspace(*s)) {
345  		len--;
346  		s++;
347  	}
348  
349  	return s;
350  }
351  
352  /**
353   * rtrim - Removes trailing whitespace from @s.
354   * @s: The string to be stripped.
355   *
356   * Note that the first trailing whitespace is replaced with a %NUL-terminator
357   * in the given string @s. Returns @s.
358   */
rtrim(char * s)359  char *rtrim(char *s)
360  {
361  	size_t size = strlen(s);
362  	char *end;
363  
364  	if (!size)
365  		return s;
366  
367  	end = s + size - 1;
368  	while (end >= s && isspace(*end))
369  		end--;
370  	*(end + 1) = '\0';
371  
372  	return s;
373  }
374  
375  /**
376   * memdup - duplicate region of memory
377   * @src: memory region to duplicate
378   * @len: memory region length
379   */
memdup(const void * src,size_t len)380  void *memdup(const void *src, size_t len)
381  {
382  	void *p;
383  
384  	p = malloc(len);
385  	if (p)
386  		memcpy(p, src, len);
387  
388  	return p;
389  }
390