xref: /openbmc/linux/tools/perf/util/string.c (revision a09d2831)
1 #include "string.h"
2 #include "util.h"
3 
4 static int hex(char ch)
5 {
6 	if ((ch >= '0') && (ch <= '9'))
7 		return ch - '0';
8 	if ((ch >= 'a') && (ch <= 'f'))
9 		return ch - 'a' + 10;
10 	if ((ch >= 'A') && (ch <= 'F'))
11 		return ch - 'A' + 10;
12 	return -1;
13 }
14 
15 /*
16  * While we find nice hex chars, build a long_val.
17  * Return number of chars processed.
18  */
19 int hex2u64(const char *ptr, u64 *long_val)
20 {
21 	const char *p = ptr;
22 	*long_val = 0;
23 
24 	while (*p) {
25 		const int hex_val = hex(*p);
26 
27 		if (hex_val < 0)
28 			break;
29 
30 		*long_val = (*long_val << 4) | hex_val;
31 		p++;
32 	}
33 
34 	return p - ptr;
35 }
36 
37 char *strxfrchar(char *s, char from, char to)
38 {
39 	char *p = s;
40 
41 	while ((p = strchr(p, from)) != NULL)
42 		*p++ = to;
43 
44 	return s;
45 }
46 
47 #define K 1024LL
48 /*
49  * perf_atoll()
50  * Parse (\d+)(b|B|kb|KB|mb|MB|gb|GB|tb|TB) (e.g. "256MB")
51  * and return its numeric value
52  */
53 s64 perf_atoll(const char *str)
54 {
55 	unsigned int i;
56 	s64 length = -1, unit = 1;
57 
58 	if (!isdigit(str[0]))
59 		goto out_err;
60 
61 	for (i = 1; i < strlen(str); i++) {
62 		switch (str[i]) {
63 		case 'B':
64 		case 'b':
65 			break;
66 		case 'K':
67 			if (str[i + 1] != 'B')
68 				goto out_err;
69 			else
70 				goto kilo;
71 		case 'k':
72 			if (str[i + 1] != 'b')
73 				goto out_err;
74 kilo:
75 			unit = K;
76 			break;
77 		case 'M':
78 			if (str[i + 1] != 'B')
79 				goto out_err;
80 			else
81 				goto mega;
82 		case 'm':
83 			if (str[i + 1] != 'b')
84 				goto out_err;
85 mega:
86 			unit = K * K;
87 			break;
88 		case 'G':
89 			if (str[i + 1] != 'B')
90 				goto out_err;
91 			else
92 				goto giga;
93 		case 'g':
94 			if (str[i + 1] != 'b')
95 				goto out_err;
96 giga:
97 			unit = K * K * K;
98 			break;
99 		case 'T':
100 			if (str[i + 1] != 'B')
101 				goto out_err;
102 			else
103 				goto tera;
104 		case 't':
105 			if (str[i + 1] != 'b')
106 				goto out_err;
107 tera:
108 			unit = K * K * K * K;
109 			break;
110 		case '\0':	/* only specified figures */
111 			unit = 1;
112 			break;
113 		default:
114 			if (!isdigit(str[i]))
115 				goto out_err;
116 			break;
117 		}
118 	}
119 
120 	length = atoll(str) * unit;
121 	goto out;
122 
123 out_err:
124 	length = -1;
125 out:
126 	return length;
127 }
128 
129 /*
130  * Helper function for splitting a string into an argv-like array.
131  * originaly copied from lib/argv_split.c
132  */
133 static const char *skip_sep(const char *cp)
134 {
135 	while (*cp && isspace(*cp))
136 		cp++;
137 
138 	return cp;
139 }
140 
141 static const char *skip_arg(const char *cp)
142 {
143 	while (*cp && !isspace(*cp))
144 		cp++;
145 
146 	return cp;
147 }
148 
149 static int count_argc(const char *str)
150 {
151 	int count = 0;
152 
153 	while (*str) {
154 		str = skip_sep(str);
155 		if (*str) {
156 			count++;
157 			str = skip_arg(str);
158 		}
159 	}
160 
161 	return count;
162 }
163 
164 /**
165  * argv_free - free an argv
166  * @argv - the argument vector to be freed
167  *
168  * Frees an argv and the strings it points to.
169  */
170 void argv_free(char **argv)
171 {
172 	char **p;
173 	for (p = argv; *p; p++)
174 		free(*p);
175 
176 	free(argv);
177 }
178 
179 /**
180  * argv_split - split a string at whitespace, returning an argv
181  * @str: the string to be split
182  * @argcp: returned argument count
183  *
184  * Returns an array of pointers to strings which are split out from
185  * @str.  This is performed by strictly splitting on white-space; no
186  * quote processing is performed.  Multiple whitespace characters are
187  * considered to be a single argument separator.  The returned array
188  * is always NULL-terminated.  Returns NULL on memory allocation
189  * failure.
190  */
191 char **argv_split(const char *str, int *argcp)
192 {
193 	int argc = count_argc(str);
194 	char **argv = zalloc(sizeof(*argv) * (argc+1));
195 	char **argvp;
196 
197 	if (argv == NULL)
198 		goto out;
199 
200 	if (argcp)
201 		*argcp = argc;
202 
203 	argvp = argv;
204 
205 	while (*str) {
206 		str = skip_sep(str);
207 
208 		if (*str) {
209 			const char *p = str;
210 			char *t;
211 
212 			str = skip_arg(str);
213 
214 			t = strndup(p, str-p);
215 			if (t == NULL)
216 				goto fail;
217 			*argvp++ = t;
218 		}
219 	}
220 	*argvp = NULL;
221 
222 out:
223 	return argv;
224 
225 fail:
226 	argv_free(argv);
227 	return NULL;
228 }
229 
230 /* Glob expression pattern matching */
231 bool strglobmatch(const char *str, const char *pat)
232 {
233 	while (*str && *pat && *pat != '*') {
234 		if (*pat == '?') {
235 			str++;
236 			pat++;
237 		} else
238 			if (*str++ != *pat++)
239 				return false;
240 	}
241 	/* Check wild card */
242 	if (*pat == '*') {
243 		while (*pat == '*')
244 			pat++;
245 		if (!*pat)	/* Tail wild card matches all */
246 			return true;
247 		while (*str)
248 			if (strglobmatch(str++, pat))
249 				return true;
250 	}
251 	return !*str && !*pat;
252 }
253 
254