| 315 | /* --------------------------------------------------------------------- */ |
| 316 | |
| 317 | ConversionResult ConvertUTF32toUTF8 ( |
| 318 | const UTF32** sourceStart, const UTF32* sourceEnd, |
| 319 | UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { |
| 320 | ConversionResult result = conversionOK; |
| 321 | const UTF32* source = *sourceStart; |
| 322 | UTF8* target = *targetStart; |
| 323 | while (source < sourceEnd) { |
| 324 | UTF32 ch; |
| 325 | unsigned short bytesToWrite = 0; |
| 326 | const UTF32 byteMask = 0xBF; |
| 327 | const UTF32 byteMark = 0x80; |
| 328 | ch = *source++; |
| 329 | if (flags == strictConversion ) { |
| 330 | /* UTF-16 surrogate values are illegal in UTF-32 */ |
| 331 | if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { |
| 332 | --source; /* return to the illegal value itself */ |
| 333 | result = sourceIllegal; |
| 334 | break; |
| 335 | } |
| 336 | } |
| 337 | /* |
| 338 | * Figure out how many bytes the result will require. Turn any |
| 339 | * illegally large UTF32 things (> Plane 17) into replacement chars. |
| 340 | */ |
| 341 | if (ch < (UTF32)0x80) { bytesToWrite = 1; |
| 342 | } else if (ch < (UTF32)0x800) { bytesToWrite = 2; |
| 343 | } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; |
| 344 | } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; |
| 345 | } else { bytesToWrite = 3; |
| 346 | ch = UNI_REPLACEMENT_CHAR; |
| 347 | result = sourceIllegal; |
| 348 | } |
| 349 | |
| 350 | target += bytesToWrite; |
| 351 | if (target > targetEnd) { |
| 352 | --source; /* Back up source pointer! */ |
| 353 | target -= bytesToWrite; result = targetExhausted; break; |
| 354 | } |
| 355 | switch (bytesToWrite) { /* note: everything falls through. */ |
| 356 | case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; |
| 357 | case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; |
| 358 | case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; |
| 359 | case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); |
| 360 | } |
| 361 | target += bytesToWrite; |
| 362 | } |
| 363 | *sourceStart = source; |
| 364 | *targetStart = target; |
| 365 | return result; |
| 366 | } |
| 367 | |
| 368 | /* --------------------------------------------------------------------- */ |
| 369 | |