string.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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. {
  169. while (*str && *pat && *pat != '*') {
  170. if (ignore_space) {
  171. /* Ignore spaces for lazy matching */
  172. if (isspace(*str)) {
  173. str++;
  174. continue;
  175. }
  176. if (isspace(*pat)) {
  177. pat++;
  178. continue;
  179. }
  180. }
  181. if (*pat == '?') { /* Matches any single character */
  182. str++;
  183. pat++;
  184. continue;
  185. } else if (*pat == '[') /* Character classes/Ranges */
  186. if (__match_charclass(pat + 1, *str, &pat)) {
  187. str++;
  188. continue;
  189. } else
  190. return false;
  191. else if (*pat == '\\') /* Escaped char match as normal char */
  192. pat++;
  193. if (*str++ != *pat++)
  194. return false;
  195. }
  196. /* Check wild card */
  197. if (*pat == '*') {
  198. while (*pat == '*')
  199. pat++;
  200. if (!*pat) /* Tail wild card matches all */
  201. return true;
  202. while (*str)
  203. if (__match_glob(str++, pat, ignore_space))
  204. return true;
  205. }
  206. return !*str && !*pat;
  207. }
  208. /**
  209. * strglobmatch - glob expression pattern matching
  210. * @str: the target string to match
  211. * @pat: the pattern string to match
  212. *
  213. * This returns true if the @str matches @pat. @pat can includes wildcards
  214. * ('*','?') and character classes ([CHARS], complementation and ranges are
  215. * also supported). Also, this supports escape character ('\') to use special
  216. * characters as normal character.
  217. *
  218. * Note: if @pat syntax is broken, this always returns false.
  219. */
  220. bool strglobmatch(const char *str, const char *pat)
  221. {
  222. return __match_glob(str, pat, false);
  223. }
  224. /**
  225. * strlazymatch - matching pattern strings lazily with glob pattern
  226. * @str: the target string to match
  227. * @pat: the pattern string to match
  228. *
  229. * This is similar to strglobmatch, except this ignores spaces in
  230. * the target string.
  231. */
  232. bool strlazymatch(const char *str, const char *pat)
  233. {
  234. return __match_glob(str, pat, true);
  235. }
  236. /**
  237. * strtailcmp - Compare the tail of two strings
  238. * @s1: 1st string to be compared
  239. * @s2: 2nd string to be compared
  240. *
  241. * Return 0 if whole of either string is same as another's tail part.
  242. */
  243. int strtailcmp(const char *s1, const char *s2)
  244. {
  245. int i1 = strlen(s1);
  246. int i2 = strlen(s2);
  247. while (--i1 >= 0 && --i2 >= 0) {
  248. if (s1[i1] != s2[i2])
  249. return s1[i1] - s2[i2];
  250. }
  251. return 0;
  252. }
  253. /**
  254. * strxfrchar - Locate and replace character in @s
  255. * @s: The string to be searched/changed.
  256. * @from: Source character to be replaced.
  257. * @to: Destination character.
  258. *
  259. * Return pointer to the changed string.
  260. */
  261. char *strxfrchar(char *s, char from, char to)
  262. {
  263. char *p = s;
  264. while ((p = strchr(p, from)) != NULL)
  265. *p++ = to;
  266. return s;
  267. }
  268. /**
  269. * ltrim - Removes leading whitespace from @s.
  270. * @s: The string to be stripped.
  271. *
  272. * Return pointer to the first non-whitespace character in @s.
  273. */
  274. char *ltrim(char *s)
  275. {
  276. int len = strlen(s);
  277. while (len && isspace(*s)) {
  278. len--;
  279. s++;
  280. }
  281. return s;
  282. }
  283. /**
  284. * rtrim - Removes trailing whitespace from @s.
  285. * @s: The string to be stripped.
  286. *
  287. * Note that the first trailing whitespace is replaced with a %NUL-terminator
  288. * in the given string @s. Returns @s.
  289. */
  290. char *rtrim(char *s)
  291. {
  292. size_t size = strlen(s);
  293. char *end;
  294. if (!size)
  295. return s;
  296. end = s + size - 1;
  297. while (end >= s && isspace(*end))
  298. end--;
  299. *(end + 1) = '\0';
  300. return s;
  301. }
  302. /**
  303. * memdup - duplicate region of memory
  304. * @src: memory region to duplicate
  305. * @len: memory region length
  306. */
  307. void *memdup(const void *src, size_t len)
  308. {
  309. void *p;
  310. p = malloc(len);
  311. if (p)
  312. memcpy(p, src, len);
  313. return p;
  314. }