strtomp.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 }