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