strtoull.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include <u.h>
  2. #include <libc.h>
  3. #define UVLONG_MAX (1LL<<63)
  4. uvlong
  5. strtoull(char *nptr, char **endptr, int base)
  6. {
  7. char *p;
  8. uvlong n, nn, m;
  9. int c, ovfl, v, neg, ndig;
  10. p = nptr;
  11. neg = 0;
  12. n = 0;
  13. ndig = 0;
  14. ovfl = 0;
  15. /*
  16. * White space
  17. */
  18. for(;; p++) {
  19. switch(*p) {
  20. case ' ':
  21. case '\t':
  22. case '\n':
  23. case '\f':
  24. case '\r':
  25. case '\v':
  26. continue;
  27. }
  28. break;
  29. }
  30. /*
  31. * Sign
  32. */
  33. if(*p == '-' || *p == '+')
  34. if(*p++ == '-')
  35. neg = 1;
  36. /*
  37. * Base
  38. */
  39. if(base == 0) {
  40. base = 10;
  41. if(*p == '0') {
  42. base = 8;
  43. if(p[1] == 'x' || p[1] == 'X'){
  44. p += 2;
  45. base = 16;
  46. }
  47. }
  48. } else
  49. if(base == 16 && *p == '0') {
  50. if(p[1] == 'x' || p[1] == 'X')
  51. p += 2;
  52. } else
  53. if(base < 0 || 36 < base)
  54. goto Return;
  55. /*
  56. * Non-empty sequence of digits
  57. */
  58. m = UVLONG_MAX/base;
  59. for(;; p++,ndig++) {
  60. c = *p;
  61. v = base;
  62. if('0' <= c && c <= '9')
  63. v = c - '0';
  64. else
  65. if('a' <= c && c <= 'z')
  66. v = c - 'a' + 10;
  67. else
  68. if('A' <= c && c <= 'Z')
  69. v = c - 'A' + 10;
  70. if(v >= base)
  71. break;
  72. if(n > m)
  73. ovfl = 1;
  74. nn = n*base + v;
  75. if(nn < n)
  76. ovfl = 1;
  77. n = nn;
  78. }
  79. Return:
  80. if(ndig == 0)
  81. p = nptr;
  82. if(endptr)
  83. *endptr = p;
  84. if(ovfl)
  85. return UVLONG_MAX;
  86. if(neg)
  87. return -n;
  88. return n;
  89. }