xref: /plan9/sys/src/cmd/unix/drawterm/libmp/strtomp.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include "os.h"
2*8ccd4a63SDavid du Colombier #include <mp.h>
3*8ccd4a63SDavid du Colombier #include <libsec.h>
4*8ccd4a63SDavid du Colombier #include "dat.h"
5*8ccd4a63SDavid du Colombier 
6*8ccd4a63SDavid du Colombier static struct {
7*8ccd4a63SDavid du Colombier 	int	inited;
8*8ccd4a63SDavid du Colombier 
9*8ccd4a63SDavid du Colombier 	uchar	t64[256];
10*8ccd4a63SDavid du Colombier 	uchar	t32[256];
11*8ccd4a63SDavid du Colombier 	uchar	t16[256];
12*8ccd4a63SDavid du Colombier 	uchar	t10[256];
13*8ccd4a63SDavid du Colombier } tab;
14*8ccd4a63SDavid du Colombier 
15*8ccd4a63SDavid du Colombier enum {
16*8ccd4a63SDavid du Colombier 	INVAL=	255
17*8ccd4a63SDavid du Colombier };
18*8ccd4a63SDavid du Colombier 
19*8ccd4a63SDavid du Colombier static char set64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
20*8ccd4a63SDavid du Colombier static char set32[] = "23456789abcdefghijkmnpqrstuvwxyz";
21*8ccd4a63SDavid du Colombier static char set16[] = "0123456789ABCDEF0123456789abcdef";
22*8ccd4a63SDavid du Colombier static char set10[] = "0123456789";
23*8ccd4a63SDavid du Colombier 
24*8ccd4a63SDavid du Colombier static void
init(void)25*8ccd4a63SDavid du Colombier init(void)
26*8ccd4a63SDavid du Colombier {
27*8ccd4a63SDavid du Colombier 	char *p;
28*8ccd4a63SDavid du Colombier 
29*8ccd4a63SDavid du Colombier 	memset(tab.t64, INVAL, sizeof(tab.t64));
30*8ccd4a63SDavid du Colombier 	memset(tab.t32, INVAL, sizeof(tab.t32));
31*8ccd4a63SDavid du Colombier 	memset(tab.t16, INVAL, sizeof(tab.t16));
32*8ccd4a63SDavid du Colombier 	memset(tab.t10, INVAL, sizeof(tab.t10));
33*8ccd4a63SDavid du Colombier 
34*8ccd4a63SDavid du Colombier 	for(p = set64; *p; p++)
35*8ccd4a63SDavid du Colombier 		tab.t64[(uchar)*p] = p-set64;
36*8ccd4a63SDavid du Colombier 	for(p = set32; *p; p++)
37*8ccd4a63SDavid du Colombier 		tab.t32[(uchar)*p] = p-set32;
38*8ccd4a63SDavid du Colombier 	for(p = set16; *p; p++)
39*8ccd4a63SDavid du Colombier 		tab.t16[(uchar)*p] = (p-set16)%16;
40*8ccd4a63SDavid du Colombier 	for(p = set10; *p; p++)
41*8ccd4a63SDavid du Colombier 		tab.t10[(uchar)*p] = (p-set10);
42*8ccd4a63SDavid du Colombier 
43*8ccd4a63SDavid du Colombier 	tab.inited = 1;
44*8ccd4a63SDavid du Colombier }
45*8ccd4a63SDavid du Colombier 
46*8ccd4a63SDavid du Colombier static char*
from16(char * a,mpint * b)47*8ccd4a63SDavid du Colombier from16(char *a, mpint *b)
48*8ccd4a63SDavid du Colombier {
49*8ccd4a63SDavid du Colombier 	char *p, *next;
50*8ccd4a63SDavid du Colombier 	int i;
51*8ccd4a63SDavid du Colombier 	mpdigit x;
52*8ccd4a63SDavid du Colombier 
53*8ccd4a63SDavid du Colombier 	b->top = 0;
54*8ccd4a63SDavid du Colombier 	for(p = a; *p; p++)
55*8ccd4a63SDavid du Colombier 		if(tab.t16[(uchar)*p] == INVAL)
56*8ccd4a63SDavid du Colombier 			break;
57*8ccd4a63SDavid du Colombier 	mpbits(b, (p-a)*4);
58*8ccd4a63SDavid du Colombier 	b->top = 0;
59*8ccd4a63SDavid du Colombier 	next = p;
60*8ccd4a63SDavid du Colombier 	while(p > a){
61*8ccd4a63SDavid du Colombier 		x = 0;
62*8ccd4a63SDavid du Colombier 		for(i = 0; i < Dbits; i += 4){
63*8ccd4a63SDavid du Colombier 			if(p <= a)
64*8ccd4a63SDavid du Colombier 				break;
65*8ccd4a63SDavid du Colombier 			x |= tab.t16[(uchar)*--p]<<i;
66*8ccd4a63SDavid du Colombier 		}
67*8ccd4a63SDavid du Colombier 		b->p[b->top++] = x;
68*8ccd4a63SDavid du Colombier 	}
69*8ccd4a63SDavid du Colombier 	return next;
70*8ccd4a63SDavid du Colombier }
71*8ccd4a63SDavid du Colombier 
72*8ccd4a63SDavid du Colombier static ulong mppow10[] = {
73*8ccd4a63SDavid du Colombier 	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
74*8ccd4a63SDavid du Colombier };
75*8ccd4a63SDavid du Colombier 
76*8ccd4a63SDavid du Colombier static char*
from10(char * a,mpint * b)77*8ccd4a63SDavid du Colombier from10(char *a, mpint *b)
78*8ccd4a63SDavid du Colombier {
79*8ccd4a63SDavid du Colombier 	ulong x, y;
80*8ccd4a63SDavid du Colombier 	mpint *pow, *r;
81*8ccd4a63SDavid du Colombier 	int i;
82*8ccd4a63SDavid du Colombier 
83*8ccd4a63SDavid du Colombier 	pow = mpnew(0);
84*8ccd4a63SDavid du Colombier 	r = mpnew(0);
85*8ccd4a63SDavid du Colombier 
86*8ccd4a63SDavid du Colombier 	b->top = 0;
87*8ccd4a63SDavid du Colombier 	for(;;){
88*8ccd4a63SDavid du Colombier 		// do a billion at a time in native arithmetic
89*8ccd4a63SDavid du Colombier 		x = 0;
90*8ccd4a63SDavid du Colombier 		for(i = 0; i < 9; i++){
91*8ccd4a63SDavid du Colombier 			y = tab.t10[(uchar)*a];
92*8ccd4a63SDavid du Colombier 			if(y == INVAL)
93*8ccd4a63SDavid du Colombier 				break;
94*8ccd4a63SDavid du Colombier 			a++;
95*8ccd4a63SDavid du Colombier 			x *= 10;
96*8ccd4a63SDavid du Colombier 			x += y;
97*8ccd4a63SDavid du Colombier 		}
98*8ccd4a63SDavid du Colombier 		if(i == 0)
99*8ccd4a63SDavid du Colombier 			break;
100*8ccd4a63SDavid du Colombier 
101*8ccd4a63SDavid du Colombier 		// accumulate into mpint
102*8ccd4a63SDavid du Colombier 		uitomp(mppow10[i], pow);
103*8ccd4a63SDavid du Colombier 		uitomp(x, r);
104*8ccd4a63SDavid du Colombier 		mpmul(b, pow, b);
105*8ccd4a63SDavid du Colombier 		mpadd(b, r, b);
106*8ccd4a63SDavid du Colombier 		if(i != 9)
107*8ccd4a63SDavid du Colombier 			break;
108*8ccd4a63SDavid du Colombier 	}
109*8ccd4a63SDavid du Colombier 	mpfree(pow);
110*8ccd4a63SDavid du Colombier 	mpfree(r);
111*8ccd4a63SDavid du Colombier 	return a;
112*8ccd4a63SDavid du Colombier }
113*8ccd4a63SDavid du Colombier 
114*8ccd4a63SDavid du Colombier static char*
from64(char * a,mpint * b)115*8ccd4a63SDavid du Colombier from64(char *a, mpint *b)
116*8ccd4a63SDavid du Colombier {
117*8ccd4a63SDavid du Colombier 	char *buf = a;
118*8ccd4a63SDavid du Colombier 	uchar *p;
119*8ccd4a63SDavid du Colombier 	int n, m;
120*8ccd4a63SDavid du Colombier 
121*8ccd4a63SDavid du Colombier 	for(; tab.t64[(uchar)*a] != INVAL; a++)
122*8ccd4a63SDavid du Colombier 		;
123*8ccd4a63SDavid du Colombier 	n = a-buf;
124*8ccd4a63SDavid du Colombier 	mpbits(b, n*6);
125*8ccd4a63SDavid du Colombier 	p = malloc(n);
126*8ccd4a63SDavid du Colombier 	if(p == nil)
127*8ccd4a63SDavid du Colombier 		return a;
128*8ccd4a63SDavid du Colombier 	m = dec64(p, n, buf, n);
129*8ccd4a63SDavid du Colombier 	betomp(p, m, b);
130*8ccd4a63SDavid du Colombier 	free(p);
131*8ccd4a63SDavid du Colombier 	return a;
132*8ccd4a63SDavid du Colombier }
133*8ccd4a63SDavid du Colombier 
134*8ccd4a63SDavid du Colombier static char*
from32(char * a,mpint * b)135*8ccd4a63SDavid du Colombier from32(char *a, mpint *b)
136*8ccd4a63SDavid du Colombier {
137*8ccd4a63SDavid du Colombier 	char *buf = a;
138*8ccd4a63SDavid du Colombier 	uchar *p;
139*8ccd4a63SDavid du Colombier 	int n, m;
140*8ccd4a63SDavid du Colombier 
141*8ccd4a63SDavid du Colombier 	for(; tab.t64[(uchar)*a] != INVAL; a++)
142*8ccd4a63SDavid du Colombier 		;
143*8ccd4a63SDavid du Colombier 	n = a-buf;
144*8ccd4a63SDavid du Colombier 	mpbits(b, n*5);
145*8ccd4a63SDavid du Colombier 	p = malloc(n);
146*8ccd4a63SDavid du Colombier 	if(p == nil)
147*8ccd4a63SDavid du Colombier 		return a;
148*8ccd4a63SDavid du Colombier 	m = dec32(p, n, buf, n);
149*8ccd4a63SDavid du Colombier 	betomp(p, m, b);
150*8ccd4a63SDavid du Colombier 	free(p);
151*8ccd4a63SDavid du Colombier 	return a;
152*8ccd4a63SDavid du Colombier }
153*8ccd4a63SDavid du Colombier 
154*8ccd4a63SDavid du Colombier mpint*
strtomp(char * a,char ** pp,int base,mpint * b)155*8ccd4a63SDavid du Colombier strtomp(char *a, char **pp, int base, mpint *b)
156*8ccd4a63SDavid du Colombier {
157*8ccd4a63SDavid du Colombier 	int sign;
158*8ccd4a63SDavid du Colombier 	char *e;
159*8ccd4a63SDavid du Colombier 
160*8ccd4a63SDavid du Colombier 	if(b == nil)
161*8ccd4a63SDavid du Colombier 		b = mpnew(0);
162*8ccd4a63SDavid du Colombier 
163*8ccd4a63SDavid du Colombier 	if(tab.inited == 0)
164*8ccd4a63SDavid du Colombier 		init();
165*8ccd4a63SDavid du Colombier 
166*8ccd4a63SDavid du Colombier 	while(*a==' ' || *a=='\t')
167*8ccd4a63SDavid du Colombier 		a++;
168*8ccd4a63SDavid du Colombier 
169*8ccd4a63SDavid du Colombier 	sign = 1;
170*8ccd4a63SDavid du Colombier 	for(;; a++){
171*8ccd4a63SDavid du Colombier 		switch(*a){
172*8ccd4a63SDavid du Colombier 		case '-':
173*8ccd4a63SDavid du Colombier 			sign *= -1;
174*8ccd4a63SDavid du Colombier 			continue;
175*8ccd4a63SDavid du Colombier 		}
176*8ccd4a63SDavid du Colombier 		break;
177*8ccd4a63SDavid du Colombier 	}
178*8ccd4a63SDavid du Colombier 
179*8ccd4a63SDavid du Colombier 	switch(base){
180*8ccd4a63SDavid du Colombier 	case 10:
181*8ccd4a63SDavid du Colombier 		e = from10(a, b);
182*8ccd4a63SDavid du Colombier 		break;
183*8ccd4a63SDavid du Colombier 	default:
184*8ccd4a63SDavid du Colombier 	case 16:
185*8ccd4a63SDavid du Colombier 		e = from16(a, b);
186*8ccd4a63SDavid du Colombier 		break;
187*8ccd4a63SDavid du Colombier 	case 32:
188*8ccd4a63SDavid du Colombier 		e = from32(a, b);
189*8ccd4a63SDavid du Colombier 		break;
190*8ccd4a63SDavid du Colombier 	case 64:
191*8ccd4a63SDavid du Colombier 		e = from64(a, b);
192*8ccd4a63SDavid du Colombier 		break;
193*8ccd4a63SDavid du Colombier 	}
194*8ccd4a63SDavid du Colombier 
195*8ccd4a63SDavid du Colombier 	// if no characters parsed, there wasn't a number to convert
196*8ccd4a63SDavid du Colombier 	if(e == a)
197*8ccd4a63SDavid du Colombier 		return nil;
198*8ccd4a63SDavid du Colombier 
199*8ccd4a63SDavid du Colombier 	mpnorm(b);
200*8ccd4a63SDavid du Colombier 	b->sign = sign;
201*8ccd4a63SDavid du Colombier 	if(pp != nil)
202*8ccd4a63SDavid du Colombier 		*pp = e;
203*8ccd4a63SDavid du Colombier 
204*8ccd4a63SDavid du Colombier 	return b;
205*8ccd4a63SDavid du Colombier }
206