xref: /plan9/sys/src/cmd/unix/u9fs/rune.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier #include	<plan9.h>
2*9a747e4fSDavid du Colombier 
3*9a747e4fSDavid du Colombier char *argv0;
4*9a747e4fSDavid du Colombier enum
5*9a747e4fSDavid du Colombier {
6*9a747e4fSDavid du Colombier 	Bit1	= 7,
7*9a747e4fSDavid du Colombier 	Bitx	= 6,
8*9a747e4fSDavid du Colombier 	Bit2	= 5,
9*9a747e4fSDavid du Colombier 	Bit3	= 4,
10*9a747e4fSDavid du Colombier 	Bit4	= 3,
11*9a747e4fSDavid du Colombier 
12*9a747e4fSDavid du Colombier 	T1	= ((1<<(Bit1+1))-1) ^ 0xFF,	/* 0000 0000 */
13*9a747e4fSDavid du Colombier 	Tx	= ((1<<(Bitx+1))-1) ^ 0xFF,	/* 1000 0000 */
14*9a747e4fSDavid du Colombier 	T2	= ((1<<(Bit2+1))-1) ^ 0xFF,	/* 1100 0000 */
15*9a747e4fSDavid du Colombier 	T3	= ((1<<(Bit3+1))-1) ^ 0xFF,	/* 1110 0000 */
16*9a747e4fSDavid du Colombier 	T4	= ((1<<(Bit4+1))-1) ^ 0xFF,	/* 1111 0000 */
17*9a747e4fSDavid du Colombier 
18*9a747e4fSDavid du Colombier 	Rune1	= (1<<(Bit1+0*Bitx))-1,		/* 0000 0000 0111 1111 */
19*9a747e4fSDavid du Colombier 	Rune2	= (1<<(Bit2+1*Bitx))-1,		/* 0000 0111 1111 1111 */
20*9a747e4fSDavid du Colombier 	Rune3	= (1<<(Bit3+2*Bitx))-1,		/* 1111 1111 1111 1111 */
21*9a747e4fSDavid du Colombier 
22*9a747e4fSDavid du Colombier 	Maskx	= (1<<Bitx)-1,			/* 0011 1111 */
23*9a747e4fSDavid du Colombier 	Testx	= Maskx ^ 0xFF,			/* 1100 0000 */
24*9a747e4fSDavid du Colombier 
25*9a747e4fSDavid du Colombier 	Bad	= Runeerror
26*9a747e4fSDavid du Colombier };
27*9a747e4fSDavid du Colombier 
28*9a747e4fSDavid du Colombier int
29*9a747e4fSDavid du Colombier chartorune(Rune *rune, char *str)
30*9a747e4fSDavid du Colombier {
31*9a747e4fSDavid du Colombier 	int c, c1, c2;
32*9a747e4fSDavid du Colombier 	long l;
33*9a747e4fSDavid du Colombier 
34*9a747e4fSDavid du Colombier 	/*
35*9a747e4fSDavid du Colombier 	 * one character sequence
36*9a747e4fSDavid du Colombier 	 *	00000-0007F => T1
37*9a747e4fSDavid du Colombier 	 */
38*9a747e4fSDavid du Colombier 	c = *(uchar*)str;
39*9a747e4fSDavid du Colombier 	if(c < Tx) {
40*9a747e4fSDavid du Colombier 		*rune = c;
41*9a747e4fSDavid du Colombier 		return 1;
42*9a747e4fSDavid du Colombier 	}
43*9a747e4fSDavid du Colombier 
44*9a747e4fSDavid du Colombier 	/*
45*9a747e4fSDavid du Colombier 	 * two character sequence
46*9a747e4fSDavid du Colombier 	 *	0080-07FF => T2 Tx
47*9a747e4fSDavid du Colombier 	 */
48*9a747e4fSDavid du Colombier 	c1 = *(uchar*)(str+1) ^ Tx;
49*9a747e4fSDavid du Colombier 	if(c1 & Testx)
50*9a747e4fSDavid du Colombier 		goto bad;
51*9a747e4fSDavid du Colombier 	if(c < T3) {
52*9a747e4fSDavid du Colombier 		if(c < T2)
53*9a747e4fSDavid du Colombier 			goto bad;
54*9a747e4fSDavid du Colombier 		l = ((c << Bitx) | c1) & Rune2;
55*9a747e4fSDavid du Colombier 		if(l <= Rune1)
56*9a747e4fSDavid du Colombier 			goto bad;
57*9a747e4fSDavid du Colombier 		*rune = l;
58*9a747e4fSDavid du Colombier 		return 2;
59*9a747e4fSDavid du Colombier 	}
60*9a747e4fSDavid du Colombier 
61*9a747e4fSDavid du Colombier 	/*
62*9a747e4fSDavid du Colombier 	 * three character sequence
63*9a747e4fSDavid du Colombier 	 *	0800-FFFF => T3 Tx Tx
64*9a747e4fSDavid du Colombier 	 */
65*9a747e4fSDavid du Colombier 	c2 = *(uchar*)(str+2) ^ Tx;
66*9a747e4fSDavid du Colombier 	if(c2 & Testx)
67*9a747e4fSDavid du Colombier 		goto bad;
68*9a747e4fSDavid du Colombier 	if(c < T4) {
69*9a747e4fSDavid du Colombier 		l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
70*9a747e4fSDavid du Colombier 		if(l <= Rune2)
71*9a747e4fSDavid du Colombier 			goto bad;
72*9a747e4fSDavid du Colombier 		*rune = l;
73*9a747e4fSDavid du Colombier 		return 3;
74*9a747e4fSDavid du Colombier 	}
75*9a747e4fSDavid du Colombier 
76*9a747e4fSDavid du Colombier 	/*
77*9a747e4fSDavid du Colombier 	 * bad decoding
78*9a747e4fSDavid du Colombier 	 */
79*9a747e4fSDavid du Colombier bad:
80*9a747e4fSDavid du Colombier 	*rune = Bad;
81*9a747e4fSDavid du Colombier 	return 1;
82*9a747e4fSDavid du Colombier }
83*9a747e4fSDavid du Colombier 
84*9a747e4fSDavid du Colombier int
85*9a747e4fSDavid du Colombier runetochar(char *str, Rune *rune)
86*9a747e4fSDavid du Colombier {
87*9a747e4fSDavid du Colombier 	long c;
88*9a747e4fSDavid du Colombier 
89*9a747e4fSDavid du Colombier 	/*
90*9a747e4fSDavid du Colombier 	 * one character sequence
91*9a747e4fSDavid du Colombier 	 *	00000-0007F => 00-7F
92*9a747e4fSDavid du Colombier 	 */
93*9a747e4fSDavid du Colombier 	c = *rune;
94*9a747e4fSDavid du Colombier 	if(c <= Rune1) {
95*9a747e4fSDavid du Colombier 		str[0] = c;
96*9a747e4fSDavid du Colombier 		return 1;
97*9a747e4fSDavid du Colombier 	}
98*9a747e4fSDavid du Colombier 
99*9a747e4fSDavid du Colombier 	/*
100*9a747e4fSDavid du Colombier 	 * two character sequence
101*9a747e4fSDavid du Colombier 	 *	0080-07FF => T2 Tx
102*9a747e4fSDavid du Colombier 	 */
103*9a747e4fSDavid du Colombier 	if(c <= Rune2) {
104*9a747e4fSDavid du Colombier 		str[0] = T2 | (c >> 1*Bitx);
105*9a747e4fSDavid du Colombier 		str[1] = Tx | (c & Maskx);
106*9a747e4fSDavid du Colombier 		return 2;
107*9a747e4fSDavid du Colombier 	}
108*9a747e4fSDavid du Colombier 
109*9a747e4fSDavid du Colombier 	/*
110*9a747e4fSDavid du Colombier 	 * three character sequence
111*9a747e4fSDavid du Colombier 	 *	0800-FFFF => T3 Tx Tx
112*9a747e4fSDavid du Colombier 	 */
113*9a747e4fSDavid du Colombier 	str[0] = T3 |  (c >> 2*Bitx);
114*9a747e4fSDavid du Colombier 	str[1] = Tx | ((c >> 1*Bitx) & Maskx);
115*9a747e4fSDavid du Colombier 	str[2] = Tx |  (c & Maskx);
116*9a747e4fSDavid du Colombier 	return 3;
117*9a747e4fSDavid du Colombier }
118*9a747e4fSDavid du Colombier 
119*9a747e4fSDavid du Colombier int
120*9a747e4fSDavid du Colombier runelen(long c)
121*9a747e4fSDavid du Colombier {
122*9a747e4fSDavid du Colombier 	Rune rune;
123*9a747e4fSDavid du Colombier 	char str[10];
124*9a747e4fSDavid du Colombier 
125*9a747e4fSDavid du Colombier 	rune = c;
126*9a747e4fSDavid du Colombier 	return runetochar(str, &rune);
127*9a747e4fSDavid du Colombier }
128*9a747e4fSDavid du Colombier 
129*9a747e4fSDavid du Colombier int
130*9a747e4fSDavid du Colombier utflen(char *s)
131*9a747e4fSDavid du Colombier {
132*9a747e4fSDavid du Colombier 	int c;
133*9a747e4fSDavid du Colombier 	long n;
134*9a747e4fSDavid du Colombier 	Rune rune;
135*9a747e4fSDavid du Colombier 
136*9a747e4fSDavid du Colombier 	n = 0;
137*9a747e4fSDavid du Colombier 	for(;;) {
138*9a747e4fSDavid du Colombier 		c = *(uchar*)s;
139*9a747e4fSDavid du Colombier 		if(c < Runeself) {
140*9a747e4fSDavid du Colombier 			if(c == 0)
141*9a747e4fSDavid du Colombier 				return n;
142*9a747e4fSDavid du Colombier 			s++;
143*9a747e4fSDavid du Colombier 		} else
144*9a747e4fSDavid du Colombier 			s += chartorune(&rune, s);
145*9a747e4fSDavid du Colombier 		n++;
146*9a747e4fSDavid du Colombier 	}
147*9a747e4fSDavid du Colombier 	return 0;
148*9a747e4fSDavid du Colombier }
149