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