Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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*
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*
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*
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*
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*
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
}