103 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to> &dst,
104 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src)
106 _Assume_(src || !count_src);
107 count_src = stdex::strnlen(src, count_src);
108 if (!count_src) _Unlikely_
112 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
113 constexpr DWORD dwFlagsWCMB = 0;
114 constexpr LPCCH lpDefaultChar = NULL;
117 if (m_from_wincp == m_to_wincp) _Unlikely_{
118 dst.append(
reinterpret_cast<const T_to*
>(src), count_src);
122#pragma warning(suppress: 4127)
123 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
wchar_t)) {
124 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
127 WCHAR szStackBuffer[1024 /
sizeof(WCHAR)];
128#pragma warning(suppress: 6387)
129 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
132 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
135 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
137 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
138 std::unique_ptr<WCHAR[]> szBuffer(
new WCHAR[cch]);
139 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch);
140 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
143 throw std::system_error(GetLastError(), std::system_category(),
"MultiByteToWideChar failed");
146#pragma warning(suppress: 4127)
147 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
wchar_t) &&
sizeof(T_to) ==
sizeof(
char)) {
148 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
151 CHAR szStackBuffer[1024 /
sizeof(CHAR)];
152#pragma warning(suppress: 6387)
153 int cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
156 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
159 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
161 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
162 std::unique_ptr<CHAR[]> szBuffer(
new CHAR[cch]);
163 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
164 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
167 throw std::system_error(GetLastError(), std::system_category(),
"WideCharToMultiByte failed");
170#pragma warning(suppress: 4127)
171 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
char)) {
172 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
175 WCHAR szStackBufferMBWC[512 /
sizeof(WCHAR)];
176#pragma warning(suppress: 6387)
177 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
180 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) :
static_cast<size_t>(cch) - 1;
181 _Assume_(count_inter < INT_MAX);
184 CHAR szStackBufferWCMB[512 /
sizeof(CHAR)];
185#pragma warning(suppress: 6387)
186 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
189 dst.append(
reinterpret_cast<const T_to*
>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
192 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
194 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
195 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
196 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
197 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
200 throw std::system_error(GetLastError(), std::system_category(),
"WideCharToMultiByte failed");
202 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
204 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
205 std::unique_ptr<WCHAR[]> szBufferMBWC(
new WCHAR[cch]);
206 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBufferMBWC.get(), cch);
207 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) :
static_cast<size_t>(cch) - 1;
210 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
211 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
212 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
213 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
216 throw std::system_error(GetLastError(), std::system_category(),
"MultiByteToWideChar failed");
219 dst.reserve(dst.size() + count_src);
220 T_to buf[1024 /
sizeof(T_to)];
221 size_t src_size = stdex::mul(
sizeof(T_from), count_src);
223 T_to* output = &buf[0];
224 size_t output_size =
sizeof(buf);
226 iconv(m_handle,
const_cast<char**
>(
reinterpret_cast<const char**
>(&src)), &src_size,
reinterpret_cast<char**
>(&output), &output_size);
227 dst.append(buf,
reinterpret_cast<T_to*
>(
reinterpret_cast<char*
>(buf) +
sizeof(buf) - output_size));
232 throw std::system_error(errno, std::system_category(),
"iconv failed");