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 /* Character class matching */ 231 static bool __match_charclass(const char *pat, char c, const char **npat) 232 { 233 bool complement = false, ret = true; 234 235 if (*pat == '!') { 236 complement = true; 237 pat++; 238 } 239 if (*pat++ == c) /* First character is special */ 240 goto end; 241 242 while (*pat && *pat != ']') { /* Matching */ 243 if (*pat == '-' && *(pat + 1) != ']') { /* Range */ 244 if (*(pat - 1) <= c && c <= *(pat + 1)) 245 goto end; 246 if (*(pat - 1) > *(pat + 1)) 247 goto error; 248 pat += 2; 249 } else if (*pat++ == c) 250 goto end; 251 } 252 if (!*pat) 253 goto error; 254 ret = false; 255 256 end: 257 while (*pat && *pat != ']') /* Searching closing */ 258 pat++; 259 if (!*pat) 260 goto error; 261 *npat = pat + 1; 262 return complement ? !ret : ret; 263 264 error: 265 return false; 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 while (*str && *pat && *pat != '*') { 283 if (*pat == '?') { /* Matches any single character */ 284 str++; 285 pat++; 286 continue; 287 } else if (*pat == '[') /* Character classes/Ranges */ 288 if (__match_charclass(pat + 1, *str, &pat)) { 289 str++; 290 continue; 291 } else 292 return false; 293 else if (*pat == '\\') /* Escaped char match as normal char */ 294 pat++; 295 if (*str++ != *pat++) 296 return false; 297 } 298 /* Check wild card */ 299 if (*pat == '*') { 300 while (*pat == '*') 301 pat++; 302 if (!*pat) /* Tail wild card matches all */ 303 return true; 304 while (*str) 305 if (strglobmatch(str++, pat)) 306 return true; 307 } 308 return !*str && !*pat; 309 } 310 311