string.c 7.5 KB

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