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