URI: 
       tstrtomp.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
       ---
       tstrtomp.c (3020B)
       ---
            1 #include "os.h"
            2 #include <mp.h>
            3 #include "dat.h"
            4 
            5 static struct {
            6         int        inited;
            7 
            8         uchar        t64[256];
            9         uchar        t32[256];
           10         uchar        t16[256];
           11         uchar        t10[256];
           12 } tab;
           13 
           14 enum {
           15         INVAL=        255
           16 };
           17 
           18 static char set64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
           19 static char set32[] = "23456789abcdefghijkmnpqrstuvwxyz";
           20 static char set16[] = "0123456789ABCDEF0123456789abcdef";
           21 static char set10[] = "0123456789";
           22 
           23 static void
           24 init(void)
           25 {
           26         char *p;
           27 
           28         memset(tab.t64, INVAL, sizeof(tab.t64));
           29         memset(tab.t32, INVAL, sizeof(tab.t32));
           30         memset(tab.t16, INVAL, sizeof(tab.t16));
           31         memset(tab.t10, INVAL, sizeof(tab.t10));
           32 
           33         for(p = set64; *p; p++)
           34                 tab.t64[(uchar)*p] = p-set64;
           35         for(p = set32; *p; p++)
           36                 tab.t32[(uchar)*p] = p-set32;
           37         for(p = set16; *p; p++)
           38                 tab.t16[(uchar)*p] = (p-set16)%16;
           39         for(p = set10; *p; p++)
           40                 tab.t10[(uchar)*p] = (p-set10);
           41 
           42         tab.inited = 1;
           43 }
           44 
           45 static char*
           46 from16(char *a, mpint *b)
           47 {
           48         char *p, *next;
           49         int i;
           50         mpdigit x;
           51 
           52         b->top = 0;
           53         for(p = a; *p; p++)
           54                 if(tab.t16[*(uchar*)p] == INVAL)
           55                         break;
           56         mpbits(b, (p-a)*4);
           57         b->top = 0;
           58         next = p;
           59         while(p > a){
           60                 x = 0;
           61                 for(i = 0; i < Dbits; i += 4){
           62                         if(p <= a)
           63                                 break;
           64                         x |= tab.t16[*(uchar*)--p]<<i;
           65                 }
           66                 b->p[b->top++] = x;
           67         }
           68         return next;
           69 }
           70 
           71 static ulong mppow10[] = {
           72         1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
           73 };
           74 
           75 static char*
           76 from10(char *a, mpint *b)
           77 {
           78         ulong x, y;
           79         mpint *pow, *r;
           80         int i;
           81 
           82         pow = mpnew(0);
           83         r = mpnew(0);
           84 
           85         b->top = 0;
           86         for(;;){
           87                 /* do a billion at a time in native arithmetic */
           88                 x = 0;
           89                 for(i = 0; i < 9; i++){
           90                         y = tab.t10[*(uchar*)a];
           91                         if(y == INVAL)
           92                                 break;
           93                         a++;
           94                         x *= 10;
           95                         x += y;
           96                 }
           97                 if(i == 0)
           98                         break;
           99 
          100                 /* accumulate into mpint */
          101                 uitomp(mppow10[i], pow);
          102                 uitomp(x, r);
          103                 mpmul(b, pow, b);
          104                 mpadd(b, r, b);
          105                 if(i != 9)
          106                         break;
          107         }
          108         mpfree(pow);
          109         mpfree(r);
          110         return a;
          111 }
          112 
          113 static char*
          114 from64(char *a, mpint *b)
          115 {
          116         char *buf = a;
          117         uchar *p;
          118         int n, m;
          119 
          120         for(; tab.t64[*(uchar*)a] != INVAL; a++)
          121                 ;
          122         n = a-buf;
          123         mpbits(b, n*6);
          124         p = malloc(n);
          125         if(p == nil)
          126                 return a;
          127         m = dec64(p, n, buf, n);
          128         betomp(p, m, b);
          129         free(p);
          130         return a;
          131 }
          132 
          133 static char*
          134 from32(char *a, mpint *b)
          135 {
          136         char *buf = a;
          137         uchar *p;
          138         int n, m;
          139 
          140         for(; tab.t64[*(uchar*)a] != INVAL; a++)
          141                 ;
          142         n = a-buf;
          143         mpbits(b, n*5);
          144         p = malloc(n);
          145         if(p == nil)
          146                 return a;
          147         m = dec32(p, n, buf, n);
          148         betomp(p, m, b);
          149         free(p);
          150         return a;
          151 }
          152 
          153 mpint*
          154 strtomp(char *a, char **pp, int base, mpint *b)
          155 {
          156         int sign;
          157         char *e;
          158 
          159         if(b == nil)
          160                 b = mpnew(0);
          161 
          162         if(tab.inited == 0)
          163                 init();
          164 
          165         while(*a==' ' || *a=='\t')
          166                 a++;
          167 
          168         sign = 1;
          169         for(;; a++){
          170                 switch(*a){
          171                 case '-':
          172                         sign *= -1;
          173                         continue;
          174                 }
          175                 break;
          176         }
          177 
          178         switch(base){
          179         case 10:
          180                 e = from10(a, b);
          181                 break;
          182         default:
          183         case 16:
          184                 e = from16(a, b);
          185                 break;
          186         case 32:
          187                 e = from32(a, b);
          188                 break;
          189         case 64:
          190                 e = from64(a, b);
          191                 break;
          192         }
          193 
          194         /* if no characters parsed, there wasn't a number to convert */
          195         if(e == a)
          196                 return nil;
          197 
          198         mpnorm(b);
          199         b->sign = sign;
          200         if(pp != nil)
          201                 *pp = e;
          202 
          203         return b;
          204 }