stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
unicode.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023 Amebis
4*/
5
6#pragma once
7
8#include "compat.hpp"
9#include "endian.hpp"
10#include "math.hpp"
11#include "string.hpp"
12#include <stdint.h>
13#ifndef _WIN32
14#include <iconv.h>
15#include <langinfo.h>
16#endif
17#include <map>
18#include <memory>
19#include <string>
20
21#ifndef _WIN32
22#pragma GCC diagnostic push
23#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
24#endif
25
26namespace stdex
27{
28 enum class charset_id : uint16_t {
29#ifdef _WIN32
30 system = CP_ACP,
31 oem = CP_OEMCP,
32 utf7 = CP_UTF7,
33 utf8 = CP_UTF8,
34 utf16 = 1200 /*CP_WINUNICODE*/,
35 utf32 = 12000,
36 windows1250 = 1250,
37 windows1251 = 1251,
38 windows1252 = 1252,
39#else
40 system = 0,
41 utf7,
42 utf8,
43 utf16,
44 utf32,
45 windows1250,
46 windows1251,
47 windows1252,
48
49 _max
50#endif
51 };
52
53#ifdef _WIN32
54 constexpr charset_id wchar_t_charset = charset_id::utf16;
55#ifdef _UNICODE
56 constexpr charset_id system_charset = charset_id::utf16;
57#else
58 constexpr charset_id system_charset = charset_id::system;
59#endif
60#else
61 constexpr charset_id wchar_t_charset = charset_id::utf32;
62 constexpr charset_id system_charset = charset_id::system;
63#endif
64
65 inline charset_id charset_from_name(_In_z_ const char* name)
66 {
67 struct charset_less {
68 inline bool operator()(_In_z_ const char* a, _In_z_ const char* b) const
69 {
70 return stdex::stricmp(a, b) < 0;
71 }
72 };
73 static const std::map<const char*, charset_id, charset_less> charsets = {
74 { "UNICODE-1-1-UTF-7", charset_id::utf7 },
75 { "UTF-7", charset_id::utf7 },
76 { "CSUNICODE11UTF7", charset_id::utf7 },
77
78 { "UTF-8", charset_id::utf8 },
79 { "UTF8", charset_id::utf8 },
80
81 { "UTF-16", charset_id::utf16 },
82#if BYTE_ORDER == BIG_ENDIAN
83 { "UTF-16BE", charset_id::utf16 },
84#else
85 { "UTF-16LE", charset_id::utf16 },
86#endif
87
88 { "UTF-32", charset_id::utf32 },
89#if BYTE_ORDER == BIG_ENDIAN
90 { "UTF-32BE", charset_id::utf32 },
91#else
92 { "UTF-32LE", charset_id::utf32 },
93#endif
94
95 { "CP1250", charset_id::windows1250 },
96 { "MS-EE", charset_id::windows1250 },
97 { "WINDOWS-1250", charset_id::windows1250 },
98
99 { "CP1251", charset_id::windows1251 },
100 { "MS-CYRL", charset_id::windows1251 },
101 { "WINDOWS-1251", charset_id::windows1251 },
102
103 { "CP1252", charset_id::windows1252 },
104 { "MS-ANSI", charset_id::windows1252 },
105 { "WINDOWS-1252", charset_id::windows1252 },
106 };
107 if (auto el = charsets.find(name); el != charsets.end())
108 return el->second;
109 return charset_id::system;
110 }
111
115 template <typename T_from, typename T_to>
117 {
118 protected:
119 charset_id m_from, m_to;
120
121 public:
122 charset_encoder(_In_ charset_id from, _In_ charset_id to) :
123 m_from(from),
124 m_to(to)
125 {
126#ifdef _WIN32
127 m_from_wincp = to_encoding(from);
128 m_to_wincp = to_encoding(to);
129#else
130 m_handle = iconv_open(to_encoding(to), to_encoding(from));
131 if (m_handle == (iconv_t)-1)
132 throw std::system_error(errno, std::system_category(), "iconv_open failed");
133#endif
134 }
135
136#ifndef _WIN32
138 {
139 iconv_close(m_handle);
140 }
141#endif
142
143 inline charset_id from_encoding() const { return m_from; }
144 inline charset_id to_encoding() const { return m_to; }
145
153 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
154 void strcat(
155 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
156 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
157 {
158 _Assume_(src || !count_src);
159 count_src = stdex::strnlen<T_from>(src, count_src);
160 if (!count_src) _Unlikely_
161 return;
162
163#ifdef _WIN32
164 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
165 constexpr DWORD dwFlagsWCMB = 0;
166 constexpr LPCCH lpDefaultChar = NULL;
167
168 _Assume_(src);
169 if (m_from_wincp == m_to_wincp) _Unlikely_{
170 dst.append(reinterpret_cast<const T_to*>(src), count_src);
171 return;
172 }
173
174#pragma warning(suppress: 4127)
175 if constexpr (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(wchar_t)) {
176 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
177
178 // Try to convert to stack buffer first.
179 WCHAR szStackBuffer[1024 / sizeof(WCHAR)];
180#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
181 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
182 if (cch) {
183 // Append from stack.
184 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
185 return;
186 }
187 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
188 // Query the required output size. Allocate buffer. Then convert again.
189 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
190 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
191 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBuffer.get(), cch);
192 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
193 return;
194 }
195 throw std::system_error(GetLastError(), std::system_category(), "MultiByteToWideChar failed");
196 }
197
198#pragma warning(suppress: 4127)
199 if constexpr (sizeof(T_from) == sizeof(wchar_t) && sizeof(T_to) == sizeof(char)) {
200 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
201
202 // Try to convert to stack buffer first.
203 CHAR szStackBuffer[1024 / sizeof(CHAR)];
204#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpWideCharStr parameter wrong?
205 int cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
206 if (cch) {
207 // Copy from stack. Be careful not to include zero terminator.
208 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
209 return;
210 }
211 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
212 // Query the required output size. Allocate buffer. Then convert again.
213 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
214 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
215 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
216 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
217 return;
218 }
219 throw std::system_error(GetLastError(), std::system_category(), "WideCharToMultiByte failed");
220 }
221
222#pragma warning(suppress: 4127)
223 if constexpr (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(char)) {
224 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
225
226 // Try to convert to stack buffer first.
227 WCHAR szStackBufferMBWC[512 / sizeof(WCHAR)];
228#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
229 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
230 if (cch) {
231 // Append from stack.
232 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) : static_cast<size_t>(cch) - 1;
233 _Assume_(count_inter < INT_MAX);
234
235 // Try to convert to stack buffer first.
236 CHAR szStackBufferWCMB[512 / sizeof(CHAR)];
237#pragma warning(suppress: 6387) // Testing indicates szStackBufferMBWC may be NULL when count_inter is also 0. Is SAL of the lpWideCharStr parameter wrong?
238 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
239 if (cch) {
240 // Copy from stack. Be careful not to include zero terminator.
241 dst.append(reinterpret_cast<const T_to*>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
242 return;
243 }
244 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
245 // Query the required output size. Allocate buffer. Then convert again.
246 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
247 std::unique_ptr<CHAR[]> szBufferWCMB(new CHAR[cch]);
248 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
249 dst.append(reinterpret_cast<const T_to*>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
250 return;
251 }
252 throw std::system_error(GetLastError(), std::system_category(), "WideCharToMultiByte failed");
253 }
254 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
255 // Query the required output size. Allocate buffer. Then convert again.
256 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
257 std::unique_ptr<WCHAR[]> szBufferMBWC(new WCHAR[cch]);
258 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBufferMBWC.get(), cch);
259 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) : static_cast<size_t>(cch) - 1;
260
261 // Query the required output size. Allocate buffer. Then convert again.
262 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(), static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
263 std::unique_ptr<CHAR[]> szBufferWCMB(new CHAR[cch]);
264 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(), static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
265 dst.append(reinterpret_cast<const T_to*>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
266 return;
267 }
268 throw std::system_error(GetLastError(), std::system_category(), "MultiByteToWideChar failed");
269 }
270#else
271 dst.reserve(dst.size() + count_src);
272 T_to buf[1024 / sizeof(T_to)];
273 size_t src_size = stdex::mul(sizeof(T_from), count_src);
274 for (;;) {
275 T_to* output = &buf[0];
276 size_t output_size = sizeof(buf);
277 errno = 0;
278 iconv(m_handle, const_cast<char**>(reinterpret_cast<const char**>(&src)), &src_size, reinterpret_cast<char**>(&output), &output_size);
279 dst.append(buf, reinterpret_cast<T_to*>(reinterpret_cast<char*>(buf) + sizeof(buf) - output_size));
280 if (!errno)
281 break;
282 if (errno == E2BIG)
283 continue;
284 throw std::system_error(errno, std::system_category(), "iconv failed");
285 }
286#endif
287 }
288
295 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
296 inline void strcat(
297 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
298 _In_z_ const T_from* src)
299 {
300 strcat(dst, src, SIZE_MAX);
301 }
302
309 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>>
310 inline void strcat(
311 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
312 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
313 {
314 strcat(dst, src.data(), src.size());
315 }
316
324 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
325 inline void strcpy(
326 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
327 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
328 {
329 dst.clear();
330 strcat(dst, src, count_src);
331 }
332
339 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
340 inline void strcpy(
341 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
342 _In_z_ const T_from* src)
343 {
344 strcpy(dst, src, SIZE_MAX);
345 }
346
353 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>>
354 inline void strcpy(
355 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
356 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
357 {
358 strcpy(dst, src.data(), src.size());
359 }
360
367 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
368 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)
369 {
370 std::basic_string<T_to, _Traits_to, _Alloc_to> dst;
371 strcat(dst, src, count_src);
372 return dst;
373 }
374
380 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
381 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_z_ const T_from* src)
382 {
383 return convert(src, SIZE_MAX);
384 }
385
391 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>>
392 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
393 {
394 return convert(src.data(), src.size());
395 }
396
397 inline void clear()
398 {
399#ifndef _WIN32
400 iconv(m_handle, NULL, NULL, NULL, NULL);
401#endif
402 }
403
404 static charset_id system_charset()
405 {
406#ifdef _WIN32
407 return static_cast<charset_id>(GetACP());
408#else
409 return charset_from_name(nl_langinfo(CODESET));
410#endif
411 }
412
413#ifdef _WIN32
414 protected:
415 static UINT to_encoding(_In_ charset_id charset)
416 {
417 return
418 charset == charset_id::system ? GetACP() :
419 charset == charset_id::oem ? GetOEMCP() :
420 static_cast<UINT>(charset);
421 }
422
423 protected:
424 UINT m_from_wincp, m_to_wincp;
425#else
426 protected:
427 static const char* to_encoding(_In_ charset_id charset)
428 {
429 static const char* const encodings[static_cast<std::underlying_type_t<charset_id>>(charset_id::_max)] = {
430 "", // system
431 "UTF-7", // utf7
432 "UTF-8", // utf8
433#if BYTE_ORDER == BIG_ENDIAN
434 "UTF-16BE", // utf16
435 "UTF-32BE", // utf32
436#else
437 "UTF-16LE", // utf16
438 "UTF-32LE", // utf32
439#endif
440 "CP1250", // windows1250
441 "CP1251", // windows1251
442 "CP1252", // windows1252
443 };
444 return
445 charset == charset_id::system ? nl_langinfo(CODESET) :
446 encodings[static_cast<std::underlying_type_t<charset_id>>(charset)];
447 }
448
449 protected:
450 iconv_t m_handle;
451#endif
452 };
453
464#ifndef _WIN32
465 _Deprecated_("For better performance, consider a reusable charset_encoder")
466#endif
467 inline void strcat(
468 _Inout_ std::wstring& dst,
469 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
470 _In_ charset_id charset = charset_id::system)
471 {
472 charset_encoder<char, wchar_t>(charset, wchar_t_charset).strcat(dst, src, count_src);
473 }
474
475 _Deprecated_("Use stdex::strcat")
476 inline void str2wstr(
477 _Inout_ std::wstring& dst,
478 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
479 _In_ charset_id charset = charset_id::system)
480 {
481 strcat(dst, src, count_src, charset);
482 }
483
493#ifndef _WIN32
494 _Deprecated_("For better performance, consider a reusable charset_encoder")
495#endif
496 inline void strcat(
497 _Inout_ std::wstring& dst,
498 _In_ const std::string& src,
499 _In_ charset_id charset = charset_id::system)
500 {
501 strcat(dst, src.data(), src.size(), charset);
502 }
503
504 _Deprecated_("Use stdex::strcat")
505 inline void str2wstr(
506 _Inout_ std::wstring& dst,
507 _In_ const std::string& src,
508 _In_ charset_id charset = charset_id::system)
509 {
510 strcat(dst, src, charset);
511 }
512
523#ifndef _WIN32
524 _Deprecated_("For better performance, consider a reusable charset_encoder")
525#endif
526 inline void strcpy(
527 _Inout_ std::wstring& dst,
528 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
529 _In_ charset_id charset = charset_id::system)
530 {
531 dst.clear();
532 strcat(dst, src, count_src, charset);
533 }
534
544#ifndef _WIN32
545 _Deprecated_("For better performance, consider a reusable charset_encoder")
546#endif
547 inline void strcpy(
548 _Inout_ std::wstring& dst,
549 _In_ const std::string& src,
550 _In_ charset_id charset = charset_id::system)
551 {
552 strcpy(dst, src.data(), src.size(), charset);
553 }
554
565#ifndef _WIN32
566 _Deprecated_("For better performance, consider a reusable charset_encoder")
567#endif
568 inline std::wstring str2wstr(
569 _In_z_ const char* src,
570 _In_ charset_id charset = charset_id::system)
571 {
572 std::wstring dst;
573 strcat(dst, src, SIZE_MAX, charset);
574 return dst;
575 }
576
588#ifndef _WIN32
589 _Deprecated_("For better performance, consider a reusable charset_encoder")
590#endif
591 inline std::wstring str2wstr(
592 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
593 _In_ charset_id charset = charset_id::system)
594 {
595 std::wstring dst;
596 strcat(dst, src, count_src, charset);
597 return dst;
598 }
599
610#ifndef _WIN32
611 _Deprecated_("For better performance, consider a reusable charset_encoder")
612#endif
613 inline std::wstring str2wstr(
614 _In_ const std::string& src,
615 _In_ charset_id charset = charset_id::system)
616 {
617 return str2wstr(src.c_str(), src.size(), charset);
618 }
619
630#ifndef _WIN32
631 _Deprecated_("For better performance, consider a reusable charset_encoder")
632#endif
633 inline void strcat(
634 _Inout_ std::string& dst,
635 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
636 _In_ charset_id charset = charset_id::system)
637 {
638 charset_encoder<wchar_t, char>(wchar_t_charset, charset).strcat(dst, src, count_src);
639 }
640
641 _Deprecated_("Use stdex::strcat")
642 inline void wstr2str(
643 _Inout_ std::string& dst,
644 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
645 _In_ charset_id charset = charset_id::system)
646 {
647 strcat(dst, src, count_src, charset);
648 }
649
659#ifndef _WIN32
660 _Deprecated_("For better performance, consider a reusable charset_encoder")
661#endif
662 inline void strcat(
663 _Inout_ std::string& dst,
664 _In_ const std::wstring& src,
665 _In_ charset_id charset = charset_id::system)
666 {
667 strcat(dst, src.c_str(), src.size(), charset);
668 }
669
670 _Deprecated_("Use stdex::strcat")
671 inline void wstr2str(
672 _Inout_ std::string& dst,
673 _In_ const std::wstring& src,
674 _In_ charset_id charset = charset_id::system)
675 {
676 strcat(dst, src, charset);
677 }
678
689#ifndef _WIN32
690 _Deprecated_("For better performance, consider a reusable charset_encoder")
691#endif
692 inline void strcpy(
693 _Inout_ std::string& dst,
694 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
695 _In_ charset_id charset = charset_id::system)
696 {
697 dst.clear();
698 strcat(dst, src, count_src, charset);
699 }
700
710#ifndef _WIN32
711 _Deprecated_("For better performance, consider a reusable charset_encoder")
712#endif
713 inline void strcpy(
714 _Inout_ std::string& dst,
715 _In_ const std::wstring& src,
716 _In_ charset_id charset = charset_id::system)
717 {
718 strcpy(dst, src.data(), src.size(), charset);
719 }
720
731#ifndef _WIN32
732 _Deprecated_("For better performance, consider a reusable charset_encoder")
733#endif
734 inline std::string wstr2str(
735 _In_z_ const wchar_t* src,
736 _In_ charset_id charset = charset_id::system)
737 {
738 std::string dst;
739 strcat(dst, src, SIZE_MAX, charset);
740 return dst;
741 }
742
754#ifndef _WIN32
755 _Deprecated_("For better performance, consider a reusable charset_encoder")
756#endif
757 inline std::string wstr2str(
758 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
759 _In_ charset_id charset = charset_id::system)
760 {
761 std::string dst;
762 strcat(dst, src, count_src, charset);
763 return dst;
764 }
765
776#ifndef _WIN32
777 _Deprecated_("For better performance, consider a reusable charset_encoder")
778#endif
779 inline std::string wstr2str(
780 _In_ const std::wstring& src,
781 _In_ charset_id charset = charset_id::system)
782 {
783 return wstr2str(src.c_str(), src.size(), charset);
784 }
785}
786
787#ifndef _WIN32
788#pragma GCC diagnostic pop
789#endif
Encoding converter context.
Definition unicode.hpp:117
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:354
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:392
std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const T_from *src)
Return converted string.
Definition unicode.hpp:381
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:310
void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
Convert string.
Definition unicode.hpp:340
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:154
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:296
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:325
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:368