* @brief Convert from one 8-bit codepage to another * * destsize must be at least 2 */
| 687 | * destsize must be at least 2 |
| 688 | */ |
| 689 | int CrossConvert(const char* src, unsigned srclen, char* dest, unsigned destsize, int cpin, int cpout, bool * lossy) |
| 690 | { |
| 691 | assert(destsize > 1); |
| 692 | |
| 693 | // Convert input to Unicode, using specified codepage |
| 694 | DWORD flags = 0; |
| 695 | int wlen = srclen * 2 + 6; |
| 696 | auto wbuff = std::make_unique<wchar_t[]>(wlen); |
| 697 | int n; |
| 698 | if (cpin == CP_UCS2LE) |
| 699 | { |
| 700 | if (srclen == -1) |
| 701 | srclen = static_cast<unsigned>(wcslen((wchar_t *)src) * sizeof(wchar_t)); |
| 702 | memcpy(wbuff.get(), src, srclen); |
| 703 | n = srclen / sizeof(wchar_t); |
| 704 | } |
| 705 | else if (cpin == CP_UCS2BE) |
| 706 | { |
| 707 | if (srclen == -1) |
| 708 | srclen = static_cast<unsigned>(wcslen((wchar_t *)src) * sizeof(wchar_t)); |
| 709 | _swab((char *)src, (char *)wbuff.get(), srclen); |
| 710 | n = srclen / sizeof(wchar_t); |
| 711 | } |
| 712 | else |
| 713 | { |
| 714 | n = MultiByteToWideChar(cpin, flags, (const char*)src, srclen, wbuff.get(), wlen - 1); |
| 715 | if (!n) |
| 716 | { |
| 717 | int nsyserr = ::GetLastError(); |
| 718 | dest[0] = '?'; |
| 719 | return 1; |
| 720 | } |
| 721 | } |
| 722 | /* |
| 723 | NB: MultiByteToWideChar is documented as only zero-terminating |
| 724 | if input was zero-terminated, but it appears that it can |
| 725 | zero-terminate even if input wasn't. |
| 726 | So we check if it zero-terminated and adjust count accordingly. |
| 727 | */ |
| 728 | if (wbuff[n-1] == 0) |
| 729 | --n; |
| 730 | wbuff[n] = 0; // zero-terminate string |
| 731 | |
| 732 | // Now convert to tchar_t (which means defcodepage) |
| 733 | flags = WC_NO_BEST_FIT_CHARS; // TODO: Think about this |
| 734 | BOOL defaulted = FALSE; |
| 735 | BOOL * pdefaulted = &defaulted; |
| 736 | if (cpout == CP_UTF8) |
| 737 | { |
| 738 | flags = 0; |
| 739 | pdefaulted = nullptr; |
| 740 | } |
| 741 | if (cpout == CP_UCS2LE) |
| 742 | { |
| 743 | memcpy(dest, wbuff.get(), n * sizeof(wchar_t)); |
| 744 | n = n * sizeof(wchar_t); |
| 745 | dest[n] = 0; |
| 746 | dest[n + 1] = 0; |