102 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to> &dst,
103 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src)
105 _Assume_(src || !count_src);
106 count_src = stdex::strnlen(src, count_src);
107 if (!count_src) _Unlikely_
111 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
112 constexpr DWORD dwFlagsWCMB = 0;
113 constexpr LPCCH lpDefaultChar = NULL;
116 if (m_from_wincp == m_to_wincp) _Unlikely_{
117 dst.append(
reinterpret_cast<const T_to*
>(src), count_src);
121#pragma warning(suppress: 4127)
122 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
wchar_t)) {
123 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
126 WCHAR szStackBuffer[1024 /
sizeof(WCHAR)];
127#pragma warning(suppress: 6387)
128 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
131 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
134 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
136 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
137 std::unique_ptr<WCHAR[]> szBuffer(
new WCHAR[cch]);
138 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch);
139 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
142 throw std::system_error(GetLastError(), std::system_category(),
"MultiByteToWideChar failed");
145#pragma warning(suppress: 4127)
146 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
wchar_t) &&
sizeof(T_to) ==
sizeof(
char)) {
147 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
150 CHAR szStackBuffer[1024 /
sizeof(CHAR)];
151#pragma warning(suppress: 6387)
152 int cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
155 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
158 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
160 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
161 std::unique_ptr<CHAR[]> szBuffer(
new CHAR[cch]);
162 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
163 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
166 throw std::system_error(GetLastError(), std::system_category(),
"WideCharToMultiByte failed");
169#pragma warning(suppress: 4127)
170 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
char)) {
171 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
174 WCHAR szStackBufferMBWC[512 /
sizeof(WCHAR)];
175#pragma warning(suppress: 6387)
176 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
179 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) :
static_cast<size_t>(cch) - 1;
180 _Assume_(count_inter < INT_MAX);
183 CHAR szStackBufferWCMB[512 /
sizeof(CHAR)];
184#pragma warning(suppress: 6387)
185 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
188 dst.append(
reinterpret_cast<const T_to*
>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
191 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
193 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
194 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
195 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
196 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
199 throw std::system_error(GetLastError(), std::system_category(),
"WideCharToMultiByte failed");
201 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
203 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
204 std::unique_ptr<WCHAR[]> szBufferMBWC(
new WCHAR[cch]);
205 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from_wincp), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBufferMBWC.get(), cch);
206 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) :
static_cast<size_t>(cch) - 1;
209 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
210 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
211 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
212 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
215 throw std::system_error(GetLastError(), std::system_category(),
"MultiByteToWideChar failed");
218 dst.reserve(dst.size() + count_src);
219 T_to buf[1024 /
sizeof(T_to)];
220 size_t src_size = stdex::mul(
sizeof(T_from), count_src);
222 T_to* output = &buf[0];
223 size_t output_size =
sizeof(buf);
225 iconv(m_handle,
const_cast<char**
>(
reinterpret_cast<const char**
>(&src)), &src_size,
reinterpret_cast<char**
>(&output), &output_size);
226 dst.append(buf,
reinterpret_cast<T_to*
>(
reinterpret_cast<char*
>(buf) +
sizeof(buf) - output_size));
231 throw std::system_error(errno, std::system_category(),
"iconv failed");