xref: /plan9/sys/src/libc/port/u64.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier 
49a747e4fSDavid du Colombier enum {
59a747e4fSDavid du Colombier 	INVAL=	255
69a747e4fSDavid du Colombier };
79a747e4fSDavid du Colombier 
89a747e4fSDavid du Colombier static uchar t64d[256] = {
99a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
109a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
119a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,   62,INVAL,INVAL,INVAL,   63,
129a747e4fSDavid du Colombier       52,   53,   54,   55,   56,   57,   58,   59,   60,   61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
139a747e4fSDavid du Colombier    INVAL,    0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,
149a747e4fSDavid du Colombier       15,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,INVAL,INVAL,INVAL,INVAL,INVAL,
159a747e4fSDavid du Colombier    INVAL,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   40,
169a747e4fSDavid du Colombier       41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,INVAL,INVAL,INVAL,INVAL,INVAL,
179a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
189a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
199a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
209a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
219a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
229a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
239a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
249a747e4fSDavid du Colombier    INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL
259a747e4fSDavid du Colombier };
269a747e4fSDavid du Colombier static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
279a747e4fSDavid du Colombier 
289a747e4fSDavid du Colombier int
dec64(uchar * out,int lim,char * in,int n)299a747e4fSDavid du Colombier dec64(uchar *out, int lim, char *in, int n)
309a747e4fSDavid du Colombier {
319a747e4fSDavid du Colombier 	ulong b24;
329a747e4fSDavid du Colombier 	uchar *start = out;
339a747e4fSDavid du Colombier 	uchar *e = out + lim;
349a747e4fSDavid du Colombier 	int i, c;
359a747e4fSDavid du Colombier 
369a747e4fSDavid du Colombier 	b24 = 0;
379a747e4fSDavid du Colombier 	i = 0;
389a747e4fSDavid du Colombier 	while(n-- > 0){
399a747e4fSDavid du Colombier 
409a747e4fSDavid du Colombier 		c = t64d[*(uchar*)in++];
419a747e4fSDavid du Colombier 		if(c == INVAL)
429a747e4fSDavid du Colombier 			continue;
439a747e4fSDavid du Colombier 		switch(i){
449a747e4fSDavid du Colombier 		case 0:
459a747e4fSDavid du Colombier 			b24 = c<<18;
469a747e4fSDavid du Colombier 			break;
479a747e4fSDavid du Colombier 		case 1:
489a747e4fSDavid du Colombier 			b24 |= c<<12;
499a747e4fSDavid du Colombier 			break;
509a747e4fSDavid du Colombier 		case 2:
519a747e4fSDavid du Colombier 			b24 |= c<<6;
529a747e4fSDavid du Colombier 			break;
539a747e4fSDavid du Colombier 		case 3:
549a747e4fSDavid du Colombier 			if(out + 3 > e)
559a747e4fSDavid du Colombier 				goto exhausted;
569a747e4fSDavid du Colombier 
579a747e4fSDavid du Colombier 			b24 |= c;
589a747e4fSDavid du Colombier 			*out++ = b24>>16;
599a747e4fSDavid du Colombier 			*out++ = b24>>8;
609a747e4fSDavid du Colombier 			*out++ = b24;
619a747e4fSDavid du Colombier 			i = -1;
629a747e4fSDavid du Colombier 			break;
639a747e4fSDavid du Colombier 		}
649a747e4fSDavid du Colombier 		i++;
659a747e4fSDavid du Colombier 	}
669a747e4fSDavid du Colombier 	switch(i){
679a747e4fSDavid du Colombier 	case 2:
689a747e4fSDavid du Colombier 		if(out + 1 > e)
699a747e4fSDavid du Colombier 			goto exhausted;
709a747e4fSDavid du Colombier 		*out++ = b24>>16;
719a747e4fSDavid du Colombier 		break;
729a747e4fSDavid du Colombier 	case 3:
739a747e4fSDavid du Colombier 		if(out + 2 > e)
749a747e4fSDavid du Colombier 			goto exhausted;
759a747e4fSDavid du Colombier 		*out++ = b24>>16;
769a747e4fSDavid du Colombier 		*out++ = b24>>8;
779a747e4fSDavid du Colombier 		break;
789a747e4fSDavid du Colombier 	}
799a747e4fSDavid du Colombier exhausted:
809a747e4fSDavid du Colombier 	return out - start;
819a747e4fSDavid du Colombier }
829a747e4fSDavid du Colombier 
839a747e4fSDavid du Colombier int
enc64(char * out,int lim,uchar * in,int n)849a747e4fSDavid du Colombier enc64(char *out, int lim, uchar *in, int n)
859a747e4fSDavid du Colombier {
869a747e4fSDavid du Colombier 	int i;
879a747e4fSDavid du Colombier 	ulong b24;
889a747e4fSDavid du Colombier 	char *start = out;
899a747e4fSDavid du Colombier 	char *e = out + lim;
909a747e4fSDavid du Colombier 
919a747e4fSDavid du Colombier 	for(i = n/3; i > 0; i--){
929a747e4fSDavid du Colombier 		b24 = (*in++)<<16;
939a747e4fSDavid du Colombier 		b24 |= (*in++)<<8;
949a747e4fSDavid du Colombier 		b24 |= *in++;
95*3ff48bf5SDavid du Colombier 		if(out + 4 >= e)
969a747e4fSDavid du Colombier 			goto exhausted;
979a747e4fSDavid du Colombier 		*out++ = t64e[(b24>>18)];
989a747e4fSDavid du Colombier 		*out++ = t64e[(b24>>12)&0x3f];
999a747e4fSDavid du Colombier 		*out++ = t64e[(b24>>6)&0x3f];
1009a747e4fSDavid du Colombier 		*out++ = t64e[(b24)&0x3f];
1019a747e4fSDavid du Colombier 	}
1029a747e4fSDavid du Colombier 
1039a747e4fSDavid du Colombier 	switch(n%3){
1049a747e4fSDavid du Colombier 	case 2:
1059a747e4fSDavid du Colombier 		b24 = (*in++)<<16;
1069a747e4fSDavid du Colombier 		b24 |= (*in)<<8;
1079a747e4fSDavid du Colombier 		if(out + 4 >= e)
1089a747e4fSDavid du Colombier 			goto exhausted;
1099a747e4fSDavid du Colombier 		*out++ = t64e[(b24>>18)];
1109a747e4fSDavid du Colombier 		*out++ = t64e[(b24>>12)&0x3f];
1119a747e4fSDavid du Colombier 		*out++ = t64e[(b24>>6)&0x3f];
1129a747e4fSDavid du Colombier 		*out++ = '=';
1139a747e4fSDavid du Colombier 		break;
1149a747e4fSDavid du Colombier 	case 1:
1159a747e4fSDavid du Colombier 		b24 = (*in)<<16;
1169a747e4fSDavid du Colombier 		if(out + 4 >= e)
1179a747e4fSDavid du Colombier 			goto exhausted;
1189a747e4fSDavid du Colombier 		*out++ = t64e[(b24>>18)];
1199a747e4fSDavid du Colombier 		*out++ = t64e[(b24>>12)&0x3f];
1209a747e4fSDavid du Colombier 		*out++ = '=';
1219a747e4fSDavid du Colombier 		*out++ = '=';
1229a747e4fSDavid du Colombier 		break;
1239a747e4fSDavid du Colombier 	}
1249a747e4fSDavid du Colombier exhausted:
1259a747e4fSDavid du Colombier 	*out = 0;
1269a747e4fSDavid du Colombier 	return out - start;
1279a747e4fSDavid du Colombier }
128