xref: /plan9-contrib/sys/src/cmd/rc/rune.c (revision c6df144405f586b73992827d584728dc975dff14)
1*c6df1444SDavid du Colombier #include "rc.h"
2*c6df1444SDavid du Colombier 
3*c6df1444SDavid du Colombier #define Bit(i) (7-(i))
4*c6df1444SDavid du Colombier /* N 0's preceded by i 1's, T(Bit(2)) is 1100 0000 */
5*c6df1444SDavid du Colombier #define T(i) (((1 << (Bit(i)+1))-1) ^ 0xFF)
6*c6df1444SDavid du Colombier /* 0000 0000 0000 0111 1111 1111 */
7*c6df1444SDavid du Colombier #define	RuneX(i) ((1 << (Bit(i) + ((i)-1)*Bitx))-1)
8*c6df1444SDavid du Colombier 
9*c6df1444SDavid du Colombier enum
10*c6df1444SDavid du Colombier {
11*c6df1444SDavid du Colombier 	Bitx	= Bit(1),
12*c6df1444SDavid du Colombier 
13*c6df1444SDavid du Colombier 	Tx	= T(1),			/* 1000 0000 */
14*c6df1444SDavid du Colombier 	Rune1 = (1<<(Bit(0)+0*Bitx))-1,	/* 0000 0000 0000 0000 0111 1111 */
15*c6df1444SDavid du Colombier 
16*c6df1444SDavid du Colombier 	Maskx	= (1<<Bitx)-1,		/* 0011 1111 */
17*c6df1444SDavid du Colombier 	Testx	= Maskx ^ 0xFF,		/* 1100 0000 */
18*c6df1444SDavid du Colombier 
19*c6df1444SDavid du Colombier 	SurrogateMin	= 0xD800,
20*c6df1444SDavid du Colombier 	SurrogateMax	= 0xDFFF,
21*c6df1444SDavid du Colombier 
22*c6df1444SDavid du Colombier 	Bad	= Runeerror,
23*c6df1444SDavid du Colombier };
24*c6df1444SDavid du Colombier 
25*c6df1444SDavid du Colombier int
chartorune(Rune * rune,char * str)26*c6df1444SDavid du Colombier chartorune(Rune *rune, char *str)
27*c6df1444SDavid du Colombier {
28*c6df1444SDavid du Colombier 	int c[UTFmax], i;
29*c6df1444SDavid du Colombier 	Rune l;
30*c6df1444SDavid du Colombier 
31*c6df1444SDavid du Colombier 	/*
32*c6df1444SDavid du Colombier 	 * N character sequence
33*c6df1444SDavid du Colombier 	 *	00000-0007F => T1
34*c6df1444SDavid du Colombier 	 *	00080-007FF => T2 Tx
35*c6df1444SDavid du Colombier 	 *	00800-0FFFF => T3 Tx Tx
36*c6df1444SDavid du Colombier 	 *	10000-10FFFF => T4 Tx Tx Tx
37*c6df1444SDavid du Colombier 	 */
38*c6df1444SDavid du Colombier 
39*c6df1444SDavid du Colombier 	c[0] = *(uchar*)(str);
40*c6df1444SDavid du Colombier 	if(c[0] < Tx){
41*c6df1444SDavid du Colombier 		*rune = c[0];
42*c6df1444SDavid du Colombier 		return 1;
43*c6df1444SDavid du Colombier 	}
44*c6df1444SDavid du Colombier 	l = c[0];
45*c6df1444SDavid du Colombier 
46*c6df1444SDavid du Colombier 	for(i = 1; i < UTFmax; i++) {
47*c6df1444SDavid du Colombier 		c[i] = *(uchar*)(str+i);
48*c6df1444SDavid du Colombier 		c[i] ^= Tx;
49*c6df1444SDavid du Colombier 		if(c[i] & Testx)
50*c6df1444SDavid du Colombier 			goto bad;
51*c6df1444SDavid du Colombier 		l = (l << Bitx) | c[i];
52*c6df1444SDavid du Colombier 		if(c[0] < T(i + 2)) {
53*c6df1444SDavid du Colombier 			l &= RuneX(i + 1);
54*c6df1444SDavid du Colombier 			if(i == 1) {
55*c6df1444SDavid du Colombier 				if(c[0] < T(2) || l <= Rune1)
56*c6df1444SDavid du Colombier 					goto bad;
57*c6df1444SDavid du Colombier 			} else if(l <= RuneX(i) || l > Runemax)
58*c6df1444SDavid du Colombier 				goto bad;
59*c6df1444SDavid du Colombier 			if (i == 2 && SurrogateMin <= l && l <= SurrogateMax)
60*c6df1444SDavid du Colombier 				goto bad;
61*c6df1444SDavid du Colombier 			*rune = l;
62*c6df1444SDavid du Colombier 			return i + 1;
63*c6df1444SDavid du Colombier 		}
64*c6df1444SDavid du Colombier 	}
65*c6df1444SDavid du Colombier 
66*c6df1444SDavid du Colombier 	/*
67*c6df1444SDavid du Colombier 	 * bad decoding
68*c6df1444SDavid du Colombier 	 */
69*c6df1444SDavid du Colombier bad:
70*c6df1444SDavid du Colombier 	*rune = Bad;
71*c6df1444SDavid du Colombier 	return 1;
72*c6df1444SDavid du Colombier }
73*c6df1444SDavid du Colombier 
74*c6df1444SDavid du Colombier int
runetochar(char * str,Rune * rune)75*c6df1444SDavid du Colombier runetochar(char *str, Rune *rune)
76*c6df1444SDavid du Colombier {
77*c6df1444SDavid du Colombier 	int i, j;
78*c6df1444SDavid du Colombier 	Rune c;
79*c6df1444SDavid du Colombier 
80*c6df1444SDavid du Colombier 	c = *rune;
81*c6df1444SDavid du Colombier 	if(c <= Rune1) {
82*c6df1444SDavid du Colombier 		str[0] = c;
83*c6df1444SDavid du Colombier 		return 1;
84*c6df1444SDavid du Colombier 	}
85*c6df1444SDavid du Colombier 
86*c6df1444SDavid du Colombier 	/*
87*c6df1444SDavid du Colombier 	 * one character sequence
88*c6df1444SDavid du Colombier 	 *	00000-0007F => 00-7F
89*c6df1444SDavid du Colombier 	 * two character sequence
90*c6df1444SDavid du Colombier 	 *	0080-07FF => T2 Tx
91*c6df1444SDavid du Colombier 	 * three character sequence
92*c6df1444SDavid du Colombier 	 *	0800-FFFF => T3 Tx Tx
93*c6df1444SDavid du Colombier 	 * four character sequence (21-bit value)
94*c6df1444SDavid du Colombier 	 *     10000-1FFFFF => T4 Tx Tx Tx
95*c6df1444SDavid du Colombier 	 * If the Rune is out of range or a surrogate half,
96*c6df1444SDavid du Colombier 	 * convert it to the error rune.
97*c6df1444SDavid du Colombier 	 * Do this test when i==3 because the error rune encodes to three bytes.
98*c6df1444SDavid du Colombier 	 * Doing it earlier would duplicate work, since an out of range
99*c6df1444SDavid du Colombier 	 * Rune wouldn't have fit in one or two bytes.
100*c6df1444SDavid du Colombier 	 */
101*c6df1444SDavid du Colombier 	for(i = 2; i < UTFmax + 1; i++){
102*c6df1444SDavid du Colombier 		if(i == 3){
103*c6df1444SDavid du Colombier 			if(c > Runemax)
104*c6df1444SDavid du Colombier 				c = Runeerror;
105*c6df1444SDavid du Colombier 			if(SurrogateMin <= c && c <= SurrogateMax)
106*c6df1444SDavid du Colombier 				c = Runeerror;
107*c6df1444SDavid du Colombier 		}
108*c6df1444SDavid du Colombier 		if (c <= RuneX(i) || i == UTFmax ) {
109*c6df1444SDavid du Colombier 			str[0] = T(i) |  (c >> (i - 1)*Bitx);
110*c6df1444SDavid du Colombier 			for(j = 1; j < i; j++)
111*c6df1444SDavid du Colombier 				str[j] = Tx | ((c >> (i - j - 1)*Bitx) & Maskx);
112*c6df1444SDavid du Colombier 			return i;
113*c6df1444SDavid du Colombier 		}
114*c6df1444SDavid du Colombier 	}
115*c6df1444SDavid du Colombier 	return UTFmax;
116*c6df1444SDavid du Colombier }
117*c6df1444SDavid du Colombier 
118*c6df1444SDavid du Colombier int
runelen(long c)119*c6df1444SDavid du Colombier runelen(long c)
120*c6df1444SDavid du Colombier {
121*c6df1444SDavid du Colombier 	Rune rune;
122*c6df1444SDavid du Colombier 	char str[10];
123*c6df1444SDavid du Colombier 
124*c6df1444SDavid du Colombier 	rune = c;
125*c6df1444SDavid du Colombier 	return runetochar(str, &rune);
126*c6df1444SDavid du Colombier }
127*c6df1444SDavid du Colombier 
128*c6df1444SDavid du Colombier int
runenlen(Rune * r,int nrune)129*c6df1444SDavid du Colombier runenlen(Rune *r, int nrune)
130*c6df1444SDavid du Colombier {
131*c6df1444SDavid du Colombier 	int nb, i;
132*c6df1444SDavid du Colombier 	Rune c;
133*c6df1444SDavid du Colombier 
134*c6df1444SDavid du Colombier 	nb = 0;
135*c6df1444SDavid du Colombier 	while(nrune--) {
136*c6df1444SDavid du Colombier 		c = *r++;
137*c6df1444SDavid du Colombier 		if(c <= Rune1){
138*c6df1444SDavid du Colombier 			nb++;
139*c6df1444SDavid du Colombier 		} else {
140*c6df1444SDavid du Colombier 			for(i = 2; i < UTFmax + 1; i++)
141*c6df1444SDavid du Colombier 				if(c <= RuneX(i) || i == UTFmax){
142*c6df1444SDavid du Colombier 					nb += i;
143*c6df1444SDavid du Colombier 					break;
144*c6df1444SDavid du Colombier 				}
145*c6df1444SDavid du Colombier 		}
146*c6df1444SDavid du Colombier 	}
147*c6df1444SDavid du Colombier 	return nb;
148*c6df1444SDavid du Colombier }
149*c6df1444SDavid du Colombier 
150*c6df1444SDavid du Colombier int
fullrune(char * str,int n)151*c6df1444SDavid du Colombier fullrune(char *str, int n)
152*c6df1444SDavid du Colombier {
153*c6df1444SDavid du Colombier 	int  i;
154*c6df1444SDavid du Colombier 	Rune c;
155*c6df1444SDavid du Colombier 
156*c6df1444SDavid du Colombier 	if(n <= 0)
157*c6df1444SDavid du Colombier 		return 0;
158*c6df1444SDavid du Colombier 	c = *(uchar*)str;
159*c6df1444SDavid du Colombier 	if(c < Tx)
160*c6df1444SDavid du Colombier 		return 1;
161*c6df1444SDavid du Colombier 	for(i = 3; i < UTFmax + 1; i++)
162*c6df1444SDavid du Colombier 		if(c < T(i))
163*c6df1444SDavid du Colombier 			return n >= i - 1;
164*c6df1444SDavid du Colombier 	return n >= UTFmax;
165*c6df1444SDavid du Colombier }
166