strto.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * linux/lib/vsprintf.c
  3. *
  4. * Copyright (C) 1991, 1992 Linus Torvalds
  5. */
  6. /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  7. /*
  8. * Wirzenius wrote this portably, Torvalds fucked it up :-)
  9. */
  10. #include <common.h>
  11. #include <errno.h>
  12. #include <linux/ctype.h>
  13. /* from lib/kstrtox.c */
  14. static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
  15. {
  16. if (*base == 0) {
  17. if (s[0] == '0') {
  18. if (tolower(s[1]) == 'x' && isxdigit(s[2]))
  19. *base = 16;
  20. else
  21. *base = 8;
  22. } else
  23. *base = 10;
  24. }
  25. if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
  26. s += 2;
  27. return s;
  28. }
  29. unsigned long simple_strtoul(const char *cp, char **endp,
  30. unsigned int base)
  31. {
  32. unsigned long result = 0;
  33. unsigned long value;
  34. cp = _parse_integer_fixup_radix(cp, &base);
  35. while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
  36. ? toupper(*cp) : *cp)-'A'+10) < base) {
  37. result = result*base + value;
  38. cp++;
  39. }
  40. if (endp)
  41. *endp = (char *)cp;
  42. return result;
  43. }
  44. int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
  45. {
  46. char *tail;
  47. unsigned long val;
  48. size_t len;
  49. *res = 0;
  50. len = strlen(cp);
  51. if (len == 0)
  52. return -EINVAL;
  53. val = simple_strtoul(cp, &tail, base);
  54. if (tail == cp)
  55. return -EINVAL;
  56. if ((*tail == '\0') ||
  57. ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
  58. *res = val;
  59. return 0;
  60. }
  61. return -EINVAL;
  62. }
  63. long simple_strtol(const char *cp, char **endp, unsigned int base)
  64. {
  65. if (*cp == '-')
  66. return -simple_strtoul(cp + 1, endp, base);
  67. return simple_strtoul(cp, endp, base);
  68. }
  69. unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
  70. {
  71. unsigned long result = simple_strtoul(cp, endp, base);
  72. switch (tolower(**endp)) {
  73. case 'g':
  74. result *= 1024;
  75. /* fall through */
  76. case 'm':
  77. result *= 1024;
  78. /* fall through */
  79. case 'k':
  80. result *= 1024;
  81. (*endp)++;
  82. if (**endp == 'i')
  83. (*endp)++;
  84. if (**endp == 'B')
  85. (*endp)++;
  86. }
  87. return result;
  88. }
  89. unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
  90. {
  91. unsigned long long result = simple_strtoull(cp, endp, base);
  92. switch (tolower(**endp)) {
  93. case 'g':
  94. result *= 1024;
  95. /* fall through */
  96. case 'm':
  97. result *= 1024;
  98. /* fall through */
  99. case 'k':
  100. result *= 1024;
  101. (*endp)++;
  102. if (**endp == 'i')
  103. (*endp)++;
  104. if (**endp == 'B')
  105. (*endp)++;
  106. }
  107. return result;
  108. }
  109. unsigned long long simple_strtoull(const char *cp, char **endp,
  110. unsigned int base)
  111. {
  112. unsigned long long result = 0, value;
  113. cp = _parse_integer_fixup_radix(cp, &base);
  114. while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
  115. : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
  116. result = result * base + value;
  117. cp++;
  118. }
  119. if (endp)
  120. *endp = (char *) cp;
  121. return result;
  122. }
  123. long trailing_strtoln(const char *str, const char *end)
  124. {
  125. const char *p;
  126. if (!end)
  127. end = str + strlen(str);
  128. if (isdigit(end[-1])) {
  129. for (p = end - 1; p > str; p--) {
  130. if (!isdigit(*p))
  131. return simple_strtoul(p + 1, NULL, 10);
  132. }
  133. }
  134. return -1;
  135. }
  136. long trailing_strtol(const char *str)
  137. {
  138. return trailing_strtoln(str, NULL);
  139. }