string.c 6.1 KB

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