Blob


1 #include "os.h"
2 #include <mp.h>
3 #include <libsec.h>
4 #include "dat.h"
6 static int
7 to64(mpint *b, char *buf, int len)
8 {
9 uchar *p;
10 int n, rv;
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 }
21 static int
22 to32(mpint *b, char *buf, int len)
23 {
24 uchar *p;
25 int n, rv;
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;
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 }
44 static char set16[] = "0123456789ABCDEF";
46 static int
47 to16(mpint *b, char *buf, int len)
48 {
49 mpdigit *p, x;
50 int i, j;
51 char *out, *eout;
53 if(len < 1)
54 return -1;
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 }
77 static char*
78 modbillion(int rem, ulong r, char *out, char *buf)
79 {
80 ulong rr;
81 int i;
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 }
95 static int
96 to10(mpint *b, char *buf, int len)
97 {
98 mpint *d, *r, *billion;
99 char *out;
101 if(len < 1)
102 return -1;
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);
119 if(out == nil)
120 return -1;
121 len -= out-buf;
122 if(out != buf)
123 memmove(buf, out, len);
124 return 0;
127 int
128 mpfmt(Fmt *fmt)
130 mpint *b;
131 char *p;
133 b = va_arg(fmt->args, mpint*);
134 if(b == nil)
135 return fmtstrcpy(fmt, "*");
137 p = mptoa(b, fmt->prec, nil, 0);
138 fmt->flags &= ~FmtPrec;
140 if(p == nil)
141 return fmtstrcpy(fmt, "*");
142 else{
143 fmtstrcpy(fmt, p);
144 free(p);
145 return 0;
149 char*
150 mptoa(mpint *b, int base, char *buf, int len)
152 char *out;
153 int rv, alloced;
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;
164 if(len < 2)
165 return nil;
167 out = buf;
168 if(b->sign < 0){
169 *out++ = '-';
170 len--;
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;
187 if(rv < 0){
188 if(alloced)
189 free(buf);
190 return nil;
192 return buf;