xref: /plan9/sys/src/cmd/unix/u9fs/rune.c (revision 82726826a7b3d40fb66339b4b0e95b60314f98b9)
19a747e4fSDavid du Colombier #include	<plan9.h>
29a747e4fSDavid du Colombier 
39a747e4fSDavid du Colombier char *argv0;
49a747e4fSDavid du Colombier enum
59a747e4fSDavid du Colombier {
69a747e4fSDavid du Colombier 	Bit1	= 7,
79a747e4fSDavid du Colombier 	Bitx	= 6,
89a747e4fSDavid du Colombier 	Bit2	= 5,
99a747e4fSDavid du Colombier 	Bit3	= 4,
109a747e4fSDavid du Colombier 	Bit4	= 3,
119a747e4fSDavid du Colombier 
129a747e4fSDavid du Colombier 	T1	= ((1<<(Bit1+1))-1) ^ 0xFF,	/* 0000 0000 */
139a747e4fSDavid du Colombier 	Tx	= ((1<<(Bitx+1))-1) ^ 0xFF,	/* 1000 0000 */
149a747e4fSDavid du Colombier 	T2	= ((1<<(Bit2+1))-1) ^ 0xFF,	/* 1100 0000 */
159a747e4fSDavid du Colombier 	T3	= ((1<<(Bit3+1))-1) ^ 0xFF,	/* 1110 0000 */
169a747e4fSDavid du Colombier 	T4	= ((1<<(Bit4+1))-1) ^ 0xFF,	/* 1111 0000 */
17*82726826SDavid du Colombier 	T5	= ((1<<(Bit5+1))-1) ^ 0xFF,	/* 1111 1000 */
189a747e4fSDavid du Colombier 
19*82726826SDavid du Colombier 	Rune1	= (1<<(Bit1+0*Bitx))-1,		/* 0000 0000 0000 0000 0111 1111 */
20*82726826SDavid du Colombier 	Rune2	= (1<<(Bit2+1*Bitx))-1,		/* 0000 0000 0000 0111 1111 1111 */
21*82726826SDavid du Colombier 	Rune3	= (1<<(Bit3+2*Bitx))-1,		/* 0000 0000 1111 1111 1111 1111 */
22*82726826SDavid du Colombier 	Rune4	= (1<<(Bit4+3*Bitx))-1,		/* 0001 1111 1111 1111 1111 1111 */
23*82726826SDavid du Colombier 
249a747e4fSDavid du Colombier 
259a747e4fSDavid du Colombier 	Maskx	= (1<<Bitx)-1,			/* 0011 1111 */
269a747e4fSDavid du Colombier 	Testx	= Maskx ^ 0xFF,			/* 1100 0000 */
279a747e4fSDavid du Colombier 
28*82726826SDavid du Colombier 	SurrogateMin	= 0xD800,
29*82726826SDavid du Colombier 	SurrogateMax	= 0xDFFF,
30*82726826SDavid du Colombier 
319a747e4fSDavid du Colombier 	Bad	= Runeerror
329a747e4fSDavid du Colombier };
339a747e4fSDavid du Colombier 
349a747e4fSDavid du Colombier int
chartorune(Rune * rune,char * str)359a747e4fSDavid du Colombier chartorune(Rune *rune, char *str)
369a747e4fSDavid du Colombier {
37*82726826SDavid du Colombier 	int c, c1, c2, c3;
389a747e4fSDavid du Colombier 	long l;
399a747e4fSDavid du Colombier 
409a747e4fSDavid du Colombier 	/*
419a747e4fSDavid du Colombier 	 * one character sequence
429a747e4fSDavid du Colombier 	 *	00000-0007F => T1
439a747e4fSDavid du Colombier 	 */
449a747e4fSDavid du Colombier 	c = *(uchar*)str;
459a747e4fSDavid du Colombier 	if(c < Tx) {
469a747e4fSDavid du Colombier 		*rune = c;
479a747e4fSDavid du Colombier 		return 1;
489a747e4fSDavid du Colombier 	}
499a747e4fSDavid du Colombier 
509a747e4fSDavid du Colombier 	/*
519a747e4fSDavid du Colombier 	 * two character sequence
52*82726826SDavid du Colombier 	 *	00080-007FF => T2 Tx
539a747e4fSDavid du Colombier 	 */
549a747e4fSDavid du Colombier 	c1 = *(uchar*)(str+1) ^ Tx;
559a747e4fSDavid du Colombier 	if(c1 & Testx)
569a747e4fSDavid du Colombier 		goto bad;
579a747e4fSDavid du Colombier 	if(c < T3) {
589a747e4fSDavid du Colombier 		if(c < T2)
599a747e4fSDavid du Colombier 			goto bad;
609a747e4fSDavid du Colombier 		l = ((c << Bitx) | c1) & Rune2;
619a747e4fSDavid du Colombier 		if(l <= Rune1)
629a747e4fSDavid du Colombier 			goto bad;
639a747e4fSDavid du Colombier 		*rune = l;
649a747e4fSDavid du Colombier 		return 2;
659a747e4fSDavid du Colombier 	}
669a747e4fSDavid du Colombier 
679a747e4fSDavid du Colombier 	/*
689a747e4fSDavid du Colombier 	 * three character sequence
69*82726826SDavid du Colombier 	 *	00800-0FFFF => T3 Tx Tx
709a747e4fSDavid du Colombier 	 */
719a747e4fSDavid du Colombier 	c2 = *(uchar*)(str+2) ^ Tx;
72*82726826SDavid du Colombier 
739a747e4fSDavid du Colombier 	if(c2 & Testx)
749a747e4fSDavid du Colombier 		goto bad;
759a747e4fSDavid du Colombier 	if(c < T4) {
769a747e4fSDavid du Colombier 		l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
779a747e4fSDavid du Colombier 		if(l <= Rune2)
789a747e4fSDavid du Colombier 			goto bad;
79*82726826SDavid du Colombier 		if (SurrogateMin <= l && l <= SurrogateMax)
80*82726826SDavid du Colombier 			goto bad;
819a747e4fSDavid du Colombier 		*rune = l;
829a747e4fSDavid du Colombier 		return 3;
839a747e4fSDavid du Colombier 	}
849a747e4fSDavid du Colombier 
859a747e4fSDavid du Colombier 	/*
86*82726826SDavid du Colombier 	 * four character sequence
87*82726826SDavid du Colombier 	 *	10000-10FFFF => T4 Tx Tx Tx
88*82726826SDavid du Colombier 	 */
89*82726826SDavid du Colombier 	if(UTFmax >= 4) {
90*82726826SDavid du Colombier 		c3 = *(uchar*)(str+3) ^ Tx;
91*82726826SDavid du Colombier 		if(c3 & Testx)
92*82726826SDavid du Colombier 			goto bad;
93*82726826SDavid du Colombier 		if(c < T5) {
94*82726826SDavid du Colombier 			l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
95*82726826SDavid du Colombier 			if(l <= Rune3)
96*82726826SDavid du Colombier 				goto bad;
97*82726826SDavid du Colombier 			if(l > Runemax)
98*82726826SDavid du Colombier 				goto bad;
99*82726826SDavid du Colombier 			*rune = l;
100*82726826SDavid du Colombier 			return 4;
101*82726826SDavid du Colombier 		}
102*82726826SDavid du Colombier 	}
103*82726826SDavid du Colombier 
104*82726826SDavid du Colombier 	/*
1059a747e4fSDavid du Colombier 	 * bad decoding
1069a747e4fSDavid du Colombier 	 */
1079a747e4fSDavid du Colombier bad:
1089a747e4fSDavid du Colombier 	*rune = Bad;
1099a747e4fSDavid du Colombier 	return 1;
1109a747e4fSDavid du Colombier }
1119a747e4fSDavid du Colombier 
1129a747e4fSDavid du Colombier int
runetochar(char * str,Rune * rune)1139a747e4fSDavid du Colombier runetochar(char *str, Rune *rune)
1149a747e4fSDavid du Colombier {
1159a747e4fSDavid du Colombier 	long c;
1169a747e4fSDavid du Colombier 
1179a747e4fSDavid du Colombier 	/*
1189a747e4fSDavid du Colombier 	 * one character sequence
1199a747e4fSDavid du Colombier 	 *	00000-0007F => 00-7F
1209a747e4fSDavid du Colombier 	 */
1219a747e4fSDavid du Colombier 	c = *rune;
1229a747e4fSDavid du Colombier 	if(c <= Rune1) {
1239a747e4fSDavid du Colombier 		str[0] = c;
1249a747e4fSDavid du Colombier 		return 1;
1259a747e4fSDavid du Colombier 	}
1269a747e4fSDavid du Colombier 
1279a747e4fSDavid du Colombier 	/*
1289a747e4fSDavid du Colombier 	 * two character sequence
1299a747e4fSDavid du Colombier 	 *	0080-07FF => T2 Tx
1309a747e4fSDavid du Colombier 	 */
1319a747e4fSDavid du Colombier 	if(c <= Rune2) {
1329a747e4fSDavid du Colombier 		str[0] = T2 | (c >> 1*Bitx);
1339a747e4fSDavid du Colombier 		str[1] = Tx | (c & Maskx);
1349a747e4fSDavid du Colombier 		return 2;
1359a747e4fSDavid du Colombier 	}
136*82726826SDavid du Colombier 	/*
137*82726826SDavid du Colombier 	 * If the Rune is out of range or a surrogate half, convert it to the error rune.
138*82726826SDavid du Colombier 	 * Do this test here because the error rune encodes to three bytes.
139*82726826SDavid du Colombier 	 * Doing it earlier would duplicate work, since an out of range
140*82726826SDavid du Colombier 	 * Rune wouldn't have fit in one or two bytes.
141*82726826SDavid du Colombier 	 */
142*82726826SDavid du Colombier 	if (c > Runemax)
143*82726826SDavid du Colombier 		c = Runeerror;
144*82726826SDavid du Colombier 	if (SurrogateMin <= c && c <= SurrogateMax)
145*82726826SDavid du Colombier 		c = Runeerror;
1469a747e4fSDavid du Colombier 
1479a747e4fSDavid du Colombier 	/*
1489a747e4fSDavid du Colombier 	 * three character sequence
1499a747e4fSDavid du Colombier 	 *	0800-FFFF => T3 Tx Tx
1509a747e4fSDavid du Colombier 	 */
151*82726826SDavid du Colombier 	if (c <= Rune3) {
1529a747e4fSDavid du Colombier 		str[0] = T3 |  (c >> 2*Bitx);
1539a747e4fSDavid du Colombier 		str[1] = Tx | ((c >> 1*Bitx) & Maskx);
1549a747e4fSDavid du Colombier 		str[2] = Tx |  (c & Maskx);
1559a747e4fSDavid du Colombier 		return 3;
1569a747e4fSDavid du Colombier 	}
1579a747e4fSDavid du Colombier 
158*82726826SDavid du Colombier 	/*
159*82726826SDavid du Colombier 	 * four character sequence (21-bit value)
160*82726826SDavid du Colombier 	 *     10000-1FFFFF => T4 Tx Tx Tx
161*82726826SDavid du Colombier 	 */
162*82726826SDavid du Colombier 	str[0] = T4 | (c >> 3*Bitx);
163*82726826SDavid du Colombier 	str[1] = Tx | ((c >> 2*Bitx) & Maskx);
164*82726826SDavid du Colombier 	str[2] = Tx | ((c >> 1*Bitx) & Maskx);
165*82726826SDavid du Colombier 	str[3] = Tx | (c & Maskx);
166*82726826SDavid du Colombier 	return 4;
167*82726826SDavid du Colombier }
168*82726826SDavid du Colombier 
1699a747e4fSDavid du Colombier int
runelen(long c)1709a747e4fSDavid du Colombier runelen(long c)
1719a747e4fSDavid du Colombier {
1729a747e4fSDavid du Colombier 	Rune rune;
1739a747e4fSDavid du Colombier 	char str[10];
1749a747e4fSDavid du Colombier 
1759a747e4fSDavid du Colombier 	rune = c;
1769a747e4fSDavid du Colombier 	return runetochar(str, &rune);
1779a747e4fSDavid du Colombier }
1789a747e4fSDavid du Colombier 
1799a747e4fSDavid du Colombier int
utflen(char * s)1809a747e4fSDavid du Colombier utflen(char *s)
1819a747e4fSDavid du Colombier {
1829a747e4fSDavid du Colombier 	int c;
1839a747e4fSDavid du Colombier 	long n;
1849a747e4fSDavid du Colombier 	Rune rune;
1859a747e4fSDavid du Colombier 
1869a747e4fSDavid du Colombier 	n = 0;
1879a747e4fSDavid du Colombier 	for(;;) {
1889a747e4fSDavid du Colombier 		c = *(uchar*)s;
1899a747e4fSDavid du Colombier 		if(c < Runeself) {
1909a747e4fSDavid du Colombier 			if(c == 0)
1919a747e4fSDavid du Colombier 				return n;
1929a747e4fSDavid du Colombier 			s++;
1939a747e4fSDavid du Colombier 		} else
1949a747e4fSDavid du Colombier 			s += chartorune(&rune, s);
1959a747e4fSDavid du Colombier 		n++;
1969a747e4fSDavid du Colombier 	}
1979a747e4fSDavid du Colombier 	return 0;
1989a747e4fSDavid du Colombier }
199