strtoumax.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include <inttypes.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <ctype.h>
  5. #include <stdio.h>
  6. /* Lookup table for digit values. -1==255>=36 -> invalid */
  7. static const unsigned char digits[] = {
  8. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  9. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  10. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  11. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
  12. -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
  13. 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
  14. -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
  15. 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
  16. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  17. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  18. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  19. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  20. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  21. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  22. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  23. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  24. };
  25. uintmax_t strtoumax(const char *s1, char **p, int base)
  26. {
  27. const unsigned char *s = (void *)s1;
  28. size_t x1, z1;
  29. uintmax_t x, z=0;
  30. int sign = 0;
  31. int shift;
  32. if (!p) p = (char **)&s1;
  33. /* Initial whitespace */
  34. for (; isspace(*s); s++);
  35. /* Optional sign */
  36. if (*s == '-') sign = *s++;
  37. else if (*s == '+') s++;
  38. /* Default base 8, 10, or 16 depending on prefix */
  39. if (base == 0) {
  40. if (s[0] == '0') {
  41. if ((s[1]|32) == 'x') base = 16;
  42. else base = 8;
  43. } else {
  44. base = 10;
  45. }
  46. }
  47. if ((unsigned)base-2 > 36-2 || digits[*s]>=base) {
  48. *p = (char *)s1;
  49. errno = EINVAL;
  50. return 0;
  51. }
  52. /* Main loops. Only use big types if we have to. */
  53. if (base == 10) {
  54. for (x1=0; isdigit(*s) && x1<=SIZE_MAX/10-10; s++)
  55. x1 = 10*x1 + *s-'0';
  56. for (x=x1; isdigit(*s) && x<=UINTMAX_MAX/10-10; s++)
  57. x = 10*x + *s-'0';
  58. if (isdigit(*s)) {
  59. if (isdigit(s[1]) || 10*x>UINTMAX_MAX-(*s-'0'))
  60. goto overflow;
  61. x = 10*x + *s-'0';
  62. }
  63. } else if (!(base & base/2)) {
  64. if (base == 16) {
  65. if (s[0]=='0' && (s[1]|32)=='x' && digits[s[2]]<16)
  66. s+=2;
  67. shift=4;
  68. z1 = SIZE_MAX/16;
  69. z = UINTMAX_MAX/16;
  70. } else if (base == 8) {
  71. shift=3;
  72. z1 = SIZE_MAX/8;
  73. z = UINTMAX_MAX/8;
  74. } else if (base == 2) {
  75. shift=1;
  76. z1 = SIZE_MAX/2;
  77. z = UINTMAX_MAX/2;
  78. } else if (base == 4) {
  79. shift=2;
  80. z1 = SIZE_MAX/4;
  81. z = UINTMAX_MAX/4;
  82. } else /* if (base == 32) */ {
  83. shift=5;
  84. z1 = SIZE_MAX/32;
  85. z = UINTMAX_MAX/32;
  86. }
  87. for (x1=0; digits[*s]<base && x1<=z1; s++)
  88. x1 = (x1<<shift) + digits[*s];
  89. for (x=x1; digits[*s]<base && x<=z; s++)
  90. x = (x<<shift) + digits[*s];
  91. if (digits[*s] < base) goto overflow;
  92. } else {
  93. z1 = SIZE_MAX/base-base;
  94. for (x1=0; digits[*s]<base && x1<=z1; s++)
  95. x1 = x1*base + digits[*s];
  96. if (digits[*s]<base)
  97. z = UINTMAX_MAX/base-base;
  98. for (x=x1; digits[*s]<base && x<=z; s++)
  99. x = x*base + digits[*s];
  100. if (digits[*s] < base) {
  101. if (digits[s[1]]<base || x*base>UINTMAX_MAX-digits[*s])
  102. goto overflow;
  103. x = x*base + digits[*s];
  104. }
  105. }
  106. *p = (char *)s;
  107. return sign ? -x : x;
  108. overflow:
  109. for (; digits[*s] < base; s++);
  110. *p = (char *)s;
  111. errno = ERANGE;
  112. return UINTMAX_MAX;
  113. }