diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-01-03 22:43:44 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-01-03 22:43:44 +0100 |
commit | d30b160fe3b595c071d37345c51b35fffb2ad30c (patch) | |
tree | 322f1664efe88d03b7d50b5aadbce06f3352af9b /sys/src/libmp/port/strtomp.c | |
parent | 39f18c9d88f52a22373790dec5721fa3521d3f00 (diff) |
libmp: support for c-style base prefixes for strtomp(), octal support
Diffstat (limited to 'sys/src/libmp/port/strtomp.c')
-rw-r--r-- | sys/src/libmp/port/strtomp.c | 106 |
1 files changed, 71 insertions, 35 deletions
diff --git a/sys/src/libmp/port/strtomp.c b/sys/src/libmp/port/strtomp.c index 59c7dd76b..b5e00f0ef 100644 --- a/sys/src/libmp/port/strtomp.c +++ b/sys/src/libmp/port/strtomp.c @@ -53,11 +53,13 @@ frompow2(char *a, mpint *b, int s) sn = 1<<s; for(p = a; *p; p++) - if((uchar)tab.t16[*(uchar*)p] >= sn) + if(tab.t16[*(uchar*)p] >= sn) break; - mpbits(b, (p-a)*4); + + mpbits(b, (p-a)*s); b->top = 0; next = p; + while(p > a){ x = 0; for(i = 0; i < Dbits; i += s){ @@ -70,6 +72,40 @@ frompow2(char *a, mpint *b, int s) return next; } +static char* +from8(char *a, mpint *b) +{ + char *p, *next; + mpdigit x, y; + int i; + + for(p = a; *p; p++) + if(tab.t10[*(uchar*)p] >= 8) + break; + + mpbits(b, (a-p)*3); + b->top = 0; + next = p; + + i = 0; + x = 0; + while(p > a){ + y = tab.t10[*(uchar*)--p]; + 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 ulong mppow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; @@ -113,42 +149,25 @@ from10(char *a, mpint *b) } static char* -from64(char *a, mpint *b) +fromdecx(char *a, mpint *b, uchar tab[256], int (*dec)(uchar*, int, char*, int)) { 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++) + b->top = 0; + for(; tab[*(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); + if(n > 0){ + p = malloc(n); + if(p == nil) + sysfatal("malloc: %r"); + m = (*dec)(p, n, buf, n); + if(m > 0) + betomp(p, m, b); + free(p); + } return a; } @@ -179,6 +198,21 @@ strtomp(char *a, char **pp, int base, mpint *b) break; } + if(base == 0){ + if(*a == '0'){ + a++; + if(*a == 'x' || *a == 'X') { + a++; + base = 16; + } else if(*a == 'b' || *a == 'B') { + a++; + base = 2; + } else + base = 8; + } else + base = 10; + } + switch(base){ case 2: e = frompow2(a, b, 1); @@ -187,21 +221,23 @@ strtomp(char *a, char **pp, int base, mpint *b) e = frompow2(a, b, 2); break; case 8: - e = frompow2(a, b, 3); + e = from8(a, b); break; case 10: e = from10(a, b); break; - default: case 16: e = frompow2(a, b, 4); break; case 32: - e = from32(a, b); + e = fromdecx(a, b, tab.t32, dec32); break; case 64: - e = from64(a, b); + e = fromdecx(a, b, tab.t64, dec64); break; + default: + abort(); + return nil; } // if no characters parsed, there wasn't a number to convert |