string.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define IN_BOOT_STRING_C 1
  3. #include <linux/ctype.h>
  4. #include <linux/kernel.h>
  5. #include <linux/errno.h>
  6. #undef CONFIG_KASAN
  7. #undef CONFIG_KASAN_GENERIC
  8. #undef CONFIG_KMSAN
  9. #include "../lib/string.c"
  10. /*
  11. * Duplicate some functions from the common lib/string.c
  12. * instead of fully including it.
  13. */
  14. int strncmp(const char *cs, const char *ct, size_t count)
  15. {
  16. unsigned char c1, c2;
  17. while (count) {
  18. c1 = *cs++;
  19. c2 = *ct++;
  20. if (c1 != c2)
  21. return c1 < c2 ? -1 : 1;
  22. if (!c1)
  23. break;
  24. count--;
  25. }
  26. return 0;
  27. }
  28. ssize_t sized_strscpy(char *dst, const char *src, size_t count)
  29. {
  30. size_t len;
  31. if (count == 0)
  32. return -E2BIG;
  33. len = strnlen(src, count - 1);
  34. memcpy(dst, src, len);
  35. dst[len] = '\0';
  36. return src[len] ? -E2BIG : len;
  37. }
  38. void *memset64(uint64_t *s, uint64_t v, size_t count)
  39. {
  40. uint64_t *xs = s;
  41. while (count--)
  42. *xs++ = v;
  43. return s;
  44. }
  45. char *skip_spaces(const char *str)
  46. {
  47. while (isspace(*str))
  48. ++str;
  49. return (char *)str;
  50. }
  51. char *strim(char *s)
  52. {
  53. size_t size;
  54. char *end;
  55. size = strlen(s);
  56. if (!size)
  57. return s;
  58. end = s + size - 1;
  59. while (end >= s && isspace(*end))
  60. end--;
  61. *(end + 1) = '\0';
  62. return skip_spaces(s);
  63. }
  64. /* Works only for digits and letters, but small and fast */
  65. #define TOLOWER(x) ((x) | 0x20)
  66. static unsigned int simple_guess_base(const char *cp)
  67. {
  68. if (cp[0] == '0') {
  69. if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
  70. return 16;
  71. else
  72. return 8;
  73. } else {
  74. return 10;
  75. }
  76. }
  77. /**
  78. * simple_strtoull - convert a string to an unsigned long long
  79. * @cp: The start of the string
  80. * @endp: A pointer to the end of the parsed string will be placed here
  81. * @base: The number base to use
  82. */
  83. unsigned long long simple_strtoull(const char *cp, char **endp,
  84. unsigned int base)
  85. {
  86. unsigned long long result = 0;
  87. if (!base)
  88. base = simple_guess_base(cp);
  89. if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
  90. cp += 2;
  91. while (isxdigit(*cp)) {
  92. unsigned int value;
  93. value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
  94. if (value >= base)
  95. break;
  96. result = result * base + value;
  97. cp++;
  98. }
  99. if (endp)
  100. *endp = (char *)cp;
  101. return result;
  102. }
  103. long simple_strtol(const char *cp, char **endp, unsigned int base)
  104. {
  105. if (*cp == '-')
  106. return -simple_strtoull(cp + 1, endp, base);
  107. return simple_strtoull(cp, endp, base);
  108. }
  109. int kstrtobool(const char *s, bool *res)
  110. {
  111. if (!s)
  112. return -EINVAL;
  113. switch (s[0]) {
  114. case 'y':
  115. case 'Y':
  116. case '1':
  117. *res = true;
  118. return 0;
  119. case 'n':
  120. case 'N':
  121. case '0':
  122. *res = false;
  123. return 0;
  124. case 'o':
  125. case 'O':
  126. switch (s[1]) {
  127. case 'n':
  128. case 'N':
  129. *res = true;
  130. return 0;
  131. case 'f':
  132. case 'F':
  133. *res = false;
  134. return 0;
  135. default:
  136. break;
  137. }
  138. default:
  139. break;
  140. }
  141. return -EINVAL;
  142. }