]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/lib/utf/rune.c
sdiahci, sdodin: avoid calling kproc() while holding ilock()
[plan9front.git] / sys / src / ape / lib / utf / rune.c
1 /*
2  * The authors of this software are Rob Pike and Ken Thompson.
3  *              Copyright (c) 2002 by Lucent Technologies.
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose without fee is hereby granted, provided that this entire notice
6  * is included in all copies of any software which is or includes a copy
7  * or modification of this software and in all copies of the supporting
8  * documentation for such software.
9  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
10  * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
11  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
12  * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
13  */
14 #include <stdarg.h>
15 #include <string.h>
16 #include "utf.h"
17 #include "utfdef.h"
18
19 enum
20 {
21         Bit1    = 7,
22         Bitx    = 6,
23         Bit2    = 5,
24         Bit3    = 4,
25         Bit4    = 3,
26         Bit5    = 2,
27
28         T1      = ((1<<(Bit1+1))-1) ^ 0xFF,     /* 0000 0000 */
29         Tx      = ((1<<(Bitx+1))-1) ^ 0xFF,     /* 1000 0000 */
30         T2      = ((1<<(Bit2+1))-1) ^ 0xFF,     /* 1100 0000 */
31         T3      = ((1<<(Bit3+1))-1) ^ 0xFF,     /* 1110 0000 */
32         T4      = ((1<<(Bit4+1))-1) ^ 0xFF,     /* 1111 0000 */
33         T5      = ((1<<(Bit5+1))-1) ^ 0xFF,     /* 1111 1000 */
34
35         Rune1   = (1<<(Bit1+0*Bitx))-1,         /* 0000 0000 0000 0000 0111 1111 */
36         Rune2   = (1<<(Bit2+1*Bitx))-1,         /* 0000 0000 0000 0111 1111 1111 */
37         Rune3   = (1<<(Bit3+2*Bitx))-1,         /* 0000 0000 1111 1111 1111 1111 */
38         Rune4   = (1<<(Bit4+3*Bitx))-1,         /* 0011 1111 1111 1111 1111 1111 */
39
40         Maskx   = (1<<Bitx)-1,                  /* 0011 1111 */
41         Testx   = Maskx ^ 0xFF,                 /* 1100 0000 */
42
43         Bad     = Runeerror,
44 };
45
46 int
47 chartorune(Rune *rune, char *str)
48 {
49         int c, c1, c2, c3;
50         long l;
51
52         /*
53          * one character sequence
54          *      00000-0007F => T1
55          */
56         c = *(uchar*)str;
57         if(c < Tx) {
58                 *rune = c;
59                 return 1;
60         }
61
62         /*
63          * two character sequence
64          *      0080-07FF => T2 Tx
65          */
66         c1 = *(uchar*)(str+1) ^ Tx;
67         if(c1 & Testx)
68                 goto bad;
69         if(c < T3) {
70                 if(c < T2)
71                         goto bad;
72                 l = ((c << Bitx) | c1) & Rune2;
73                 if(l <= Rune1)
74                         goto bad;
75                 *rune = l;
76                 return 2;
77         }
78
79         /*
80          * three character sequence
81          *      0800-FFFF => T3 Tx Tx
82          */
83         c2 = *(uchar*)(str+2) ^ Tx;
84         if(c2 & Testx)
85                 goto bad;
86         if(c < T4) {
87                 l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
88                 if(l <= Rune2)
89                         goto bad;
90                 *rune = l;
91                 return 3;
92         }
93
94         /*
95          * four character sequence
96          *      10000-10FFFF => T4 Tx Tx Tx
97          */
98         if(UTFmax >= 4) {
99                 c3 = *(uchar*)(str+3) ^ Tx;
100                 if(c3 & Testx)
101                         goto bad;
102                 if(c < T5) {
103                         l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
104                         if(l <= Rune3)
105                                 goto bad;
106                         if(l > Runemax)
107                                 goto bad;
108                         *rune = l;
109                         return 4;
110                 }
111         }
112
113         /*
114          * bad decoding
115          */
116 bad:
117         *rune = Bad;
118         return 1;
119 }
120
121 int
122 runetochar(char *str, Rune *rune)
123 {
124         long c;
125
126         c = *rune;
127         if(c > Runemax)
128                 c = Runeerror;
129
130         /*
131          * one character sequence
132          *      00000-0007F => 00-7F
133          */
134         if(c <= Rune1) {
135                 str[0] = c;
136                 return 1;
137         }
138
139         /*
140          * two character sequence
141          *      0080-07FF => T2 Tx
142          */
143         if(c <= Rune2) {
144                 str[0] = T2 | (c >> 1*Bitx);
145                 str[1] = Tx | (c & Maskx);
146                 return 2;
147         }
148
149         /*
150          * three character sequence
151          *      0800-FFFF => T3 Tx Tx
152          */
153         if(c <= Rune3) {
154                 str[0] = T3 |  (c >> 2*Bitx);
155                 str[1] = Tx | ((c >> 1*Bitx) & Maskx);
156                 str[2] = Tx |  (c & Maskx);
157                 return 3;
158         }
159
160         /*
161          * four character sequence
162          *      10000-1FFFFF => T4 Tx Tx Tx
163          */
164         str[0] = T4 |  (c >> 3*Bitx);
165         str[1] = Tx | ((c >> 2*Bitx) & Maskx);
166         str[2] = Tx | ((c >> 1*Bitx) & Maskx);
167         str[3] = Tx |  (c & Maskx);
168         return 4;
169 }
170
171 int
172 runelen(long c)
173 {
174         Rune rune;
175         char str[UTFmax];
176
177         rune = c;
178         return runetochar(str, &rune);
179 }
180
181 int
182 runenlen(Rune *r, int nrune)
183 {
184         int nb, c;
185
186         nb = 0;
187         while(nrune--) {
188                 c = *r++;
189                 if(c <= Rune1)
190                         nb++;
191                 else
192                 if(c <= Rune2)
193                         nb += 2;
194                 else
195                 if(c <= Rune3 || c > Runemax)
196                         nb += 3;
197                 else
198                         nb += 4;
199         }
200         return nb;
201 }
202
203 int
204 fullrune(char *str, int n)
205 {
206         int c;
207
208         if(n <= 0)
209                 return 0;
210         c = *(uchar*)str;
211         if(c < Tx)
212                 return 1;
213         if(c < T3)
214                 return n >= 2;
215         if(UTFmax == 3 || c < T4)
216                 return n >= 3;
217         return n >= 4;
218 }
219