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 assert(src || !count_src);
90 count_src = stdex::strnlen(src, count_src);
91 if (!count_src) _Unlikely_
95 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
96 constexpr DWORD dwFlagsWCMB = 0;
97 constexpr LPCCH lpDefaultChar = NULL;
99 _Analysis_assume_(src);
100 if (m_from == m_to) _Unlikely_{
101 dst.append(
reinterpret_cast<const T_to*
>(src), count_src);
105 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
wchar_t)) {
106 assert(count_src < INT_MAX || count_src == SIZE_MAX);
109 WCHAR szStackBuffer[1024 /
sizeof(WCHAR)];
110#pragma warning(suppress: 6387)
111 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
114 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
117 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
119 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
120 std::unique_ptr<WCHAR[]> szBuffer(
new WCHAR[cch]);
121 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch);
122 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
125 throw std::runtime_error(
"MultiByteToWideChar failed");
128 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
wchar_t) &&
sizeof(T_to) ==
sizeof(
char)) {
129 assert(count_src < INT_MAX || count_src == SIZE_MAX);
132 CHAR szStackBuffer[1024 /
sizeof(CHAR)];
133#pragma warning(suppress: 6387)
134 int cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
137 dst.append(
reinterpret_cast<const T_to*
>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) :
static_cast<size_t>(cch) - 1);
140 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
142 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
143 std::unique_ptr<CHAR[]> szBuffer(
new CHAR[cch]);
144 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB,
reinterpret_cast<LPCWCH
>(src),
static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
145 dst.append(
reinterpret_cast<const T_to*
>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) :
static_cast<size_t>(cch) - 1);
148 throw std::runtime_error(
"WideCharToMultiByte failed");
151 if _Constexpr_ (
sizeof(T_from) ==
sizeof(
char) &&
sizeof(T_to) ==
sizeof(
char)) {
152 assert(count_src < INT_MAX || count_src == SIZE_MAX);
155 WCHAR szStackBufferMBWC[512 /
sizeof(WCHAR)];
156#pragma warning(suppress: 6387)
157 int cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
160 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) :
static_cast<size_t>(cch) - 1;
161 assert(count_inter < INT_MAX);
164 CHAR szStackBufferWCMB[512 /
sizeof(CHAR)];
165#pragma warning(suppress: 6387)
166 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
169 dst.append(
reinterpret_cast<const T_to*
>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
172 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
174 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
175 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
176 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szStackBufferMBWC,
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
177 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
180 throw std::runtime_error(
"WideCharToMultiByte failed");
182 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
184 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), NULL, 0);
185 std::unique_ptr<WCHAR[]> szBufferMBWC(
new WCHAR[cch]);
186 cch = MultiByteToWideChar(
static_cast<UINT
>(m_from), dwFlagsMBWC,
reinterpret_cast<LPCCH
>(src),
static_cast<int>(count_src), szBufferMBWC.get(), cch);
187 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) :
static_cast<size_t>(cch) - 1;
190 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
191 std::unique_ptr<CHAR[]> szBufferWCMB(
new CHAR[cch]);
192 cch = WideCharToMultiByte(
static_cast<UINT
>(m_to), dwFlagsWCMB, szBufferMBWC.get(),
static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
193 dst.append(
reinterpret_cast<const T_to*
>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
196 throw std::runtime_error(
"MultiByteToWideChar failed");
199 dst.reserve(dst.size() + count_src);
200 T_to buf[1024 /
sizeof(T_to)];
201 size_t src_size = stdex::mul(
sizeof(T_from), count_src);
203 T_to* output = &buf[0];
204 size_t output_size =
sizeof(buf);
206 iconv(m_handle,
const_cast<char**
>(
reinterpret_cast<const char**
>(&src)), &src_size,
reinterpret_cast<char**
>(&output), &output_size);
207 dst.append(buf,
reinterpret_cast<T_to*
>(
reinterpret_cast<char*
>(buf) +
sizeof(buf) - output_size));
212 throw std::runtime_error(
"iconv failed");
223 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
225 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
226 _In_z_
const T_from* src)
228 strcat(dst, src, SIZE_MAX);
237 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>>
239 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
240 _In_
const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
242 strcat(dst, src.data(), src.size());
252 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
254 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
255 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src)
258 strcat(dst, src, count_src);
267 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
269 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
270 _In_z_
const T_from* src)
272 strcpy(dst, src, SIZE_MAX);
281 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>>
283 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
284 _In_
const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
286 strcpy(dst, src.data(), src.size());
295 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
296 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)
298 std::basic_string<T_to, _Traits_to, _Alloc_to> dst;
299 strcat(dst, src, count_src);
308 template <
class _Traits_to = std::
char_traits<T_to>,
class _Alloc_to = std::allocator<T_to>>
309 inline std::basic_string<T_to, _Traits_to, _Alloc_to>
convert(_In_z_
const T_from* src)
319 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>>
320 inline std::basic_string<T_to, _Traits_to, _Alloc_to>
convert(_In_
const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
322 return convert(src.data(), src.size());
328 iconv(m_handle, NULL, NULL, NULL, NULL);
332 static charset_id system_charset()
335 return static_cast<charset_id
>(GetACP());
337 const char* lctype = nl_langinfo(CODESET);
338 if (strcmp(lctype,
"UTF-8") == 0)
return charset_id::utf8;
339 if (strcmp(lctype,
"UTF-16") == 0)
return charset_id::utf16;
340#if BYTE_ORDER == BIG_ENDIAN
341 if (strcmp(lctype,
"UTF-16BE") == 0)
return charset_id::utf16;
343 if (strcmp(lctype,
"UTF-16LE") == 0)
return charset_id::utf16;
345 if (strcmp(lctype,
"UTF-32") == 0)
return charset_id::utf32;
346#if BYTE_ORDER == BIG_ENDIAN
347 if (strcmp(lctype,
"UTF-32BE") == 0)
return charset_id::utf32;
349 if (strcmp(lctype,
"UTF-32LE") == 0)
return charset_id::utf32;
351 if (strcmp(lctype,
"CP1250") == 0)
return charset_id::windows1250;
352 if (strcmp(lctype,
"CP1251") == 0)
return charset_id::windows1251;
353 if (strcmp(lctype,
"CP1252") == 0)
return charset_id::windows1252;
354 return charset_id::system;
360 static UINT to_encoding(_In_ charset_id charset)
363 charset == charset_id::system ? GetACP() :
364 charset == charset_id::oem ? GetOEMCP() :
365 static_cast<UINT>(charset);
372 static const char* to_encoding(_In_ charset_id charset)
374 static const char*
const encodings[
static_cast<std::underlying_type_t<charset_id>
>(charset_id::_max)] = {
377#if BYTE_ORDER == BIG_ENDIAN
389 charset == charset_id::system ? nl_langinfo(CODESET) :
390 encodings[static_cast<std::underlying_type_t<charset_id>>(charset)];
409 _Inout_ std::wstring& dst,
410 _In_reads_or_z_opt_(count_src)
const char* src, _In_
size_t count_src,
411 _In_ charset_id charset = charset_id::system)
413 charset_encoder<char, wchar_t>(charset, wchar_t_charset).strcat(dst, src, count_src);
416 _Deprecated_(
"Use stdex::strcat")
417 inline
void str2wstr(
418 _Inout_ std::wstring& dst,
419 _In_reads_or_z_opt_(count_src) const
char* src, _In_
size_t count_src,
420 _In_ charset_id charset = charset_id::system)
422 strcat(dst, src, count_src, charset);
435 _Inout_ std::wstring& dst,
436 _In_
const std::string& src,
437 _In_ charset_id charset = charset_id::system)
439 strcat(dst, src.data(), src.size(), charset);
442 _Deprecated_(
"Use stdex::strcat")
443 inline
void str2wstr(
444 _Inout_ std::wstring& dst,
445 _In_ const std::
string& src,
446 _In_ charset_id charset = charset_id::system)
448 strcat(dst, src, charset);
462 _Inout_ std::wstring& dst,
463 _In_reads_or_z_opt_(count_src)
const char* src, _In_
size_t count_src,
464 _In_ charset_id charset = charset_id::system)
467 strcat(dst, src, count_src, charset);
480 _Inout_ std::wstring& dst,
481 _In_
const std::string& src,
482 _In_ charset_id charset = charset_id::system)
484 strcpy(dst, src.data(), src.size(), charset);
497 inline std::wstring str2wstr(
498 _In_z_
const char* src,
499 _In_ charset_id charset = charset_id::system)
502 strcat(dst, src, SIZE_MAX, charset);
517 inline std::wstring str2wstr(
518 _In_reads_or_z_opt_(count_src)
const char* src, _In_
size_t count_src,
519 _In_ charset_id charset = charset_id::system)
522 strcat(dst, src, count_src, charset);
536 inline std::wstring str2wstr(
537 _In_
const std::string& src,
538 _In_ charset_id charset = charset_id::system)
540 return str2wstr(src.c_str(), src.size(), charset);
554 _Inout_ std::string& dst,
555 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
556 _In_ charset_id charset = charset_id::system)
558 charset_encoder<wchar_t, char>(wchar_t_charset, charset).strcat(dst, src, count_src);
561 _Deprecated_(
"Use stdex::strcat")
562 inline
void wstr2str(
563 _Inout_ std::
string& dst,
564 _In_reads_or_z_opt_(count_src) const
wchar_t* src, _In_
size_t count_src,
565 _In_ charset_id charset = charset_id::system)
567 strcat(dst, src, count_src, charset);
580 _Inout_ std::string& dst,
581 _In_
const std::wstring& src,
582 _In_ charset_id charset = charset_id::system)
584 strcat(dst, src.c_str(), src.size(), charset);
587 _Deprecated_(
"Use stdex::strcat")
588 inline
void wstr2str(
589 _Inout_ std::
string& dst,
590 _In_ const std::wstring& src,
591 _In_ charset_id charset = charset_id::system)
593 strcat(dst, src, charset);
607 _Inout_ std::string& dst,
608 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
609 _In_ charset_id charset = charset_id::system)
612 strcat(dst, src, count_src, charset);
625 _Inout_ std::string& dst,
626 _In_
const std::wstring& src,
627 _In_ charset_id charset = charset_id::system)
629 strcpy(dst, src.data(), src.size(), charset);
642 inline std::string wstr2str(
643 _In_z_
const wchar_t* src,
644 _In_ charset_id charset = charset_id::system)
647 strcat(dst, src, SIZE_MAX, charset);
662 inline std::string wstr2str(
663 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
664 _In_ charset_id charset = charset_id::system)
667 strcat(dst, src, count_src, charset);
681 inline std::string wstr2str(
682 _In_
const std::wstring& src,
683 _In_ charset_id charset = charset_id::system)
685 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:282
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:320
std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const T_from *src)
Return converted string.
Definition unicode.hpp:309
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:238
void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
Convert string.
Definition unicode.hpp:268
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:224
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:253
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:296