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