108 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to> &dst,
109 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src)
111 _Assume_(src || !count_src);
112 count_src = stdex::strnlen<T_from>(src, count_src);
113 if (!count_src) _Unlikely_
117 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
118 constexpr DWORD dwFlagsWCMB = 0;
119 constexpr LPCCH lpDefaultChar = NULL;
122 if (m_from_wincp == m_to_wincp) _Unlikely_{
123 dst.append(
reinterpret_cast<const T_to*
>(src), count_src);
127#pragma warning(suppress: 4127)
128 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
wchar_t)) {
129 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
132 WCHAR szStackBuffer[1024 /
sizeof(WCHAR)];
133#pragma warning(suppress: 6387)
134 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
137 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
140 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
142 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
143 std::unique_ptr<WCHAR[]> szBuffer(
new WCHAR[cch]);
144 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch);
145 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
148 throw std::system_error(GetLastError(), std::system_category(),
"MultiByteToWideChar failed");
151#pragma warning(suppress: 4127)
152 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
wchar_t) &&
sizeof(T_to) ==
sizeof(
char)) {
153 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
156 CHAR szStackBuffer[1024 /
sizeof(CHAR)];
157#pragma warning(suppress: 6387)
158 int cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
161 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
164 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
166 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
167 std::unique_ptr<CHAR[]> szBuffer(
new CHAR[cch]);
168 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
169 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
172 throw std::system_error(GetLastError(), std::system_category(),
"WideCharToMultiByte failed");
175#pragma warning(suppress: 4127)
176 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
char)) {
177 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
180 WCHAR szStackBufferMBWC[512 /
sizeof(WCHAR)];
181#pragma warning(suppress: 6387)
182 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
185 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) :
static_cast<size_t>(cch) - 1;
186 _Assume_(count_inter < INT_MAX);
189 CHAR szStackBufferWCMB[512 /
sizeof(CHAR)];
190#pragma warning(suppress: 6387)
191 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
194 dst.append(
reinterpret_cast<const T_to*
>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
197 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
199 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
200 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
201 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
202 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
205 throw std::system_error(GetLastError(), std::system_category(),
"WideCharToMultiByte failed");
207 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
209 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
210 std::unique_ptr<WCHAR[]> szBufferMBWC(
new WCHAR[cch]);
211 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBufferMBWC.get(), cch);
212 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) :
static_cast<size_t>(cch) - 1;
215 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
216 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
217 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
218 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
221 throw std::system_error(GetLastError(), std::system_category(),
"MultiByteToWideChar failed");
224 dst.reserve(dst.size() + count_src);
225 T_to buf[1024 /
sizeof(T_to)];
226 size_t src_size = stdex::mul(
sizeof(T_from), count_src);
228 T_to* output = &buf[0];
229 size_t output_size =
sizeof(buf);
231 iconv(m_handle,
const_cast<char**
>(
reinterpret_cast<const char**
>(&src)), &src_size,
reinterpret_cast<char**
>(&output), &output_size);
232 dst.append(buf,
reinterpret_cast<T_to*
>(
reinterpret_cast<char*
>(buf) +
sizeof(buf) - output_size));
237 throw std::system_error(errno, std::system_category(),
"iconv failed");