summaryrefslogtreecommitdiff
path: root/sys/src/libmp/port/strtomp.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2016-01-03 22:43:44 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2016-01-03 22:43:44 +0100
commitd30b160fe3b595c071d37345c51b35fffb2ad30c (patch)
tree322f1664efe88d03b7d50b5aadbce06f3352af9b /sys/src/libmp/port/strtomp.c
parent39f18c9d88f52a22373790dec5721fa3521d3f00 (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.c106
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