URI:
       tmpfmt.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tmpfmt.c (2986B)
       ---
            1 #include "os.h"
            2 #include <mp.h>
            3 #include "dat.h"
            4 
            5 static int
            6 to64(mpint *b, char *buf, int len)
            7 {
            8         uchar *p;
            9         int n, rv;
           10 
           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 }
           19 
           20 static int
           21 to32(mpint *b, char *buf, int len)
           22 {
           23         uchar *p;
           24         int n, rv;
           25 
           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;
           34 
           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 }
           42 
           43 static char upper16[] = "0123456789ABCDEF";
           44 static char lower16[] = "0123456789abcdef";
           45 static int
           46 to16(mpint *b, char *buf, int len, char *set16)
           47 {
           48         mpdigit *p, x;
           49         int i, j;
           50         char *out, *eout;
           51 
           52         if(len < 1)
           53                 return -1;
           54 
           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 }
           75 
           76 static char*
           77 modbillion(int rem, ulong r, char *out, char *buf)
           78 {
           79         ulong rr;
           80         int i;
           81 
           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 }
           93 
           94 static int
           95 to10(mpint *b, char *buf, int len)
           96 {
           97         mpint *d, *r, *billion;
           98         char *out;
           99 
          100         if(len < 1)
          101                 return -1;
          102 
          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);
          117 
          118         if(out == nil)
          119                 return -1;
          120         len -= out-buf;
          121         if(out != buf)
          122                 memmove(buf, out, len);
          123         return 0;
          124 }
          125 
          126 static char*
          127 _mptoa(mpint *b, int base, char *buf, int len, char *set16)
          128 {
          129         char *out;
          130         int rv, alloced;
          131 
          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         }
          140 
          141         if(len < 2)
          142                 return nil;
          143 
          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 }
          171 
          172 char*
          173 mptoa(mpint *b, int base, char *buf, int len)
          174 {
          175         return _mptoa(b, base, buf, len, upper16);
          176 }
          177 
          178 int
          179 mpfmt(Fmt *fmt)
          180 {
          181         mpint *b;
          182         char *p;
          183         char *set16;
          184 
          185         b = va_arg(fmt->args, mpint*);
          186         if(b == nil)
          187                 return fmtstrcpy(fmt, "*");
          188 
          189         set16 = upper16;
          190         if(fmt->flags & FmtLong)
          191                 set16 = lower16;
          192         p = _mptoa(b, fmt->prec, nil, 0, set16);
          193         fmt->flags &= ~FmtPrec;
          194 
          195         if(p == nil)
          196                 return fmtstrcpy(fmt, "*");
          197         else{
          198                 fmtstrcpy(fmt, p);
          199                 free(p);
          200                 return 0;
          201         }
          202 }