diff options
Diffstat (limited to 'tools/perf/util/string.c')
-rw-r--r-- | tools/perf/util/string.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index c93eca9a7be3..f24a8cc933d5 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include "string.h" | 1 | #include "string.h" |
2 | #include "util.h" | ||
2 | 3 | ||
3 | static int hex(char ch) | 4 | static int hex(char ch) |
4 | { | 5 | { |
@@ -32,3 +33,196 @@ int hex2u64(const char *ptr, u64 *long_val) | |||
32 | 33 | ||
33 | return p - ptr; | 34 | return p - ptr; |
34 | } | 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 | } | ||