intparse.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include <stdint.h>
  2. #include <limits.h>
  3. #include <stdlib.h>
  4. #include <errno.h>
  5. #include "intparse.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. #define SLIM (UINT_MAX/36-1)
  26. int __intparse(struct intparse *v, const void *buf, size_t n)
  27. {
  28. const unsigned char *s = buf;
  29. int d, b = v->base;
  30. uintmax_t llim;
  31. v->cnt += n;
  32. for (; n; n--, s++) switch (v->state) {
  33. case 0:
  34. v->err = EINVAL;
  35. v->state++;
  36. if (*s=='+' || *s=='-') {
  37. v->neg = *s=='-';
  38. continue;
  39. }
  40. case 1:
  41. v->state++;
  42. if (*s=='0' && (!b || b==16)) continue;
  43. if (!b) v->base = b = 10;
  44. v->state++;
  45. goto firstdigit;
  46. case 2:
  47. v->state++;
  48. if ((!b || b==16) && (*s|32) == 'x') {
  49. v->err = 0;
  50. v->base = b = 16;
  51. continue;
  52. }
  53. if (!b) v->base = b = 8;
  54. goto seconddigit;
  55. case 3:
  56. firstdigit:
  57. if (digits[*s] >= b) {
  58. n++;
  59. goto finished;
  60. }
  61. seconddigit:
  62. v->err = 0;
  63. v->state++;
  64. case 4:
  65. if (b==10) {
  66. for (; n && *s-'0'<10U && v->small<=SLIM; n--, s++)
  67. v->small = v->small * 10 + (*s-'0');
  68. } else if ((b&-b) == b) {
  69. /* Compute bitshift for power-of-two bases
  70. * using a De Bruijn B(2,3) sequence. */
  71. int bs = "\0\1\2\4\7\3\6\5"[(0x17*b)>>5&7];
  72. for (; n && (d=digits[*s])<b && v->small<=SLIM; n--, s++)
  73. v->small = (v->small<<bs) + d;
  74. } else {
  75. for (; n && (d=digits[*s])<b && v->small<=SLIM; n--, s++)
  76. v->small = v->small * b + d;
  77. }
  78. if (!n) return 1;
  79. v->state++;
  80. v->val = v->small;
  81. case 5:
  82. if (b==10) {
  83. for (; n && *s-'0'<10U && v->val<=UINTMAX_MAX/10 && (*s-'0')<=UINTMAX_MAX-10*v->val; n--, s++)
  84. v->val = v->val * 10 + (*s-'0');
  85. } else if ((b&-b) == b) {
  86. int bs = "\0\1\2\4\7\3\6\5"[(0x17*b)>>5&7];
  87. llim = UINTMAX_MAX>>bs;
  88. for (; n && (d=digits[*s])<b && v->val<=llim; n--, s++)
  89. v->val = (v->val<<bs) + d;
  90. } else {
  91. llim = UINTMAX_MAX/b;
  92. for (; n && (d=digits[*s])<b && v->val<=llim && d<=UINTMAX_MAX-b*v->val; n--, s++)
  93. v->val = v->val * b + d;
  94. }
  95. if (!n) return 1;
  96. if (d >= b) goto finished;
  97. v->state++;
  98. case 6:
  99. if (n && digits[*s]<b) {
  100. v->err = ERANGE;
  101. v->val = UINTMAX_MAX;
  102. n--; s++;
  103. for (; n && digits[*s]<b; n--, s++);
  104. }
  105. if (!n) return 1;
  106. goto finished;
  107. }
  108. return 1;
  109. finished:
  110. v->cnt -= n;
  111. return 0;
  112. }