plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }