kstrtox.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Convert integer string representation to an integer.
  3. * If an integer doesn't fit into specified type, -E is returned.
  4. *
  5. * Integer starts with optional sign.
  6. * kstrtou*() functions do not accept sign "-".
  7. *
  8. * Radix 0 means autodetection: leading "0x" implies radix 16,
  9. * leading "0" implies radix 8, otherwise radix is 10.
  10. * Autodetection hints work after optional sign, but not before.
  11. *
  12. * If -E is returned, result is not touched.
  13. */
  14. #include <linux/ctype.h>
  15. #include <linux/errno.h>
  16. #include <linux/kernel.h>
  17. #include <linux/math64.h>
  18. #include <linux/module.h>
  19. #include <linux/types.h>
  20. static inline char _tolower(const char c)
  21. {
  22. return c | 0x20;
  23. }
  24. static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
  25. {
  26. unsigned long long acc;
  27. int ok;
  28. if (base == 0) {
  29. if (s[0] == '0') {
  30. if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
  31. base = 16;
  32. else
  33. base = 8;
  34. } else
  35. base = 10;
  36. }
  37. if (base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
  38. s += 2;
  39. acc = 0;
  40. ok = 0;
  41. while (*s) {
  42. unsigned int val;
  43. if ('0' <= *s && *s <= '9')
  44. val = *s - '0';
  45. else if ('a' <= _tolower(*s) && _tolower(*s) <= 'f')
  46. val = _tolower(*s) - 'a' + 10;
  47. else if (*s == '\n' && *(s + 1) == '\0')
  48. break;
  49. else
  50. return -EINVAL;
  51. if (val >= base)
  52. return -EINVAL;
  53. if (acc > div_u64(ULLONG_MAX - val, base))
  54. return -ERANGE;
  55. acc = acc * base + val;
  56. ok = 1;
  57. s++;
  58. }
  59. if (!ok)
  60. return -EINVAL;
  61. *res = acc;
  62. return 0;
  63. }
  64. int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
  65. {
  66. if (s[0] == '+')
  67. s++;
  68. return _kstrtoull(s, base, res);
  69. }
  70. EXPORT_SYMBOL(kstrtoull);
  71. int kstrtoll(const char *s, unsigned int base, long long *res)
  72. {
  73. unsigned long long tmp;
  74. int rv;
  75. if (s[0] == '-') {
  76. rv = _kstrtoull(s + 1, base, &tmp);
  77. if (rv < 0)
  78. return rv;
  79. if ((long long)(-tmp) >= 0)
  80. return -ERANGE;
  81. *res = -tmp;
  82. } else {
  83. rv = kstrtoull(s, base, &tmp);
  84. if (rv < 0)
  85. return rv;
  86. if ((long long)tmp < 0)
  87. return -ERANGE;
  88. *res = tmp;
  89. }
  90. return 0;
  91. }
  92. EXPORT_SYMBOL(kstrtoll);
  93. /* Internal, do not use. */
  94. int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
  95. {
  96. unsigned long long tmp;
  97. int rv;
  98. rv = kstrtoull(s, base, &tmp);
  99. if (rv < 0)
  100. return rv;
  101. if (tmp != (unsigned long long)(unsigned long)tmp)
  102. return -ERANGE;
  103. *res = tmp;
  104. return 0;
  105. }
  106. EXPORT_SYMBOL(_kstrtoul);
  107. /* Internal, do not use. */
  108. int _kstrtol(const char *s, unsigned int base, long *res)
  109. {
  110. long long tmp;
  111. int rv;
  112. rv = kstrtoll(s, base, &tmp);
  113. if (rv < 0)
  114. return rv;
  115. if (tmp != (long long)(long)tmp)
  116. return -ERANGE;
  117. *res = tmp;
  118. return 0;
  119. }
  120. EXPORT_SYMBOL(_kstrtol);
  121. int kstrtouint(const char *s, unsigned int base, unsigned int *res)
  122. {
  123. unsigned long long tmp;
  124. int rv;
  125. rv = kstrtoull(s, base, &tmp);
  126. if (rv < 0)
  127. return rv;
  128. if (tmp != (unsigned long long)(unsigned int)tmp)
  129. return -ERANGE;
  130. *res = tmp;
  131. return 0;
  132. }
  133. EXPORT_SYMBOL(kstrtouint);
  134. int kstrtoint(const char *s, unsigned int base, int *res)
  135. {
  136. long long tmp;
  137. int rv;
  138. rv = kstrtoll(s, base, &tmp);
  139. if (rv < 0)
  140. return rv;
  141. if (tmp != (long long)(int)tmp)
  142. return -ERANGE;
  143. *res = tmp;
  144. return 0;
  145. }
  146. EXPORT_SYMBOL(kstrtoint);
  147. int kstrtou16(const char *s, unsigned int base, u16 *res)
  148. {
  149. unsigned long long tmp;
  150. int rv;
  151. rv = kstrtoull(s, base, &tmp);
  152. if (rv < 0)
  153. return rv;
  154. if (tmp != (unsigned long long)(u16)tmp)
  155. return -ERANGE;
  156. *res = tmp;
  157. return 0;
  158. }
  159. EXPORT_SYMBOL(kstrtou16);
  160. int kstrtos16(const char *s, unsigned int base, s16 *res)
  161. {
  162. long long tmp;
  163. int rv;
  164. rv = kstrtoll(s, base, &tmp);
  165. if (rv < 0)
  166. return rv;
  167. if (tmp != (long long)(s16)tmp)
  168. return -ERANGE;
  169. *res = tmp;
  170. return 0;
  171. }
  172. EXPORT_SYMBOL(kstrtos16);
  173. int kstrtou8(const char *s, unsigned int base, u8 *res)
  174. {
  175. unsigned long long tmp;
  176. int rv;
  177. rv = kstrtoull(s, base, &tmp);
  178. if (rv < 0)
  179. return rv;
  180. if (tmp != (unsigned long long)(u8)tmp)
  181. return -ERANGE;
  182. *res = tmp;
  183. return 0;
  184. }
  185. EXPORT_SYMBOL(kstrtou8);
  186. int kstrtos8(const char *s, unsigned int base, s8 *res)
  187. {
  188. long long tmp;
  189. int rv;
  190. rv = kstrtoll(s, base, &tmp);
  191. if (rv < 0)
  192. return rv;
  193. if (tmp != (long long)(s8)tmp)
  194. return -ERANGE;
  195. *res = tmp;
  196. return 0;
  197. }
  198. EXPORT_SYMBOL(kstrtos8);