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 size27 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 536 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 set16[] = "0123456789ABCDEF";45 static int46 to16(mpint *b, char *buf, int len)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 int127 mpfmt(Fmt *fmt)128 {129 mpint *b;130 char *p;132 b = va_arg(fmt->args, mpint*);133 if(b == nil)134 return fmtstrcpy(fmt, "*");136 p = mptoa(b, fmt->prec, nil, 0);137 fmt->flags &= ~FmtPrec;139 if(p == nil)140 return fmtstrcpy(fmt, "*");141 else{142 fmtstrcpy(fmt, p);143 free(p);144 return 0;145 }146 }148 char*149 mptoa(mpint *b, int base, char *buf, int len)150 {151 char *out;152 int rv, alloced;154 alloced = 0;155 if(buf == nil){156 len = ((b->top+1)*Dbits+2)/3 + 1;157 buf = malloc(len);158 if(buf == nil)159 return nil;160 alloced = 1;161 }163 if(len < 2)164 return nil;166 out = buf;167 if(b->sign < 0){168 *out++ = '-';169 len--;170 }171 switch(base){172 case 64:173 rv = to64(b, out, len);174 break;175 case 32:176 rv = to32(b, out, len);177 break;178 default:179 case 16:180 rv = to16(b, out, len);181 break;182 case 10:183 rv = to10(b, out, len);184 break;185 }186 if(rv < 0){187 if(alloced)188 free(buf);189 return nil;190 }191 return buf;192 }