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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 391 /** 392 * str_append - reallocate string and append another 393 * @s: pointer to string pointer 394 * @len: pointer to len (initialized) 395 * @a: string to append. 396 */ 397 int str_append(char **s, int *len, const char *a) 398 { 399 int olen = *s ? strlen(*s) : 0; 400 int nlen = olen + strlen(a) + 1; 401 if (*len < nlen) { 402 *len = *len * 2; 403 if (*len < nlen) 404 *len = nlen; 405 *s = realloc(*s, *len); 406 if (!*s) 407 return -ENOMEM; 408 if (olen == 0) 409 **s = 0; 410 } 411 strcat(*s, a); 412 return 0; 413 } 414