xref: /plan9-contrib/sys/src/libmp/port/strtomp.c (revision f7db61556a577f91350f05658e9c0724969b02c3)
17dd7cddfSDavid du Colombier #include "os.h"
27dd7cddfSDavid du Colombier #include <mp.h>
37dd7cddfSDavid du Colombier #include <libsec.h>
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier 
67dd7cddfSDavid du Colombier static struct {
77dd7cddfSDavid du Colombier 	int	inited;
87dd7cddfSDavid du Colombier 
97dd7cddfSDavid du Colombier 	uchar	t64[256];
107dd7cddfSDavid du Colombier 	uchar	t32[256];
117dd7cddfSDavid du Colombier 	uchar	t16[256];
127dd7cddfSDavid du Colombier 	uchar	t10[256];
137dd7cddfSDavid du Colombier } tab;
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier enum {
167dd7cddfSDavid du Colombier 	INVAL=	255
177dd7cddfSDavid du Colombier };
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier static char set64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
207dd7cddfSDavid du Colombier static char set32[] = "23456789abcdefghijkmnpqrstuvwxyz";
217dd7cddfSDavid du Colombier static char set16[] = "0123456789ABCDEF0123456789abcdef";
227dd7cddfSDavid du Colombier static char set10[] = "0123456789";
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier static void
init(void)257dd7cddfSDavid du Colombier init(void)
267dd7cddfSDavid du Colombier {
277dd7cddfSDavid du Colombier 	char *p;
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier 	memset(tab.t64, INVAL, sizeof(tab.t64));
307dd7cddfSDavid du Colombier 	memset(tab.t32, INVAL, sizeof(tab.t32));
317dd7cddfSDavid du Colombier 	memset(tab.t16, INVAL, sizeof(tab.t16));
327dd7cddfSDavid du Colombier 	memset(tab.t10, INVAL, sizeof(tab.t10));
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier 	for(p = set64; *p; p++)
357dd7cddfSDavid du Colombier 		tab.t64[*p] = p-set64;
367dd7cddfSDavid du Colombier 	for(p = set32; *p; p++)
377dd7cddfSDavid du Colombier 		tab.t32[*p] = p-set32;
387dd7cddfSDavid du Colombier 	for(p = set16; *p; p++)
397dd7cddfSDavid du Colombier 		tab.t16[*p] = (p-set16)%16;
407dd7cddfSDavid du Colombier 	for(p = set10; *p; p++)
417dd7cddfSDavid du Colombier 		tab.t10[*p] = (p-set10);
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier 	tab.inited = 1;
447dd7cddfSDavid du Colombier }
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier static char*
from16(char * a,mpint * b)477dd7cddfSDavid du Colombier from16(char *a, mpint *b)
487dd7cddfSDavid du Colombier {
497dd7cddfSDavid du Colombier 	char *p, *next;
507dd7cddfSDavid du Colombier 	int i;
517dd7cddfSDavid du Colombier 	mpdigit x;
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier 	b->top = 0;
547dd7cddfSDavid du Colombier 	for(p = a; *p; p++)
55dc5a79c1SDavid du Colombier 		if(tab.t16[*(uchar*)p] == INVAL)
567dd7cddfSDavid du Colombier 			break;
5780ee5cbfSDavid du Colombier 	mpbits(b, (p-a)*4);
5880ee5cbfSDavid du Colombier 	b->top = 0;
597dd7cddfSDavid du Colombier 	next = p;
607dd7cddfSDavid du Colombier 	while(p > a){
617dd7cddfSDavid du Colombier 		x = 0;
627dd7cddfSDavid du Colombier 		for(i = 0; i < Dbits; i += 4){
637dd7cddfSDavid du Colombier 			if(p <= a)
647dd7cddfSDavid du Colombier 				break;
65dc5a79c1SDavid du Colombier 			x |= tab.t16[*(uchar*)--p]<<i;
667dd7cddfSDavid du Colombier 		}
677dd7cddfSDavid du Colombier 		b->p[b->top++] = x;
687dd7cddfSDavid du Colombier 	}
697dd7cddfSDavid du Colombier 	return next;
707dd7cddfSDavid du Colombier }
717dd7cddfSDavid du Colombier 
727dd7cddfSDavid du Colombier static ulong mppow10[] = {
737dd7cddfSDavid du Colombier 	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
747dd7cddfSDavid du Colombier };
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier static char*
from10(char * a,mpint * b)777dd7cddfSDavid du Colombier from10(char *a, mpint *b)
787dd7cddfSDavid du Colombier {
797dd7cddfSDavid du Colombier 	ulong x, y;
807dd7cddfSDavid du Colombier 	mpint *pow, *r;
817dd7cddfSDavid du Colombier 	int i;
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier 	pow = mpnew(0);
847dd7cddfSDavid du Colombier 	r = mpnew(0);
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier 	b->top = 0;
877dd7cddfSDavid du Colombier 	for(;;){
887dd7cddfSDavid du Colombier 		// do a billion at a time in native arithmetic
897dd7cddfSDavid du Colombier 		x = 0;
907dd7cddfSDavid du Colombier 		for(i = 0; i < 9; i++){
91dc5a79c1SDavid du Colombier 			y = tab.t10[*(uchar*)a];
927dd7cddfSDavid du Colombier 			if(y == INVAL)
937dd7cddfSDavid du Colombier 				break;
947dd7cddfSDavid du Colombier 			a++;
957dd7cddfSDavid du Colombier 			x *= 10;
967dd7cddfSDavid du Colombier 			x += y;
977dd7cddfSDavid du Colombier 		}
987dd7cddfSDavid du Colombier 		if(i == 0)
997dd7cddfSDavid du Colombier 			break;
1007dd7cddfSDavid du Colombier 
1017dd7cddfSDavid du Colombier 		// accumulate into mpint
1027dd7cddfSDavid du Colombier 		uitomp(mppow10[i], pow);
1037dd7cddfSDavid du Colombier 		uitomp(x, r);
1047dd7cddfSDavid du Colombier 		mpmul(b, pow, b);
1057dd7cddfSDavid du Colombier 		mpadd(b, r, b);
1067dd7cddfSDavid du Colombier 		if(i != 9)
1077dd7cddfSDavid du Colombier 			break;
1087dd7cddfSDavid du Colombier 	}
1097dd7cddfSDavid du Colombier 	mpfree(pow);
1107dd7cddfSDavid du Colombier 	mpfree(r);
1117dd7cddfSDavid du Colombier 	return a;
1127dd7cddfSDavid du Colombier }
1137dd7cddfSDavid du Colombier 
1147dd7cddfSDavid du Colombier static char*
from64(char * a,mpint * b)1157dd7cddfSDavid du Colombier from64(char *a, mpint *b)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier 	char *buf = a;
1187dd7cddfSDavid du Colombier 	uchar *p;
1197dd7cddfSDavid du Colombier 	int n, m;
1207dd7cddfSDavid du Colombier 
121dc5a79c1SDavid du Colombier 	for(; tab.t64[*(uchar*)a] != INVAL; a++)
1227dd7cddfSDavid du Colombier 		;
1237dd7cddfSDavid du Colombier 	n = a-buf;
12480ee5cbfSDavid du Colombier 	mpbits(b, n*6);
1257dd7cddfSDavid du Colombier 	p = malloc(n);
1267dd7cddfSDavid du Colombier 	if(p == nil)
1277dd7cddfSDavid du Colombier 		return a;
1287dd7cddfSDavid du Colombier 	m = dec64(p, n, buf, n);
1297dd7cddfSDavid du Colombier 	betomp(p, m, b);
1307dd7cddfSDavid du Colombier 	free(p);
1317dd7cddfSDavid du Colombier 	return a;
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier static char*
from32(char * a,mpint * b)1357dd7cddfSDavid du Colombier from32(char *a, mpint *b)
1367dd7cddfSDavid du Colombier {
1377dd7cddfSDavid du Colombier 	char *buf = a;
1387dd7cddfSDavid du Colombier 	uchar *p;
1397dd7cddfSDavid du Colombier 	int n, m;
1407dd7cddfSDavid du Colombier 
141dc5a79c1SDavid du Colombier 	for(; tab.t64[*(uchar*)a] != INVAL; a++)
1427dd7cddfSDavid du Colombier 		;
1437dd7cddfSDavid du Colombier 	n = a-buf;
14480ee5cbfSDavid du Colombier 	mpbits(b, n*5);
1457dd7cddfSDavid du Colombier 	p = malloc(n);
1467dd7cddfSDavid du Colombier 	if(p == nil)
147*f7db6155SDavid du Colombier 		return buf;
1487dd7cddfSDavid du Colombier 	m = dec32(p, n, buf, n);
149*f7db6155SDavid du Colombier 	if(m == -1)
150*f7db6155SDavid du Colombier 		a = buf;
151*f7db6155SDavid du Colombier 	else
1527dd7cddfSDavid du Colombier 		betomp(p, m, b);
1537dd7cddfSDavid du Colombier 	free(p);
1547dd7cddfSDavid du Colombier 	return a;
1557dd7cddfSDavid du Colombier }
1567dd7cddfSDavid du Colombier 
1577dd7cddfSDavid du Colombier mpint*
strtomp(char * a,char ** pp,int base,mpint * b)1587dd7cddfSDavid du Colombier strtomp(char *a, char **pp, int base, mpint *b)
1597dd7cddfSDavid du Colombier {
1607dd7cddfSDavid du Colombier 	int sign;
1617dd7cddfSDavid du Colombier 	char *e;
1627dd7cddfSDavid du Colombier 
1637dd7cddfSDavid du Colombier 	if(b == nil)
1647dd7cddfSDavid du Colombier 		b = mpnew(0);
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier 	if(tab.inited == 0)
1677dd7cddfSDavid du Colombier 		init();
1687dd7cddfSDavid du Colombier 
16980ee5cbfSDavid du Colombier 	while(*a==' ' || *a=='\t')
17080ee5cbfSDavid du Colombier 		a++;
17180ee5cbfSDavid du Colombier 
1727dd7cddfSDavid du Colombier 	sign = 1;
1737dd7cddfSDavid du Colombier 	for(;; a++){
1747dd7cddfSDavid du Colombier 		switch(*a){
1757dd7cddfSDavid du Colombier 		case '-':
1767dd7cddfSDavid du Colombier 			sign *= -1;
1777dd7cddfSDavid du Colombier 			continue;
1787dd7cddfSDavid du Colombier 		}
1797dd7cddfSDavid du Colombier 		break;
1807dd7cddfSDavid du Colombier 	}
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier 	switch(base){
1837dd7cddfSDavid du Colombier 	case 10:
1847dd7cddfSDavid du Colombier 		e = from10(a, b);
1857dd7cddfSDavid du Colombier 		break;
1867dd7cddfSDavid du Colombier 	default:
1877dd7cddfSDavid du Colombier 	case 16:
1887dd7cddfSDavid du Colombier 		e = from16(a, b);
1897dd7cddfSDavid du Colombier 		break;
1907dd7cddfSDavid du Colombier 	case 32:
1917dd7cddfSDavid du Colombier 		e = from32(a, b);
1927dd7cddfSDavid du Colombier 		break;
1937dd7cddfSDavid du Colombier 	case 64:
1947dd7cddfSDavid du Colombier 		e = from64(a, b);
1957dd7cddfSDavid du Colombier 		break;
1967dd7cddfSDavid du Colombier 	}
19780ee5cbfSDavid du Colombier 
19880ee5cbfSDavid du Colombier 	// if no characters parsed, there wasn't a number to convert
19980ee5cbfSDavid du Colombier 	if(e == a)
20080ee5cbfSDavid du Colombier 		return nil;
20180ee5cbfSDavid du Colombier 
2027dd7cddfSDavid du Colombier 	mpnorm(b);
2037dd7cddfSDavid du Colombier 	b->sign = sign;
2047dd7cddfSDavid du Colombier 	if(pp != nil)
2057dd7cddfSDavid du Colombier 		*pp = e;
2067dd7cddfSDavid du Colombier 
2077dd7cddfSDavid du Colombier 	return b;
2087dd7cddfSDavid du Colombier }
209