string.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. #include "util.h"
  2. #include "linux/string.h"
  3. #define K 1024LL
  4. /*
  5. * perf_atoll()
  6. * Parse (\d+)(b|B|kb|KB|mb|MB|gb|GB|tb|TB) (e.g. "256MB")
  7. * and return its numeric value
  8. */
  9. s64 perf_atoll(const char *str)
  10. {
  11. s64 length;
  12. char *p;
  13. char c;
  14. if (!isdigit(str[0]))
  15. goto out_err;
  16. length = strtoll(str, &p, 10);
  17. switch (c = *p++) {
  18. case 'b': case 'B':
  19. if (*p)
  20. goto out_err;
  21. case '\0':
  22. return length;
  23. default:
  24. goto out_err;
  25. /* two-letter suffices */
  26. case 'k': case 'K':
  27. length <<= 10;
  28. break;
  29. case 'm': case 'M':
  30. length <<= 20;
  31. break;
  32. case 'g': case 'G':
  33. length <<= 30;
  34. break;
  35. case 't': case 'T':
  36. length <<= 40;
  37. break;
  38. }
  39. /* we want the cases to match */
  40. if (islower(c)) {
  41. if (strcmp(p, "b") != 0)
  42. goto out_err;
  43. } else {
  44. if (strcmp(p, "B") != 0)
  45. goto out_err;
  46. }
  47. return length;
  48. out_err:
  49. return -1;
  50. }
  51. /*
  52. * Helper function for splitting a string into an argv-like array.
  53. * originally copied from lib/argv_split.c
  54. */
  55. static const char *skip_sep(const char *cp)
  56. {
  57. while (*cp && isspace(*cp))
  58. cp++;
  59. return cp;
  60. }
  61. static const char *skip_arg(const char *cp)
  62. {
  63. while (*cp && !isspace(*cp))
  64. cp++;
  65. return cp;
  66. }
  67. static int count_argc(const char *str)
  68. {
  69. int count = 0;
  70. while (*str) {
  71. str = skip_sep(str);
  72. if (*str) {
  73. count++;
  74. str = skip_arg(str);
  75. }
  76. }
  77. return count;
  78. }
  79. /**
  80. * argv_free - free an argv
  81. * @argv - the argument vector to be freed
  82. *
  83. * Frees an argv and the strings it points to.
  84. */
  85. void argv_free(char **argv)
  86. {
  87. char **p;
  88. for (p = argv; *p; p++)
  89. zfree(p);
  90. free(argv);
  91. }
  92. /**
  93. * argv_split - split a string at whitespace, returning an argv
  94. * @str: the string to be split
  95. * @argcp: returned argument count
  96. *
  97. * Returns an array of pointers to strings which are split out from
  98. * @str. This is performed by strictly splitting on white-space; no
  99. * quote processing is performed. Multiple whitespace characters are
  100. * considered to be a single argument separator. The returned array
  101. * is always NULL-terminated. Returns NULL on memory allocation
  102. * failure.
  103. */
  104. char **argv_split(const char *str, int *argcp)
  105. {
  106. int argc = count_argc(str);
  107. char **argv = zalloc(sizeof(*argv) * (argc+1));
  108. char **argvp;
  109. if (argv == NULL)
  110. goto out;
  111. if (argcp)
  112. *argcp = argc;
  113. argvp = argv;
  114. while (*str) {
  115. str = skip_sep(str);
  116. if (*str) {
  117. const char *p = str;
  118. char *t;
  119. str = skip_arg(str);
  120. t = strndup(p, str-p);
  121. if (t == NULL)
  122. goto fail;
  123. *argvp++ = t;
  124. }
  125. }
  126. *argvp = NULL;
  127. out:
  128. return argv;
  129. fail:
  130. argv_free(argv);
  131. return NULL;
  132. }
  133. /* Character class matching */
  134. static bool __match_charclass(const char *pat, char c, const char **npat)
  135. {
  136. bool complement = false, ret = true;
  137. if (*pat == '!') {
  138. complement = true;
  139. pat++;
  140. }
  141. if (*pat++ == c) /* First character is special */
  142. goto end;
  143. while (*pat && *pat != ']') { /* Matching */
  144. if (*pat == '-' && *(pat + 1) != ']') { /* Range */
  145. if (*(pat - 1) <= c && c <= *(pat + 1))
  146. goto end;
  147. if (*(pat - 1) > *(pat + 1))
  148. goto error;
  149. pat += 2;
  150. } else if (*pat++ == c)
  151. goto end;
  152. }
  153. if (!*pat)
  154. goto error;
  155. ret = false;
  156. end:
  157. while (*pat && *pat != ']') /* Searching closing */
  158. pat++;
  159. if (!*pat)
  160. goto error;
  161. *npat = pat + 1;
  162. return complement ? !ret : ret;
  163. error:
  164. return false;
  165. }
  166. /* Glob/lazy pattern matching */
  167. static bool __match_glob(const char *str, const char *pat, bool ignore_space,
  168. bool case_ins)
  169. {
  170. while (*str && *pat && *pat != '*') {
  171. if (ignore_space) {
  172. /* Ignore spaces for lazy matching */
  173. if (isspace(*str)) {
  174. str++;
  175. continue;
  176. }
  177. if (isspace(*pat)) {
  178. pat++;
  179. continue;
  180. }
  181. }
  182. if (*pat == '?') { /* Matches any single character */
  183. str++;
  184. pat++;
  185. continue;
  186. } else if (*pat == '[') /* Character classes/Ranges */
  187. if (__match_charclass(pat + 1, *str, &pat)) {
  188. str++;
  189. continue;
  190. } else
  191. return false;
  192. else if (*pat == '\\') /* Escaped char match as normal char */
  193. pat++;
  194. if (case_ins) {
  195. if (tolower(*str) != tolower(*pat))
  196. return false;
  197. } else if (*str != *pat)
  198. return false;
  199. str++;
  200. pat++;
  201. }
  202. /* Check wild card */
  203. if (*pat == '*') {
  204. while (*pat == '*')
  205. pat++;
  206. if (!*pat) /* Tail wild card matches all */
  207. return true;
  208. while (*str)
  209. if (__match_glob(str++, pat, ignore_space, case_ins))
  210. return true;
  211. }
  212. return !*str && !*pat;
  213. }
  214. /**
  215. * strglobmatch - glob expression pattern matching
  216. * @str: the target string to match
  217. * @pat: the pattern string to match
  218. *
  219. * This returns true if the @str matches @pat. @pat can includes wildcards
  220. * ('*','?') and character classes ([CHARS], complementation and ranges are
  221. * also supported). Also, this supports escape character ('\') to use special
  222. * characters as normal character.
  223. *
  224. * Note: if @pat syntax is broken, this always returns false.
  225. */
  226. bool strglobmatch(const char *str, const char *pat)
  227. {
  228. return __match_glob(str, pat, false, false);
  229. }
  230. bool strglobmatch_nocase(const char *str, const char *pat)
  231. {
  232. return __match_glob(str, pat, false, true);
  233. }
  234. /**
  235. * strlazymatch - matching pattern strings lazily with glob pattern
  236. * @str: the target string to match
  237. * @pat: the pattern string to match
  238. *
  239. * This is similar to strglobmatch, except this ignores spaces in
  240. * the target string.
  241. */
  242. bool strlazymatch(const char *str, const char *pat)
  243. {
  244. return __match_glob(str, pat, true, false);
  245. }
  246. /**
  247. * strtailcmp - Compare the tail of two strings
  248. * @s1: 1st string to be compared
  249. * @s2: 2nd string to be compared
  250. *
  251. * Return 0 if whole of either string is same as another's tail part.
  252. */
  253. int strtailcmp(const char *s1, const char *s2)
  254. {
  255. int i1 = strlen(s1);
  256. int i2 = strlen(s2);
  257. while (--i1 >= 0 && --i2 >= 0) {
  258. if (s1[i1] != s2[i2])
  259. return s1[i1] - s2[i2];
  260. }
  261. return 0;
  262. }
  263. /**
  264. * strxfrchar - Locate and replace character in @s
  265. * @s: The string to be searched/changed.
  266. * @from: Source character to be replaced.
  267. * @to: Destination character.
  268. *
  269. * Return pointer to the changed string.
  270. */
  271. char *strxfrchar(char *s, char from, char to)
  272. {
  273. char *p = s;
  274. while ((p = strchr(p, from)) != NULL)
  275. *p++ = to;
  276. return s;
  277. }
  278. /**
  279. * ltrim - Removes leading whitespace from @s.
  280. * @s: The string to be stripped.
  281. *
  282. * Return pointer to the first non-whitespace character in @s.
  283. */
  284. char *ltrim(char *s)
  285. {
  286. int len = strlen(s);
  287. while (len && isspace(*s)) {
  288. len--;
  289. s++;
  290. }
  291. return s;
  292. }
  293. /**
  294. * rtrim - Removes trailing whitespace from @s.
  295. * @s: The string to be stripped.
  296. *
  297. * Note that the first trailing whitespace is replaced with a %NUL-terminator
  298. * in the given string @s. Returns @s.
  299. */
  300. char *rtrim(char *s)
  301. {
  302. size_t size = strlen(s);
  303. char *end;
  304. if (!size)
  305. return s;
  306. end = s + size - 1;
  307. while (end >= s && isspace(*end))
  308. end--;
  309. *(end + 1) = '\0';
  310. return s;
  311. }
  312. char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints)
  313. {
  314. /*
  315. * FIXME: replace this with an expression using log10() when we
  316. * find a suitable implementation, maybe the one in the dvb drivers...
  317. *
  318. * "%s == %d || " = log10(MAXINT) * 2 + 8 chars for the operators
  319. */
  320. size_t size = nints * 28 + 1; /* \0 */
  321. size_t i, printed = 0;
  322. char *expr = malloc(size);
  323. if (expr) {
  324. const char *or_and = "||", *eq_neq = "==";
  325. char *e = expr;
  326. if (!in) {
  327. or_and = "&&";
  328. eq_neq = "!=";
  329. }
  330. for (i = 0; i < nints; ++i) {
  331. if (printed == size)
  332. goto out_err_overflow;
  333. if (i > 0)
  334. printed += snprintf(e + printed, size - printed, " %s ", or_and);
  335. printed += scnprintf(e + printed, size - printed,
  336. "%s %s %d", var, eq_neq, ints[i]);
  337. }
  338. }
  339. return expr;
  340. out_err_overflow:
  341. free(expr);
  342. return NULL;
  343. }