strto.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. unsigned long simple_strtoul(const char *cp, char **endp,
  14. unsigned int base)
  15. {
  16. unsigned long result = 0;
  17. unsigned long value;
  18. if (*cp == '0') {
  19. cp++;
  20. if ((*cp == 'x') && isxdigit(cp[1])) {
  21. base = 16;
  22. cp++;
  23. }
  24. if (!base)
  25. base = 8;
  26. }
  27. if (!base)
  28. base = 10;
  29. while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
  30. ? toupper(*cp) : *cp)-'A'+10) < base) {
  31. result = result*base + value;
  32. cp++;
  33. }
  34. if (endp)
  35. *endp = (char *)cp;
  36. return result;
  37. }
  38. int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
  39. {
  40. char *tail;
  41. unsigned long val;
  42. size_t len;
  43. *res = 0;
  44. len = strlen(cp);
  45. if (len == 0)
  46. return -EINVAL;
  47. val = simple_strtoul(cp, &tail, base);
  48. if (tail == cp)
  49. return -EINVAL;
  50. if ((*tail == '\0') ||
  51. ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
  52. *res = val;
  53. return 0;
  54. }
  55. return -EINVAL;
  56. }
  57. long simple_strtol(const char *cp, char **endp, unsigned int base)
  58. {
  59. if (*cp == '-')
  60. return -simple_strtoul(cp + 1, endp, base);
  61. return simple_strtoul(cp, endp, base);
  62. }
  63. unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
  64. {
  65. unsigned long result = simple_strtoul(cp, endp, base);
  66. switch (**endp) {
  67. case 'G':
  68. result *= 1024;
  69. /* fall through */
  70. case 'M':
  71. result *= 1024;
  72. /* fall through */
  73. case 'K':
  74. case 'k':
  75. result *= 1024;
  76. if ((*endp)[1] == 'i') {
  77. if ((*endp)[2] == 'B')
  78. (*endp) += 3;
  79. else
  80. (*endp) += 2;
  81. }
  82. }
  83. return result;
  84. }
  85. unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
  86. {
  87. unsigned long long result = simple_strtoull(cp, endp, base);
  88. switch (**endp) {
  89. case 'G':
  90. result *= 1024;
  91. /* fall through */
  92. case 'M':
  93. result *= 1024;
  94. /* fall through */
  95. case 'K':
  96. case 'k':
  97. result *= 1024;
  98. if ((*endp)[1] == 'i') {
  99. if ((*endp)[2] == 'B')
  100. (*endp) += 3;
  101. else
  102. (*endp) += 2;
  103. }
  104. }
  105. return result;
  106. }
  107. unsigned long long simple_strtoull(const char *cp, char **endp,
  108. unsigned int base)
  109. {
  110. unsigned long long result = 0, value;
  111. if (*cp == '0') {
  112. cp++;
  113. if ((*cp == 'x') && isxdigit(cp[1])) {
  114. base = 16;
  115. cp++;
  116. }
  117. if (!base)
  118. base = 8;
  119. }
  120. if (!base)
  121. base = 10;
  122. while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
  123. : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
  124. result = result * base + value;
  125. cp++;
  126. }
  127. if (endp)
  128. *endp = (char *) cp;
  129. return result;
  130. }
  131. long trailing_strtoln(const char *str, const char *end)
  132. {
  133. const char *p;
  134. if (!end)
  135. end = str + strlen(str);
  136. if (isdigit(end[-1])) {
  137. for (p = end - 1; p > str; p--) {
  138. if (!isdigit(*p))
  139. return simple_strtoul(p + 1, NULL, 10);
  140. }
  141. }
  142. return -1;
  143. }
  144. long trailing_strtol(const char *str)
  145. {
  146. return trailing_strtoln(str, NULL);
  147. }