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
68 template <typename T_from, typename T_to>
70 {
71 protected:
72 charset_id m_from, m_to;
73
74 public:
75 charset_encoder(_In_ charset_id from, _In_ charset_id to) :
76 m_from(from),
77 m_to(to)
78 {
79#ifdef _WIN32
80 m_from_wincp = to_encoding(from);
81 m_to_wincp = to_encoding(to);
82#else
83 m_handle = iconv_open(to_encoding(to), to_encoding(from));
84 if (m_handle == (iconv_t)-1)
85 throw std::system_error(errno, std::system_category(), "iconv_open failed");
86#endif
87 }
88
89#ifndef _WIN32
91 {
92 iconv_close(m_handle);
93 }
94#endif
95
96 inline charset_id from_encoding() const { return m_from; }
97 inline charset_id to_encoding() const { return m_to; }
98
106 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
107 void strcat(
108 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to> &dst,
109 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
110 {
111 _Assume_(src || !count_src);
112 count_src = stdex::strnlen<T_from>(src, count_src);
113 if (!count_src) _Unlikely_
114 return;
115
116#ifdef _WIN32
117 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
118 constexpr DWORD dwFlagsWCMB = 0;
119 constexpr LPCCH lpDefaultChar = NULL;
120
121 _Assume_(src);
122 if (m_from_wincp == m_to_wincp) _Unlikely_{
123 dst.append(reinterpret_cast<const T_to*>(src), count_src);
124 return;
125 }
126
127#pragma warning(suppress: 4127)
128 if _Constexpr_ (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(wchar_t)) {
129 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
130
131 // Try to convert to stack buffer first.
132 WCHAR szStackBuffer[1024 / sizeof(WCHAR)];
133#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
134 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
135 if (cch) {
136 // Append from stack.
137 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
138 return;
139 }
140 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
141 // Query the required output size. Allocate buffer. Then convert again.
142 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
143 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
144 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBuffer.get(), cch);
145 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
146 return;
147 }
148 throw std::system_error(GetLastError(), std::system_category(), "MultiByteToWideChar failed");
149 }
150
151#pragma warning(suppress: 4127)
152 if _Constexpr_ (sizeof(T_from) == sizeof(wchar_t) && sizeof(T_to) == sizeof(char)) {
153 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
154
155 // Try to convert to stack buffer first.
156 CHAR szStackBuffer[1024 / sizeof(CHAR)];
157#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpWideCharStr parameter wrong?
158 int cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
159 if (cch) {
160 // Copy from stack. Be careful not to include zero terminator.
161 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
162 return;
163 }
164 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
165 // Query the required output size. Allocate buffer. Then convert again.
166 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
167 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
168 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
169 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
170 return;
171 }
172 throw std::system_error(GetLastError(), std::system_category(), "WideCharToMultiByte failed");
173 }
174
175#pragma warning(suppress: 4127)
176 if _Constexpr_ (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(char)) {
177 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
178
179 // Try to convert to stack buffer first.
180 WCHAR szStackBufferMBWC[512 / sizeof(WCHAR)];
181#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
182 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
183 if (cch) {
184 // Append from stack.
185 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) : static_cast<size_t>(cch) - 1;
186 _Assume_(count_inter < INT_MAX);
187
188 // Try to convert to stack buffer first.
189 CHAR szStackBufferWCMB[512 / sizeof(CHAR)];
190#pragma warning(suppress: 6387) // Testing indicates szStackBufferMBWC may be NULL when count_inter is also 0. Is SAL of the lpWideCharStr parameter wrong?
191 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
192 if (cch) {
193 // Copy from stack. Be careful not to include zero terminator.
194 dst.append(reinterpret_cast<const T_to*>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
195 return;
196 }
197 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
198 // Query the required output size. Allocate buffer. Then convert again.
199 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
200 std::unique_ptr<CHAR[]> szBufferWCMB(new CHAR[cch]);
201 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
202 dst.append(reinterpret_cast<const T_to*>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
203 return;
204 }
205 throw std::system_error(GetLastError(), std::system_category(), "WideCharToMultiByte failed");
206 }
207 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
208 // Query the required output size. Allocate buffer. Then convert again.
209 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
210 std::unique_ptr<WCHAR[]> szBufferMBWC(new WCHAR[cch]);
211 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBufferMBWC.get(), cch);
212 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) : static_cast<size_t>(cch) - 1;
213
214 // Query the required output size. Allocate buffer. Then convert again.
215 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(), static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
216 std::unique_ptr<CHAR[]> szBufferWCMB(new CHAR[cch]);
217 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(), static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
218 dst.append(reinterpret_cast<const T_to*>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
219 return;
220 }
221 throw std::system_error(GetLastError(), std::system_category(), "MultiByteToWideChar failed");
222 }
223#else
224 dst.reserve(dst.size() + count_src);
225 T_to buf[1024 / sizeof(T_to)];
226 size_t src_size = stdex::mul(sizeof(T_from), count_src);
227 for (;;) {
228 T_to* output = &buf[0];
229 size_t output_size = sizeof(buf);
230 errno = 0;
231 iconv(m_handle, const_cast<char**>(reinterpret_cast<const char**>(&src)), &src_size, reinterpret_cast<char**>(&output), &output_size);
232 dst.append(buf, reinterpret_cast<T_to*>(reinterpret_cast<char*>(buf) + sizeof(buf) - output_size));
233 if (!errno)
234 break;
235 if (errno == E2BIG)
236 continue;
237 throw std::system_error(errno, std::system_category(), "iconv failed");
238 }
239#endif
240 }
241
248 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
249 inline void strcat(
250 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
251 _In_z_ const T_from* src)
252 {
253 strcat(dst, src, SIZE_MAX);
254 }
255
262 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>>
263 inline void strcat(
264 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
265 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
266 {
267 strcat(dst, src.data(), src.size());
268 }
269
277 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
278 inline void strcpy(
279 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
280 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
281 {
282 dst.clear();
283 strcat(dst, src, count_src);
284 }
285
292 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
293 inline void strcpy(
294 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
295 _In_z_ const T_from* src)
296 {
297 strcpy(dst, src, SIZE_MAX);
298 }
299
306 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>>
307 inline void strcpy(
308 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
309 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
310 {
311 strcpy(dst, src.data(), src.size());
312 }
313
320 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
321 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)
322 {
323 std::basic_string<T_to, _Traits_to, _Alloc_to> dst;
324 strcat(dst, src, count_src);
325 return dst;
326 }
327
333 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
334 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_z_ const T_from* src)
335 {
336 return convert(src, SIZE_MAX);
337 }
338
344 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>>
345 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
346 {
347 return convert(src.data(), src.size());
348 }
349
350 inline void clear()
351 {
352#ifndef _WIN32
353 iconv(m_handle, NULL, NULL, NULL, NULL);
354#endif
355 }
356
357 static charset_id system_charset()
358 {
359#ifdef _WIN32
360 return static_cast<charset_id>(GetACP());
361#else
362 static const std::map<const char*, charset_id> charsets = {
363 { "UNICODE-1-1-UTF-7", charset_id::utf7 },
364 { "UTF-7", charset_id::utf7 },
365 { "CSUNICODE11UTF7", charset_id::utf7 },
366
367 { "UTF-8", charset_id::utf8 },
368 { "UTF8", charset_id::utf8 },
369
370 { "UTF-16", charset_id::utf16 },
371#if BYTE_ORDER == BIG_ENDIAN
372 { "UTF-16BE", charset_id::utf16 },
373#else
374 { "UTF-16LE", charset_id::utf16 },
375#endif
376
377 { "UTF-32", charset_id::utf32 },
378#if BYTE_ORDER == BIG_ENDIAN
379 { "UTF-32BE", charset_id::utf32 },
380#else
381 { "UTF-32LE", charset_id::utf32 },
382#endif
383
384 { "CP1250", charset_id::windows1250 },
385 { "MS-EE", charset_id::windows1250 },
386 { "WINDOWS-1250", charset_id::windows1250 },
387
388 { "CP1251", charset_id::windows1251 },
389 { "MS-CYRL", charset_id::windows1251 },
390 { "WINDOWS-1251", charset_id::windows1251 },
391
392 { "CP1252", charset_id::windows1252 },
393 { "MS-ANSI", charset_id::windows1252 },
394 { "WINDOWS-1252", charset_id::windows1252 },
395 };
396 const char* lctype = nl_langinfo(CODESET);
397 if (auto el = charsets.find(lctype); el != charsets.end())
398 return el->second;
399 return charset_id::system;
400#endif
401 }
402
403#ifdef _WIN32
404 protected:
405 static UINT to_encoding(_In_ charset_id charset)
406 {
407 return
408 charset == charset_id::system ? GetACP() :
409 charset == charset_id::oem ? GetOEMCP() :
410 static_cast<UINT>(charset);
411 }
412
413 protected:
414 UINT m_from_wincp, m_to_wincp;
415#else
416 protected:
417 static const char* to_encoding(_In_ charset_id charset)
418 {
419 static const char* const encodings[static_cast<std::underlying_type_t<charset_id>>(charset_id::_max)] = {
420 "", // system
421 "UTF-7", // utf7
422 "UTF-8", // utf8
423#if BYTE_ORDER == BIG_ENDIAN
424 "UTF-16BE", // utf16
425 "UTF-32BE", // utf32
426#else
427 "UTF-16LE", // utf16
428 "UTF-32LE", // utf32
429#endif
430 "CP1250", // windows1250
431 "CP1251", // windows1251
432 "CP1252", // windows1252
433 };
434 return
435 charset == charset_id::system ? nl_langinfo(CODESET) :
436 encodings[static_cast<std::underlying_type_t<charset_id>>(charset)];
437 }
438
439 protected:
440 iconv_t m_handle;
441#endif
442 };
443
454#ifndef _WIN32
455 _Deprecated_("For better performance, consider a reusable charset_encoder")
456#endif
457 inline void strcat(
458 _Inout_ std::wstring& dst,
459 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
460 _In_ charset_id charset = charset_id::system)
461 {
462 charset_encoder<char, wchar_t>(charset, wchar_t_charset).strcat(dst, src, count_src);
463 }
464
465 _Deprecated_("Use stdex::strcat")
466 inline void str2wstr(
467 _Inout_ std::wstring& dst,
468 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
469 _In_ charset_id charset = charset_id::system)
470 {
471 strcat(dst, src, count_src, charset);
472 }
473
483#ifndef _WIN32
484 _Deprecated_("For better performance, consider a reusable charset_encoder")
485#endif
486 inline void strcat(
487 _Inout_ std::wstring& dst,
488 _In_ const std::string& src,
489 _In_ charset_id charset = charset_id::system)
490 {
491 strcat(dst, src.data(), src.size(), charset);
492 }
493
494 _Deprecated_("Use stdex::strcat")
495 inline void str2wstr(
496 _Inout_ std::wstring& dst,
497 _In_ const std::string& src,
498 _In_ charset_id charset = charset_id::system)
499 {
500 strcat(dst, src, charset);
501 }
502
513#ifndef _WIN32
514 _Deprecated_("For better performance, consider a reusable charset_encoder")
515#endif
516 inline void strcpy(
517 _Inout_ std::wstring& dst,
518 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
519 _In_ charset_id charset = charset_id::system)
520 {
521 dst.clear();
522 strcat(dst, src, count_src, charset);
523 }
524
534#ifndef _WIN32
535 _Deprecated_("For better performance, consider a reusable charset_encoder")
536#endif
537 inline void strcpy(
538 _Inout_ std::wstring& dst,
539 _In_ const std::string& src,
540 _In_ charset_id charset = charset_id::system)
541 {
542 strcpy(dst, src.data(), src.size(), charset);
543 }
544
555#ifndef _WIN32
556 _Deprecated_("For better performance, consider a reusable charset_encoder")
557#endif
558 inline std::wstring str2wstr(
559 _In_z_ const char* src,
560 _In_ charset_id charset = charset_id::system)
561 {
562 std::wstring dst;
563 strcat(dst, src, SIZE_MAX, charset);
564 return dst;
565 }
566
578#ifndef _WIN32
579 _Deprecated_("For better performance, consider a reusable charset_encoder")
580#endif
581 inline std::wstring str2wstr(
582 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
583 _In_ charset_id charset = charset_id::system)
584 {
585 std::wstring dst;
586 strcat(dst, src, count_src, charset);
587 return dst;
588 }
589
600#ifndef _WIN32
601 _Deprecated_("For better performance, consider a reusable charset_encoder")
602#endif
603 inline std::wstring str2wstr(
604 _In_ const std::string& src,
605 _In_ charset_id charset = charset_id::system)
606 {
607 return str2wstr(src.c_str(), src.size(), charset);
608 }
609
620#ifndef _WIN32
621 _Deprecated_("For better performance, consider a reusable charset_encoder")
622#endif
623 inline void strcat(
624 _Inout_ std::string& dst,
625 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
626 _In_ charset_id charset = charset_id::system)
627 {
628 charset_encoder<wchar_t, char>(wchar_t_charset, charset).strcat(dst, src, count_src);
629 }
630
631 _Deprecated_("Use stdex::strcat")
632 inline void wstr2str(
633 _Inout_ std::string& dst,
634 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
635 _In_ charset_id charset = charset_id::system)
636 {
637 strcat(dst, src, count_src, charset);
638 }
639
649#ifndef _WIN32
650 _Deprecated_("For better performance, consider a reusable charset_encoder")
651#endif
652 inline void strcat(
653 _Inout_ std::string& dst,
654 _In_ const std::wstring& src,
655 _In_ charset_id charset = charset_id::system)
656 {
657 strcat(dst, src.c_str(), src.size(), charset);
658 }
659
660 _Deprecated_("Use stdex::strcat")
661 inline void wstr2str(
662 _Inout_ std::string& dst,
663 _In_ const std::wstring& src,
664 _In_ charset_id charset = charset_id::system)
665 {
666 strcat(dst, src, charset);
667 }
668
679#ifndef _WIN32
680 _Deprecated_("For better performance, consider a reusable charset_encoder")
681#endif
682 inline void strcpy(
683 _Inout_ std::string& dst,
684 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
685 _In_ charset_id charset = charset_id::system)
686 {
687 dst.clear();
688 strcat(dst, src, count_src, charset);
689 }
690
700#ifndef _WIN32
701 _Deprecated_("For better performance, consider a reusable charset_encoder")
702#endif
703 inline void strcpy(
704 _Inout_ std::string& dst,
705 _In_ const std::wstring& src,
706 _In_ charset_id charset = charset_id::system)
707 {
708 strcpy(dst, src.data(), src.size(), charset);
709 }
710
721#ifndef _WIN32
722 _Deprecated_("For better performance, consider a reusable charset_encoder")
723#endif
724 inline std::string wstr2str(
725 _In_z_ const wchar_t* src,
726 _In_ charset_id charset = charset_id::system)
727 {
728 std::string dst;
729 strcat(dst, src, SIZE_MAX, charset);
730 return dst;
731 }
732
744#ifndef _WIN32
745 _Deprecated_("For better performance, consider a reusable charset_encoder")
746#endif
747 inline std::string wstr2str(
748 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
749 _In_ charset_id charset = charset_id::system)
750 {
751 std::string dst;
752 strcat(dst, src, count_src, charset);
753 return dst;
754 }
755
766#ifndef _WIN32
767 _Deprecated_("For better performance, consider a reusable charset_encoder")
768#endif
769 inline std::string wstr2str(
770 _In_ const std::wstring& src,
771 _In_ charset_id charset = charset_id::system)
772 {
773 return wstr2str(src.c_str(), src.size(), charset);
774 }
775}
776
777#ifndef _WIN32
778#pragma GCC diagnostic pop
779#endif
Encoding converter context.
Definition unicode.hpp:70
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:307
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:345
std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const T_from *src)
Return converted string.
Definition unicode.hpp:334
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:263
void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
Convert string.
Definition unicode.hpp:293
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:107
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:249
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:278
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:321