| #include "os.h" |
| #include <mp.h> |
| #include "dat.h" |
| |
| static struct { |
| int inited; |
| |
| uchar t64[256]; |
| uchar t32[256]; |
| uchar t16[256]; |
| uchar t10[256]; |
| } tab; |
| |
| enum { |
| INVAL= 255 |
| }; |
| |
| static char set64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| static char set32[] = "23456789abcdefghijkmnpqrstuvwxyz"; |
| static char set16[] = "0123456789ABCDEF0123456789abcdef"; |
| static char set10[] = "0123456789"; |
| |
| static void |
| init(void) |
| { |
| char *p; |
| |
| memset(tab.t64, INVAL, sizeof(tab.t64)); |
| memset(tab.t32, INVAL, sizeof(tab.t32)); |
| memset(tab.t16, INVAL, sizeof(tab.t16)); |
| memset(tab.t10, INVAL, sizeof(tab.t10)); |
| |
| for(p = set64; *p; p++) |
| tab.t64[(uchar)*p] = p-set64; |
| for(p = set32; *p; p++) |
| tab.t32[(uchar)*p] = p-set32; |
| for(p = set16; *p; p++) |
| tab.t16[(uchar)*p] = (p-set16)%16; |
| for(p = set10; *p; p++) |
| tab.t10[(uchar)*p] = (p-set10); |
| |
| tab.inited = 1; |
| } |
| |
| static char* |
| from16(char *a, mpint *b) |
| { |
| char *p, *next; |
| int i; |
| mpdigit x; |
| |
| b->top = 0; |
| for(p = a; *p; p++) |
| if(tab.t16[*(uchar*)p] == INVAL) |
| break; |
| mpbits(b, (p-a)*4); |
| b->top = 0; |
| next = p; |
| while(p > a){ |
| x = 0; |
| for(i = 0; i < Dbits; i += 4){ |
| if(p <= a) |
| break; |
| x |= tab.t16[*(uchar*)--p]<<i; |
| } |
| b->p[b->top++] = x; |
| } |
| return next; |
| } |
| |
| static ulong mppow10[] = { |
| 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 |
| }; |
| |
| static char* |
| from10(char *a, mpint *b) |
| { |
| ulong 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 = tab.t10[*(uchar*)a]; |
| if(y == INVAL) |
| 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; |
| } |
| |
| static char* |
| from64(char *a, mpint *b) |
| { |
| char *buf = a; |
| uchar *p; |
| int n, m; |
| |
| for(; tab.t64[*(uchar*)a] != INVAL; a++) |
| ; |
| n = a-buf; |
| mpbits(b, n*6); |
| p = malloc(n); |
| if(p == nil) |
| return a; |
| m = dec64(p, n, buf, n); |
| betomp(p, m, b); |
| free(p); |
| return a; |
| } |
| |
| static char* |
| from32(char *a, mpint *b) |
| { |
| char *buf = a; |
| uchar *p; |
| int n, m; |
| |
| for(; tab.t64[*(uchar*)a] != INVAL; a++) |
| ; |
| n = a-buf; |
| mpbits(b, n*5); |
| p = malloc(n); |
| if(p == nil) |
| return a; |
| m = dec32(p, n, buf, n); |
| betomp(p, m, b); |
| free(p); |
| return a; |
| } |
| |
| mpint* |
| strtomp(char *a, char **pp, int base, mpint *b) |
| { |
| int sign; |
| char *e; |
| |
| if(b == nil) |
| b = mpnew(0); |
| |
| if(tab.inited == 0) |
| init(); |
| |
| while(*a==' ' || *a=='\t') |
| a++; |
| |
| sign = 1; |
| for(;; a++){ |
| switch(*a){ |
| case '-': |
| sign *= -1; |
| continue; |
| } |
| break; |
| } |
| |
| switch(base){ |
| case 10: |
| e = from10(a, b); |
| break; |
| default: |
| case 16: |
| e = from16(a, b); |
| break; |
| case 32: |
| e = from32(a, b); |
| break; |
| case 64: |
| e = from64(a, b); |
| break; |
| } |
| |
| /* if no characters parsed, there wasn't a number to convert */ |
| if(e == a) |
| return nil; |
| |
| mpnorm(b); |
| b->sign = sign; |
| if(pp != nil) |
| *pp = e; |
| |
| return b; |
| } |