ref: 20488fc4915662e0ec50bb8c4ebc2609d6e110b4
dir: /3rd/mp/strtomp.c/
#include "platform.h" static const char* frompow2(const char *a, mpint *b, int s) { const char *p, *next; mpdigit x; uint32_t i; i = 1<<s; for(p = a; (dec16chr(*p) & 255) < i; p++) ; mpbits(b, (p-a)*s); b->top = 0; next = p; while(p > a){ x = 0; for(i = 0; i < Dbits; i += s){ if(p <= a) break; x |= dec16chr(*--p)<<i; } b->p[b->top++] = x; } return next; } static const char* from8(const char *a, mpint *b) { const char *p, *next; mpdigit x, y; int i; for(p = a; ((*p - '0') & 255) < 8; p++) ; mpbits(b, (p-a)*3); b->top = 0; next = p; i = 0; x = y = 0; while(p > a){ y = *--p - '0'; x |= y << i; i += 3; if(i >= Dbits){ Digout: i -= Dbits; b->p[b->top++] = x; x = y >> (3-i); } } if(i > 0) goto Digout; return next; } static uint32_t mppow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; static const char* from10(const char *a, mpint *b) { uint32_t x, y; mpint *pow, *r; int i; pow = mpnew(0); r = mpnew(0); b->top = 0; for(;;){ // do a billion at a time in native arithmetic x = 0; for(i = 0; i < 9; i++){ y = *a - '0'; if(y > 9) break; a++; x *= 10; x += y; } if(i == 0) break; // accumulate into mpint uitomp(mppow10[i], pow); uitomp(x, r); mpmul(b, pow, b); mpadd(b, r, b); if(i < 9) break; } mpfree(pow); mpfree(r); return a; } mpint* strtomp(const char *a, char **pp, int base, mpint *b) { int sign; const char *e; if(b == nil){ b = mpnew(0); } while(*a==' ' || *a=='\t') a++; sign = 1; for(;; a++){ switch(*a){ case '-': sign *= -1; continue; } break; } if(base == 0){ base = 10; if(a[0] == '0'){ if(a[1] == 'x' || a[1] == 'X') { a += 2; base = 16; } else if(a[1] == 'b' || a[1] == 'B') { a += 2; base = 2; } else if(a[1] >= '0' && a[1] <= '7') { a++; base = 8; } } } switch(base){ case 2: e = frompow2(a, b, 1); break; case 4: e = frompow2(a, b, 2); break; case 8: e = from8(a, b); break; case 10: e = from10(a, b); break; case 16: e = frompow2(a, b, 4); break; default: abort(); return nil; } if(pp != nil) *pp = (char*)e; // if no characters parsed, there wasn't a number to convert if(e == a) return nil; b->sign = sign; return mpnorm(b); }