/ utf8fromwc() */ / Turn "wide characters" as returned by some system calls (especially on Windows) into UTF-8. Up to \a dstlen bytes are written to \a dst, including a null terminator. The return value is the number of bytes that would be written, not counting the null terminator. If greater or equal to \a dstlen then if you malloc a new array of s
| 456 | pairs are converted as though they are individual characters. |
| 457 | */ |
| 458 | static unsigned int utf8fromwc(char *dst, unsigned dstlen, const wchar_t *src, |
| 459 | unsigned srclen) { |
| 460 | unsigned int i = 0; |
| 461 | unsigned int count = 0; |
| 462 | if (dstlen) |
| 463 | while (true) { |
| 464 | if (i >= srclen) { |
| 465 | dst[count] = 0; |
| 466 | return count; |
| 467 | } |
| 468 | unsigned int ucs = src[i++]; |
| 469 | if (ucs < 0x80U) { |
| 470 | dst[count++] = static_cast<char>(ucs); |
| 471 | if (count >= dstlen) { |
| 472 | dst[count - 1] = 0; |
| 473 | break; |
| 474 | } |
| 475 | } else if (ucs < 0x800U) { |
| 476 | // 2 bytes. |
| 477 | if (count + 2 >= dstlen) { |
| 478 | dst[count] = 0; |
| 479 | count += 2; |
| 480 | break; |
| 481 | } |
| 482 | dst[count++] = 0xc0 | static_cast<char>(ucs >> 6); |
| 483 | dst[count++] = 0x80 | static_cast<char>(ucs & 0x3F); |
| 484 | #ifdef _WIN32 |
| 485 | } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen && |
| 486 | src[i] >= 0xdc00 && src[i] <= 0xdfff) { |
| 487 | // Surrogate pair. |
| 488 | unsigned int ucs2 = src[i++]; |
| 489 | ucs = 0x10000U + ((ucs & 0x3ff) << 10) + (ucs2 & 0x3ff); |
| 490 | // All surrogate pairs turn into 4-byte utf8. |
| 491 | #else |
| 492 | } else if (ucs >= 0x10000) { |
| 493 | if (ucs > 0x10ffff) { |
| 494 | ucs = 0xfffd; |
| 495 | goto J1; |
| 496 | } |
| 497 | #endif |
| 498 | if (count + 4 >= dstlen) { |
| 499 | dst[count] = 0; |
| 500 | count += 4; |
| 501 | break; |
| 502 | } |
| 503 | dst[count++] = 0xf0 | static_cast<char>(ucs >> 18); |
| 504 | dst[count++] = 0x80 | static_cast<char>((ucs >> 12) & 0x3F); |
| 505 | dst[count++] = 0x80 | static_cast<char>((ucs >> 6) & 0x3F); |
| 506 | dst[count++] = 0x80 | static_cast<char>(ucs & 0x3F); |
| 507 | } else { |
| 508 | #ifndef _WIN32 |
| 509 | J1: |
| 510 | #endif |
| 511 | // All others are 3 bytes: |
| 512 | if (count + 3 >= dstlen) { |
| 513 | dst[count] = 0; |
| 514 | count += 3; |
| 515 | break; |