| 220 | } |
| 221 | |
| 222 | static uint32 * |
| 223 | uni_8to32(const char *inp) |
| 224 | { |
| 225 | size_t i, j; |
| 226 | uint32 *out; |
| 227 | |
| 228 | /* Output string */ |
| 229 | out = (uint32 *) alloc((strlen(inp) + 1) * sizeof(out[0])); |
| 230 | |
| 231 | i = 0; |
| 232 | j = 0; |
| 233 | while (inp[i] != 0) { |
| 234 | unsigned char byte = inp[i++]; |
| 235 | uint32 ch32; |
| 236 | uint32 min = 0; |
| 237 | unsigned count = 0; |
| 238 | |
| 239 | if (byte < 0x80) { |
| 240 | ch32 = byte; |
| 241 | } else if (byte < 0xC0) { |
| 242 | ch32 = 0xFFFD; |
| 243 | } else if (byte < 0xE0) { |
| 244 | ch32 = byte & 0x1F; |
| 245 | min = 0x80; |
| 246 | count = 1; |
| 247 | } else if (byte < 0xF0) { |
| 248 | ch32 = byte & 0x0F; |
| 249 | min = 0x800; |
| 250 | count = 2; |
| 251 | } else if (byte < 0xF5) { |
| 252 | ch32 = byte & 0x07; |
| 253 | min = 0x10000; |
| 254 | count = 3; |
| 255 | } else { |
| 256 | ch32 = 0xFFFD; |
| 257 | } |
| 258 | |
| 259 | for (; count != 0; --count) { |
| 260 | byte = inp[i]; |
| 261 | if ((byte & 0xC0) != 0x80) { |
| 262 | break; |
| 263 | } |
| 264 | ++i; |
| 265 | ch32 = (ch32 << 6) | (byte & 0x3F); |
| 266 | } |
| 267 | if (count != 0 || ch32 < min || ((ch32 & 0xFFFFF800) == 0xD800)) { |
| 268 | ch32 = 0xFFFD; |
| 269 | } |
| 270 | out[j++] = ch32; |
| 271 | } |
| 272 | |
| 273 | out[j] = 0; |
| 274 | return out; |
| 275 | } |