Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/libmp/port/mpfmt.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | 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 int
7
to64(mpint *b, char *buf, int len)
8
{
9
	uchar *p;
10
	int n, rv;
11
 
12
	p = nil;
13
	n = mptobe(b, nil, 0, &p);
14
	if(n < 0)
15
		return -1;
16
	rv = enc64(buf, len, p, n);
17
	free(p);
18
	return rv;
19
}
20
 
21
static int
22
to32(mpint *b, char *buf, int len)
23
{
24
	uchar *p;
25
	int n, rv;
26
 
27
	// leave room for a multiple of 5 buffer size
28
	n = b->top*Dbytes + 5;
29
	p = malloc(n);
30
	if(p == nil)
31
		return -1;
32
	n = mptobe(b, p, n, nil);
33
	if(n < 0)
34
		return -1;
35
 
36
	// round up buffer size, enc32 only accepts a multiple of 5
37
	if(n%5)
38
		n += 5 - (n%5);
39
	rv = enc32(buf, len, p, n);
40
	free(p);
41
	return rv;
42
}
43
 
44
static char set16[] = "0123456789ABCDEF";
45
 
46
static int
47
to16(mpint *b, char *buf, int len)
48
{
49
	mpdigit *p, x;
50
	int i, j;
51
	char *out, *eout;
52
 
53
	if(len < 1)
54
		return -1;
55
 
56
	out = buf;
57
	eout = buf+len;
58
	for(p = &b->p[b->top-1]; p >= b->p; p--){
59
		x = *p;
60
		for(i = Dbits-4; i >= 0; i -= 4){
61
			j = 0xf & (x>>i);
62
			if(j != 0 || out != buf){
63
				if(out >= eout)
64
					return -1;
65
				*out++ = set16[j];
66
			}
67
		}
68
	}
69
	if(out == buf)
70
		*out++ = '0';
71
	if(out >= eout)
72
		return -1;
73
	*out = 0;
74
	return 0;
75
}
76
 
77
static char*
78
modbillion(int rem, ulong r, char *out, char *buf)
79
{
80
	ulong rr;
81
	int i;
82
 
83
	for(i = 0; i < 9; i++){
84
		rr = r%10;
85
		r /= 10;
86
		if(out <= buf)
87
			return nil;
88
		*--out = '0' + rr;
89
		if(rem == 0 && r == 0)
90
			break;
91
	}
92
	return out;
93
}
94
 
95
static int
96
to10(mpint *b, char *buf, int len)
97
{
98
	mpint *d, *r, *billion;
99
	char *out;
100
 
101
	if(len < 1)
102
		return -1;
103
 
104
	d = mpcopy(b);
105
	r = mpnew(0);
106
	billion = uitomp(1000000000, nil);
107
	out = buf+len;
108
	*--out = 0;
109
	do {
110
		mpdiv(d, billion, d, r);
111
		out = modbillion(d->top, r->p[0], out, buf);
112
		if(out == nil)
113
			break;
114
	} while(d->top != 0);
115
	mpfree(d);
116
	mpfree(r);
117
	mpfree(billion);
118
 
119
	if(out == nil)
120
		return -1;
121
	len -= out-buf;
122
	if(out != buf)
123
		memmove(buf, out, len);
124
	return 0;
125
}
126
 
127
int
128
mpfmt(Fmt *fmt)
129
{
130
	mpint *b;
131
	char *p;
132
 
133
	b = va_arg(fmt->args, mpint*);
134
	if(b == nil)
135
		return fmtstrcpy(fmt, "*");
136
 
137
	p = mptoa(b, fmt->prec, nil, 0);
138
	fmt->flags &= ~FmtPrec;
139
 
140
	if(p == nil)
141
		return fmtstrcpy(fmt, "*");
142
	else{
143
		fmtstrcpy(fmt, p);
144
		free(p);
145
		return 0;
146
	}
147
}
148
 
149
char*
150
mptoa(mpint *b, int base, char *buf, int len)
151
{
152
	char *out;
153
	int rv, alloced;
154
 
155
	alloced = 0;
156
	if(buf == nil){
157
		len = ((b->top+1)*Dbits+2)/3 + 1;
158
		buf = malloc(len);
159
		if(buf == nil)
160
			return nil;
161
		alloced = 1;
162
	}
163
 
164
	if(len < 2)
165
		return nil;
166
 
167
	out = buf;
168
	if(b->sign < 0){
169
		*out++ = '-';
170
		len--;
171
	}
172
	switch(base){
173
	case 64:
174
		rv = to64(b, out, len);
175
		break;
176
	case 32:
177
		rv = to32(b, out, len);
178
		break;
179
	default:
180
	case 16:
181
		rv = to16(b, out, len);
182
		break;
183
	case 10:
184
		rv = to10(b, out, len);
185
		break;
186
	}
187
	if(rv < 0){
188
		if(alloced)
189
			free(buf);
190
		return nil;
191
	}
192
	return buf;
193
}