string.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * linux/tools/lib/string.c
  4. *
  5. * Copied from linux/lib/string.c, where it is:
  6. *
  7. * Copyright (C) 1991, 1992 Linus Torvalds
  8. *
  9. * More specifically, the first copied function was strtobool, which
  10. * was introduced by:
  11. *
  12. * d0f1fed29e6e ("Add a strtobool function matching semantics of existing in kernel equivalents")
  13. * Author: Jonathan Cameron <jic23@cam.ac.uk>
  14. */
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <errno.h>
  18. #include <linux/string.h>
  19. #include <linux/ctype.h>
  20. #include <linux/compiler.h>
  21. /**
  22. * memdup - duplicate region of memory
  23. *
  24. * @src: memory region to duplicate
  25. * @len: memory region length
  26. */
  27. void *memdup(const void *src, size_t len)
  28. {
  29. void *p = malloc(len);
  30. if (p)
  31. memcpy(p, src, len);
  32. return p;
  33. }
  34. /**
  35. * strtobool - convert common user inputs into boolean values
  36. * @s: input string
  37. * @res: result
  38. *
  39. * This routine returns 0 iff the first character is one of 'Yy1Nn0', or
  40. * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value
  41. * pointed to by res is updated upon finding a match.
  42. */
  43. int strtobool(const char *s, bool *res)
  44. {
  45. if (!s)
  46. return -EINVAL;
  47. switch (s[0]) {
  48. case 'y':
  49. case 'Y':
  50. case '1':
  51. *res = true;
  52. return 0;
  53. case 'n':
  54. case 'N':
  55. case '0':
  56. *res = false;
  57. return 0;
  58. case 'o':
  59. case 'O':
  60. switch (s[1]) {
  61. case 'n':
  62. case 'N':
  63. *res = true;
  64. return 0;
  65. case 'f':
  66. case 'F':
  67. *res = false;
  68. return 0;
  69. default:
  70. break;
  71. }
  72. default:
  73. break;
  74. }
  75. return -EINVAL;
  76. }
  77. /**
  78. * strlcpy - Copy a C-string into a sized buffer
  79. * @dest: Where to copy the string to
  80. * @src: Where to copy the string from
  81. * @size: size of destination buffer
  82. *
  83. * Compatible with *BSD: the result is always a valid
  84. * NUL-terminated string that fits in the buffer (unless,
  85. * of course, the buffer size is zero). It does not pad
  86. * out the result like strncpy() does.
  87. *
  88. * If libc has strlcpy() then that version will override this
  89. * implementation:
  90. */
  91. #ifdef __clang__
  92. #pragma clang diagnostic push
  93. #pragma clang diagnostic ignored "-Wignored-attributes"
  94. #endif
  95. size_t __weak strlcpy(char *dest, const char *src, size_t size)
  96. {
  97. size_t ret = strlen(src);
  98. if (size) {
  99. size_t len = (ret >= size) ? size - 1 : ret;
  100. memcpy(dest, src, len);
  101. dest[len] = '\0';
  102. }
  103. return ret;
  104. }
  105. #ifdef __clang__
  106. #pragma clang diagnostic pop
  107. #endif
  108. /**
  109. * skip_spaces - Removes leading whitespace from @str.
  110. * @str: The string to be stripped.
  111. *
  112. * Returns a pointer to the first non-whitespace character in @str.
  113. */
  114. char *skip_spaces(const char *str)
  115. {
  116. while (isspace(*str))
  117. ++str;
  118. return (char *)str;
  119. }
  120. /**
  121. * strim - Removes leading and trailing whitespace from @s.
  122. * @s: The string to be stripped.
  123. *
  124. * Note that the first trailing whitespace is replaced with a %NUL-terminator
  125. * in the given string @s. Returns a pointer to the first non-whitespace
  126. * character in @s.
  127. */
  128. char *strim(char *s)
  129. {
  130. size_t size;
  131. char *end;
  132. size = strlen(s);
  133. if (!size)
  134. return s;
  135. end = s + size - 1;
  136. while (end >= s && isspace(*end))
  137. end--;
  138. *(end + 1) = '\0';
  139. return skip_spaces(s);
  140. }
  141. /**
  142. * strreplace - Replace all occurrences of character in string.
  143. * @s: The string to operate on.
  144. * @old: The character being replaced.
  145. * @new: The character @old is replaced with.
  146. *
  147. * Returns pointer to the nul byte at the end of @s.
  148. */
  149. char *strreplace(char *s, char old, char new)
  150. {
  151. for (; *s; ++s)
  152. if (*s == old)
  153. *s = new;
  154. return s;
  155. }
  156. static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
  157. {
  158. while (bytes) {
  159. if (*start != value)
  160. return (void *)start;
  161. start++;
  162. bytes--;
  163. }
  164. return NULL;
  165. }
  166. /**
  167. * memchr_inv - Find an unmatching character in an area of memory.
  168. * @start: The memory area
  169. * @c: Find a character other than c
  170. * @bytes: The size of the area.
  171. *
  172. * returns the address of the first character other than @c, or %NULL
  173. * if the whole buffer contains just @c.
  174. */
  175. void *memchr_inv(const void *start, int c, size_t bytes)
  176. {
  177. u8 value = c;
  178. u64 value64;
  179. unsigned int words, prefix;
  180. if (bytes <= 16)
  181. return check_bytes8(start, value, bytes);
  182. value64 = value;
  183. value64 |= value64 << 8;
  184. value64 |= value64 << 16;
  185. value64 |= value64 << 32;
  186. prefix = (unsigned long)start % 8;
  187. if (prefix) {
  188. u8 *r;
  189. prefix = 8 - prefix;
  190. r = check_bytes8(start, value, prefix);
  191. if (r)
  192. return r;
  193. start += prefix;
  194. bytes -= prefix;
  195. }
  196. words = bytes / 8;
  197. while (words) {
  198. if (*(u64 *)start != value64)
  199. return check_bytes8(start, value, 8);
  200. start += 8;
  201. words--;
  202. }
  203. return check_bytes8(start, value, bytes % 8);
  204. }