23 enum class charset_id : uint16_t {
46 constexpr charset_id wchar_t_charset = charset_id::utf16;
48 constexpr charset_id wchar_t_charset = charset_id::utf32;
54 template <
typename T_from,
typename T_to>
61 m_from = to_encoding(from);
62 m_to = to_encoding(to);
64 m_handle = iconv_open(to_encoding(to), to_encoding(from));
65 if (m_handle == (iconv_t)-1)
66 throw std::runtime_error(
"iconv_open failed");
73 iconv_close(m_handle);
84 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
86 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to> &dst,
87 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src)
89 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
90 constexpr DWORD dwFlagsWCMB = 0;
91 constexpr LPCCH lpDefaultChar = NULL;
93 assert(src || !count_src);
94 count_src = stdex::strnlen(src, count_src);
95 if (!count_src) _Unlikely_
98 _Analysis_assume_(src);
99 if (m_from == m_to) _Unlikely_{
100 dst.append(
reinterpret_cast<const T_to*
>(src), count_src);
104 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
wchar_t)) {
105 assert(count_src < INT_MAX || count_src == SIZE_MAX);
108 WCHAR szStackBuffer[1024 /
sizeof(WCHAR)];
109#pragma warning(suppress: 6387)
110 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
113 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
116 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
118 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
119 std::unique_ptr<WCHAR[]> szBuffer(
new WCHAR[cch]);
120 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch);
121 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
124 throw std::runtime_error(
"MultiByteToWideChar failed");
127 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
wchar_t) &&
sizeof(T_to) ==
sizeof(
char)) {
128 assert(count_src < INT_MAX || count_src == SIZE_MAX);
131 CHAR szStackBuffer[1024 /
sizeof(CHAR)];
132#pragma warning(suppress: 6387)
133 int cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
136 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
139 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
141 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
142 std::unique_ptr<CHAR[]> szBuffer(
new CHAR[cch]);
143 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
144 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
147 throw std::runtime_error(
"WideCharToMultiByte failed");
150 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
char)) {
151 assert(count_src < INT_MAX || count_src == SIZE_MAX);
154 WCHAR szStackBufferMBWC[512 /
sizeof(WCHAR)];
155#pragma warning(suppress: 6387)
156 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
159 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) :
static_cast<size_t>(cch) - 1;
160 assert(count_inter < INT_MAX);
163 CHAR szStackBufferWCMB[512 /
sizeof(CHAR)];
164#pragma warning(suppress: 6387)
165 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
168 dst.append(
reinterpret_cast<const T_to*
>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
171 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
173 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
174 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
175 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
176 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
179 throw std::runtime_error(
"WideCharToMultiByte failed");
181 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
183 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
184 std::unique_ptr<WCHAR[]> szBufferMBWC(
new WCHAR[cch]);
185 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBufferMBWC.get(), cch);
186 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) :
static_cast<size_t>(cch) - 1;
189 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
190 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
191 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
192 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
195 throw std::runtime_error(
"MultiByteToWideChar failed");
198 T_to buf[1024 /
sizeof(T_to)];
199 size_t src_size = stdex::mul(
sizeof(T_from), count_src);
201 T_to* output = &buf[0];
202 size_t output_size =
sizeof(buf);
204 iconv(m_handle, (
char**)&src, &src_size, (
char**)&output, &output_size);
206 throw std::runtime_error(
"iconv failed");
207 dst.append(buf,
reinterpret_cast<T_to*
>(
reinterpret_cast<char*
>(buf) +
sizeof(buf) - output_size));
218 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
220 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
221 _In_z_
const T_from* src)
223 strcat(dst, src, SIZE_MAX);
232 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>,
class _Traits_from = std::
char_traits<T_from>,
class _Alloc_from = std::allocator<T_from>>
234 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
235 _In_
const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
237 strcat(dst, src.data(), src.size());
247 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
249 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
250 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src)
253 strcat(dst, src, count_src);
262 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
264 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
265 _In_z_
const T_from* src)
267 strcpy(dst, src, SIZE_MAX);
276 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>,
class _Traits_from = std::
char_traits<T_from>,
class _Alloc_from = std::allocator<T_from>>
278 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
279 _In_
const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
281 strcpy(dst, src.data(), src.size());
290 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
291 inline std::basic_string<T_to, _Traits_to, _Alloc_to>
convert(_In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src)
293 std::basic_string<T_to, _Traits_to, _Alloc_to> dst;
294 strcat(dst, src, count_src);
303 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
304 inline std::basic_string<T_to, _Traits_to, _Alloc_to>
convert(_In_z_
const T_from* src)
314 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>,
class _Traits_from = std::
char_traits<T_from>,
class _Alloc_from = std::allocator<T_from>>
315 inline std::basic_string<T_to, _Traits_to, _Alloc_to>
convert(_In_
const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
317 return convert(src.data(), src.size());
323 iconv(m_handle, NULL, NULL, NULL, NULL);
329 static UINT to_encoding(_In_ charset_id charset)
332 charset == charset_id::system ? GetACP() :
333 charset == charset_id::oem ? GetOEMCP() :
334 static_cast<UINT>(charset);
341 static const char* to_encoding(_In_ charset_id charset)
343 static const char*
const encodings[
static_cast<std::underlying_type_t<charset_id>
>(charset_id::_max)] = {
346#if BYTE_ORDER == BIG_ENDIAN
358 charset == charset_id::system ? nl_langinfo(LC_CTYPE) :
359 encodings[static_cast<std::underlying_type_t<charset_id>>(charset))];
378 _Inout_ std::wstring& dst,
379 _In_reads_or_z_opt_(count_src)
const char* src, _In_
size_t count_src,
380 _In_ charset_id charset = charset_id::system)
382 charset_encoder<char, wchar_t>(charset, wchar_t_charset).strcat(dst, src, count_src);
385 _Deprecated_(
"Use stdex::strcat")
386 inline
void str2wstr(
387 _Inout_ std::wstring& dst,
388 _In_reads_or_z_opt_(count_src) const
char* src, _In_
size_t count_src,
389 _In_ charset_id charset = charset_id::system)
391 strcat(dst, src, count_src, charset);
404 _Inout_ std::wstring& dst,
405 _In_
const std::string& src,
406 _In_ charset_id charset = charset_id::system)
408 strcat(dst, src.data(), src.size(), charset);
411 _Deprecated_(
"Use stdex::strcat")
412 inline
void str2wstr(
413 _Inout_ std::wstring& dst,
414 _In_ const std::
string& src,
415 _In_ charset_id charset = charset_id::system)
417 strcat(dst, src, charset);
431 _Inout_ std::wstring& dst,
432 _In_reads_or_z_opt_(count_src)
const char* src, _In_
size_t count_src,
433 _In_ charset_id charset = charset_id::system)
436 strcat(dst, src, count_src, charset);
449 _Inout_ std::wstring& dst,
450 _In_
const std::string& src,
451 _In_ charset_id charset = charset_id::system)
453 strcpy(dst, src.data(), src.size(), charset);
466 inline std::wstring str2wstr(
467 _In_z_
const char* src,
468 _In_ charset_id charset = charset_id::system)
471 strcat(dst, src, SIZE_MAX, charset);
486 inline std::wstring str2wstr(
487 _In_reads_or_z_opt_(count_src)
const char* src, _In_
size_t count_src,
488 _In_ charset_id charset = charset_id::system)
491 strcat(dst, src, count_src, charset);
505 inline std::wstring str2wstr(
506 _In_
const std::string& src,
507 _In_ charset_id charset = charset_id::system)
509 return str2wstr(src.c_str(), src.size(), charset);
523 _Inout_ std::string& dst,
524 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
525 _In_ charset_id charset = charset_id::system)
527 charset_encoder<wchar_t, char>(wchar_t_charset, charset).strcat(dst, src, count_src);
530 _Deprecated_(
"Use stdex::strcat")
531 inline
void wstr2str(
532 _Inout_ std::
string& dst,
533 _In_reads_or_z_opt_(count_src) const
wchar_t* src, _In_
size_t count_src,
534 _In_ charset_id charset = charset_id::system)
536 strcat(dst, src, count_src, charset);
549 _Inout_ std::string& dst,
550 _In_
const std::wstring& src,
551 _In_ charset_id charset = charset_id::system)
553 strcat(dst, src.c_str(), src.size(), charset);
556 _Deprecated_(
"Use stdex::strcat")
557 inline
void wstr2str(
558 _Inout_ std::
string& dst,
559 _In_ const std::wstring& src,
560 _In_ charset_id charset = charset_id::system)
562 strcat(dst, src, charset);
576 _Inout_ std::string& dst,
577 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
578 _In_ charset_id charset = charset_id::system)
581 strcat(dst, src, count_src, charset);
594 _Inout_ std::string& dst,
595 _In_
const std::wstring& src,
596 _In_ charset_id charset = charset_id::system)
598 strcpy(dst, src.data(), src.size(), charset);
611 inline std::string wstr2str(
612 _In_z_
const wchar_t* src,
613 _In_ charset_id charset = charset_id::system)
616 strcat(dst, src, SIZE_MAX, charset);
631 inline std::string wstr2str(
632 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
633 _In_ charset_id charset = charset_id::system)
636 strcat(dst, src, count_src, charset);
650 inline std::string wstr2str(
651 _In_
const std::wstring& src,
652 _In_ charset_id charset = charset_id::system)
654 return wstr2str(src.c_str(), src.size(), charset);
Encoding converter context.
Definition unicode.hpp:56
void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const std::basic_string< T_from, _Traits_from, _Alloc_from > &src)
Convert string.
Definition unicode.hpp:277
std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const std::basic_string< T_from, _Traits_from, _Alloc_from > &src)
Return converted string.
Definition unicode.hpp:315
std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const T_from *src)
Return converted string.
Definition unicode.hpp:304
void strcat(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const std::basic_string< T_from, _Traits_from, _Alloc_from > &src)
Convert string and append to string.
Definition unicode.hpp:233
void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
Convert string.
Definition unicode.hpp:263
void strcat(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, _In_reads_or_z_opt_(count_src) const T_from *src, size_t count_src)
Convert string and append to string.
Definition unicode.hpp:85
void strcat(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
Convert string and append to string.
Definition unicode.hpp:219
void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, _In_reads_or_z_opt_(count_src) const T_from *src, size_t count_src)
Convert string.
Definition unicode.hpp:248
std::basic_string< T_to, _Traits_to, _Alloc_to > convert(_In_reads_or_z_opt_(count_src) const T_from *src, size_t count_src)
Return converted string.
Definition unicode.hpp:291