#include "os.h"#include <mp.h>#include <libsec.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 voidinit(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[*p] = p-set64; for(p = set32; *p; p++) tab.t32[*p] = p-set32; for(p = set16; *p; p++) tab.t16[*p] = (p-set16)%16; for(p = set10; *p; p++) tab.t10[*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 buf; m = dec32(p, n, buf, n); if(m == -1) a = buf; else 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;}
#include "os.h"
#include <mp.h>
#include <libsec.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[*p] = p-set64;
for(p = set32; *p; p++)
tab.t32[*p] = p-set32;
for(p = set16; *p; p++)
tab.t16[*p] = (p-set16)%16;
for(p = set10; *p; p++)
tab.t10[*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 buf;
m = dec32(p, n, buf, n);
if(m == -1)
a = buf;
else
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;
}