| @@ -1,24 +1,29 @@ |
| 1 | #include <u.h> | 1 | #include <u.h> |
| 2 | #include <libc.h> | 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 | enum | 4 | enum |
| 11 | { | 5 | { |
| 12 | Bitx = Bit(1), | 6 | Bit1 = 7, |
| 13 | | 7 | Bitx = 6, |
| 14 | Tx = T(1), /* 1000 0000 */ | 8 | Bit2 = 5, |
| 15 | Rune1 = (1<<(Bit(0)+0*Bitx))-1, /* 0000 0000 0000 0000 0111 1111 */ | 9 | Bit3 = 4, |
| 16 | | 10 | Bit4 = 3, |
| 17 | Maskx = (1<<Bitx)-1, /* 0011 1111 */ | 11 | Bit5 = 2, |
| 18 | Testx = Maskx ^ 0xFF, /* 1100 0000 */ | 12 | |
| 19 | | 13 | T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ |
| 20 | SurrogateMin = 0xD800, | 14 | Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ |
| 21 | SurrogateMax = 0xDFFF, | 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 | Bad = Runeerror, | 28 | Bad = Runeerror, |
| 24 | }; | 29 | }; |
| @@ -26,41 +31,67 @@ enum · 1 unmodified line |
| 26 | int | 31 | int |
| 27 | chartorune(Rune *rune, char *str) | 32 | chartorune(Rune *rune, char *str) |
| 28 | { | 33 | { |
| 29 | int c[UTFmax], i; | 34 | int c, c1, c2, c3; |
| 30 | Rune l; | 35 | long l; |
| 31 | | 36 | |
| 32 | /* | 37 | /* |
| 33 | * N character sequence | 38 | * one character sequence |
| 34 | * 00000-0007F => T1 | 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 | | 41 | c = *(uchar*)str; |
| 40 | c[0] = *(uchar*)(str); | 42 | if(c < Tx) { |
| 41 | if(c[0] < Tx){ | 43 | *rune = c; |
| 42 | *rune = c[0]; | | |
| 43 | return 1; | 44 | return 1; |
| 44 | } | 45 | } |
| 45 | l = c[0]; | | |
| 46 | | 46 | |
| 47 | for(i = 1; i < UTFmax; i++) { | 47 | /* |
| 48 | c[i] = *(uchar*)(str+i); | 48 | * two character sequence |
| 49 | c[i] ^= Tx; | 49 | * 0080-07FF => T2 Tx |
| 50 | if(c[i] & Testx) | 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 | goto bad; | 74 | goto bad; |
| 52 | l = (l << Bitx) | c[i]; | 75 | *rune = l; |
| 53 | if(c[0] < T(i + 2)) { | 76 | return 3; |
| 54 | l &= RuneX(i + 1); | 77 | } |
| 55 | if(i == 1) { | 78 | |
| 56 | if(c[0] < T(2) || l <= Rune1) | 79 | /* |
| 57 | goto bad; | 80 | * four character sequence |
| 58 | } else if(l <= RuneX(i) || l > Runemax) | 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 | goto bad; | 90 | goto bad; |
| 60 | if (i == 2 && SurrogateMin <= l && l <= SurrogateMax) | 91 | if(l > Runemax) |
| 61 | goto bad; | 92 | goto bad; |
| 62 | *rune = l; | 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 | int | 106 | int |
| 76 | runetochar(char *str, Rune *rune) | 107 | runetochar(char *str, Rune *rune) |
| 77 | { | 108 | { |
| 78 | int i, j; | 109 | long c; |
| 79 | Rune c; | | |
| 80 | | 110 | |
| 81 | c = *rune; | 111 | c = *rune; |
| | 112 | if(c > Runemax) |
| | 113 | c = Runeerror; |
| | 114 | |
| | 115 | /* |
| | 116 | * one character sequence |
| | 117 | * 00000-0007F => 00-7F |
| | 118 | */ |
| 82 | if(c <= Rune1) { | 119 | if(c <= Rune1) { |
| 83 | str[0] = c; | 120 | str[0] = c; |
| 84 | return 1; | 121 | return 1; |
| 85 | } | 122 | } |
| 86 | | 123 | |
| 87 | /* | 124 | /* |
| 88 | * one character sequence | | |
| 89 | * 00000-0007F => 00-7F | | |
| 90 | * two character sequence | 125 | * two character sequence |
| 91 | * 0080-07FF => T2 Tx | 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 | * three character sequence | 135 | * three character sequence |
| 93 | * 0800-FFFF => T3 Tx Tx | 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++){ | 138 | if(c <= Rune3) { |
| 103 | if(i == 3){ | 139 | str[0] = T3 | (c >> 2*Bitx); |
| 104 | if(c > Runemax) | 140 | str[1] = Tx | ((c >> 1*Bitx) & Maskx); |
| 105 | c = Runeerror; | 141 | str[2] = Tx | (c & Maskx); |
| 106 | if(SurrogateMin <= c && c <= SurrogateMax) | 142 | return 3; |
| 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 | } | | |
| 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 | int | 156 | int |
| 120 | runelen(long c) | 157 | runelen(long c) |
| 121 | { | 158 | { |
| 122 | Rune rune; | 159 | Rune rune; |
| 123 | char str[10]; | 160 | char str[UTFmax]; |
| 124 | | 161 | |
| 125 | rune = c; | 162 | rune = c; |
| 126 | return runetochar(str, &rune); | 163 | return runetochar(str, &rune); |
| @@ -129,21 +166,21 @@ runelen(long c) · 2 unmodified lines |
| 129 | int | 166 | int |
| 130 | runenlen(Rune *r, int nrune) | 167 | runenlen(Rune *r, int nrune) |
| 131 | { | 168 | { |
| 132 | int nb, i; | 169 | int nb, c; |
| 133 | Rune c; | | |
| 134 | | 170 | |
| 135 | nb = 0; | 171 | nb = 0; |
| 136 | while(nrune--) { | 172 | while(nrune--) { |
| 137 | c = *r++; | 173 | c = *r++; |
| 138 | if(c <= Rune1){ | 174 | if(c <= Rune1) |
| 139 | nb++; | 175 | nb++; |
| 140 | } else { | 176 | else |
| 141 | for(i = 2; i < UTFmax + 1; i++) | 177 | if(c <= Rune2) |
| 142 | if(c <= RuneX(i) || i == UTFmax){ | 178 | nb += 2; |
| 143 | nb += i; | 179 | else |
| 144 | break; | 180 | if(c <= Rune3 || c > Runemax) |
| 145 | } | 181 | nb += 3; |
| 146 | } | 182 | else |
| | 183 | nb += 4; |
| 147 | } | 184 | } |
| 148 | return nb; | 185 | return nb; |
| 149 | } | 186 | } |
| @@ -151,16 +188,17 @@ runenlen(Rune *r, int nrune) · 1 unmodified line |
| 151 | int | 188 | int |
| 152 | fullrune(char *str, int n) | 189 | fullrune(char *str, int n) |
| 153 | { | 190 | { |
| 154 | int i; | 191 | int c; |
| 155 | Rune c; | | |
| 156 | | 192 | |
| 157 | if(n <= 0) | 193 | if(n <= 0) |
| 158 | return 0; | 194 | return 0; |
| 159 | c = *(uchar*)str; | 195 | c = *(uchar*)str; |
| 160 | if(c < Tx) | 196 | if(c < Tx) |
| 161 | return 1; | 197 | return 1; |
| 162 | for(i = 3; i < UTFmax + 1; i++) | 198 | if(c < T3) |
| 163 | if(c < T(i)) | 199 | return n >= 2; |
| 164 | return n >= i - 1; | 200 | if(UTFmax == 3 || c < T4) |
| 165 | return n >= UTFmax; | 201 | return n >= 3; |
| | 202 | return n >= 4; |
| 166 | } | 203 | } |
| | 204 | |