xref: /plan9/sys/src/libc/port/rune.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier #include	<u.h>
23e12c5d1SDavid du Colombier #include	<libc.h>
33e12c5d1SDavid du Colombier 
43e12c5d1SDavid du Colombier enum
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier 	Bit1	= 7,
73e12c5d1SDavid du Colombier 	Bitx	= 6,
83e12c5d1SDavid du Colombier 	Bit2	= 5,
93e12c5d1SDavid du Colombier 	Bit3	= 4,
103e12c5d1SDavid du Colombier 	Bit4	= 3,
113e12c5d1SDavid du Colombier 
123e12c5d1SDavid du Colombier 	T1	= ((1<<(Bit1+1))-1) ^ 0xFF,	/* 0000 0000 */
133e12c5d1SDavid du Colombier 	Tx	= ((1<<(Bitx+1))-1) ^ 0xFF,	/* 1000 0000 */
143e12c5d1SDavid du Colombier 	T2	= ((1<<(Bit2+1))-1) ^ 0xFF,	/* 1100 0000 */
153e12c5d1SDavid du Colombier 	T3	= ((1<<(Bit3+1))-1) ^ 0xFF,	/* 1110 0000 */
163e12c5d1SDavid du Colombier 	T4	= ((1<<(Bit4+1))-1) ^ 0xFF,	/* 1111 0000 */
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier 	Rune1	= (1<<(Bit1+0*Bitx))-1,		/* 0000 0000 0111 1111 */
193e12c5d1SDavid du Colombier 	Rune2	= (1<<(Bit2+1*Bitx))-1,		/* 0000 0111 1111 1111 */
203e12c5d1SDavid du Colombier 	Rune3	= (1<<(Bit3+2*Bitx))-1,		/* 1111 1111 1111 1111 */
213e12c5d1SDavid du Colombier 
223e12c5d1SDavid du Colombier 	Maskx	= (1<<Bitx)-1,			/* 0011 1111 */
233e12c5d1SDavid du Colombier 	Testx	= Maskx ^ 0xFF,			/* 1100 0000 */
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier 	Bad	= Runeerror,
263e12c5d1SDavid du Colombier };
273e12c5d1SDavid du Colombier 
283e12c5d1SDavid du Colombier int
293e12c5d1SDavid du Colombier chartorune(Rune *rune, char *str)
303e12c5d1SDavid du Colombier {
313e12c5d1SDavid du Colombier 	int c, c1, c2;
323e12c5d1SDavid du Colombier 	long l;
333e12c5d1SDavid du Colombier 
343e12c5d1SDavid du Colombier 	/*
353e12c5d1SDavid du Colombier 	 * one character sequence
363e12c5d1SDavid du Colombier 	 *	00000-0007F => T1
373e12c5d1SDavid du Colombier 	 */
383e12c5d1SDavid du Colombier 	c = *(uchar*)str;
393e12c5d1SDavid du Colombier 	if(c < Tx) {
403e12c5d1SDavid du Colombier 		*rune = c;
413e12c5d1SDavid du Colombier 		return 1;
423e12c5d1SDavid du Colombier 	}
433e12c5d1SDavid du Colombier 
443e12c5d1SDavid du Colombier 	/*
453e12c5d1SDavid du Colombier 	 * two character sequence
463e12c5d1SDavid du Colombier 	 *	0080-07FF => T2 Tx
473e12c5d1SDavid du Colombier 	 */
483e12c5d1SDavid du Colombier 	c1 = *(uchar*)(str+1) ^ Tx;
493e12c5d1SDavid du Colombier 	if(c1 & Testx)
503e12c5d1SDavid du Colombier 		goto bad;
513e12c5d1SDavid du Colombier 	if(c < T3) {
523e12c5d1SDavid du Colombier 		if(c < T2)
533e12c5d1SDavid du Colombier 			goto bad;
543e12c5d1SDavid du Colombier 		l = ((c << Bitx) | c1) & Rune2;
553e12c5d1SDavid du Colombier 		if(l <= Rune1)
563e12c5d1SDavid du Colombier 			goto bad;
573e12c5d1SDavid du Colombier 		*rune = l;
583e12c5d1SDavid du Colombier 		return 2;
593e12c5d1SDavid du Colombier 	}
603e12c5d1SDavid du Colombier 
613e12c5d1SDavid du Colombier 	/*
623e12c5d1SDavid du Colombier 	 * three character sequence
633e12c5d1SDavid du Colombier 	 *	0800-FFFF => T3 Tx Tx
643e12c5d1SDavid du Colombier 	 */
653e12c5d1SDavid du Colombier 	c2 = *(uchar*)(str+2) ^ Tx;
663e12c5d1SDavid du Colombier 	if(c2 & Testx)
673e12c5d1SDavid du Colombier 		goto bad;
683e12c5d1SDavid du Colombier 	if(c < T4) {
693e12c5d1SDavid du Colombier 		l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
703e12c5d1SDavid du Colombier 		if(l <= Rune2)
713e12c5d1SDavid du Colombier 			goto bad;
723e12c5d1SDavid du Colombier 		*rune = l;
733e12c5d1SDavid du Colombier 		return 3;
743e12c5d1SDavid du Colombier 	}
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier 	/*
773e12c5d1SDavid du Colombier 	 * bad decoding
783e12c5d1SDavid du Colombier 	 */
793e12c5d1SDavid du Colombier bad:
803e12c5d1SDavid du Colombier 	*rune = Bad;
813e12c5d1SDavid du Colombier 	return 1;
823e12c5d1SDavid du Colombier }
833e12c5d1SDavid du Colombier 
843e12c5d1SDavid du Colombier int
853e12c5d1SDavid du Colombier runetochar(char *str, Rune *rune)
863e12c5d1SDavid du Colombier {
873e12c5d1SDavid du Colombier 	long c;
883e12c5d1SDavid du Colombier 
893e12c5d1SDavid du Colombier 	/*
903e12c5d1SDavid du Colombier 	 * one character sequence
913e12c5d1SDavid du Colombier 	 *	00000-0007F => 00-7F
923e12c5d1SDavid du Colombier 	 */
933e12c5d1SDavid du Colombier 	c = *rune;
943e12c5d1SDavid du Colombier 	if(c <= Rune1) {
953e12c5d1SDavid du Colombier 		str[0] = c;
963e12c5d1SDavid du Colombier 		return 1;
973e12c5d1SDavid du Colombier 	}
983e12c5d1SDavid du Colombier 
993e12c5d1SDavid du Colombier 	/*
1003e12c5d1SDavid du Colombier 	 * two character sequence
1013e12c5d1SDavid du Colombier 	 *	0080-07FF => T2 Tx
1023e12c5d1SDavid du Colombier 	 */
1033e12c5d1SDavid du Colombier 	if(c <= Rune2) {
1043e12c5d1SDavid du Colombier 		str[0] = T2 | (c >> 1*Bitx);
1053e12c5d1SDavid du Colombier 		str[1] = Tx | (c & Maskx);
1063e12c5d1SDavid du Colombier 		return 2;
1073e12c5d1SDavid du Colombier 	}
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier 	/*
1103e12c5d1SDavid du Colombier 	 * three character sequence
1113e12c5d1SDavid du Colombier 	 *	0800-FFFF => T3 Tx Tx
1123e12c5d1SDavid du Colombier 	 */
1133e12c5d1SDavid du Colombier 	str[0] = T3 |  (c >> 2*Bitx);
1143e12c5d1SDavid du Colombier 	str[1] = Tx | ((c >> 1*Bitx) & Maskx);
1153e12c5d1SDavid du Colombier 	str[2] = Tx |  (c & Maskx);
1163e12c5d1SDavid du Colombier 	return 3;
1173e12c5d1SDavid du Colombier }
1183e12c5d1SDavid du Colombier 
1193e12c5d1SDavid du Colombier int
1203e12c5d1SDavid du Colombier runelen(long c)
1213e12c5d1SDavid du Colombier {
1223e12c5d1SDavid du Colombier 	Rune rune;
1233e12c5d1SDavid du Colombier 	char str[10];
1243e12c5d1SDavid du Colombier 
1253e12c5d1SDavid du Colombier 	rune = c;
1263e12c5d1SDavid du Colombier 	return runetochar(str, &rune);
1273e12c5d1SDavid du Colombier }
1283e12c5d1SDavid du Colombier 
1293e12c5d1SDavid du Colombier int
130*7dd7cddfSDavid du Colombier runenlen(Rune *r, int nrune)
131*7dd7cddfSDavid du Colombier {
132*7dd7cddfSDavid du Colombier 	int nb, c;
133*7dd7cddfSDavid du Colombier 
134*7dd7cddfSDavid du Colombier 	nb = 0;
135*7dd7cddfSDavid du Colombier 	while(nrune--) {
136*7dd7cddfSDavid du Colombier 		c = *r++;
137*7dd7cddfSDavid du Colombier 		if(c <= Rune1)
138*7dd7cddfSDavid du Colombier 			nb++;
139*7dd7cddfSDavid du Colombier 		else
140*7dd7cddfSDavid du Colombier 		if(c <= Rune2)
141*7dd7cddfSDavid du Colombier 			nb += 2;
142*7dd7cddfSDavid du Colombier 		else
143*7dd7cddfSDavid du Colombier 			nb += 3;
144*7dd7cddfSDavid du Colombier 	}
145*7dd7cddfSDavid du Colombier 	return nb;
146*7dd7cddfSDavid du Colombier }
147*7dd7cddfSDavid du Colombier 
148*7dd7cddfSDavid du Colombier int
1493e12c5d1SDavid du Colombier fullrune(char *str, int n)
1503e12c5d1SDavid du Colombier {
1513e12c5d1SDavid du Colombier 	int c;
1523e12c5d1SDavid du Colombier 
1533e12c5d1SDavid du Colombier 	if(n > 0) {
1543e12c5d1SDavid du Colombier 		c = *(uchar*)str;
1553e12c5d1SDavid du Colombier 		if(c < Tx)
1563e12c5d1SDavid du Colombier 			return 1;
1573e12c5d1SDavid du Colombier 		if(n > 1)
1583e12c5d1SDavid du Colombier 			if(c < T3 || n > 2)
1593e12c5d1SDavid du Colombier 				return 1;
1603e12c5d1SDavid du Colombier 	}
1613e12c5d1SDavid du Colombier 	return 0;
1623e12c5d1SDavid du Colombier }
163