Blob
1 #include "os.h"2 #include <mp.h>3 #include <libsec.h>4 #include "dat.h"6 static int7 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 int22 to32(mpint *b, char *buf, int len)23 {24 uchar *p;25 int n, rv;27 // leave room for a multiple of 5 buffer size28 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 537 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 int47 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 int96 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;125 }127 int128 mpfmt(Fmt *fmt)129 {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;146 }147 }149 char*150 mptoa(mpint *b, int base, char *buf, int len)151 {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;162 }164 if(len < 2)165 return nil;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 }