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 "system.hpp"
12#include <assert.h>
13#include <stdint.h>
14#ifndef _WIN32
15#include <iconv.h>
16#include <langinfo.h>
17#endif
18#include <memory>
19#include <string>
20
21namespace stdex
22{
23 enum class charset_id : uint16_t {
24#ifdef _WIN32
25 system = CP_ACP,
26 oem = CP_OEMCP,
27 utf8 = CP_UTF8,
28 utf16 = 1200 /*CP_WINUNICODE*/,
29 utf32 = 12000,
30 windows1250 = 1250,
31 windows1251 = 1251,
32 windows1252 = 1252,
33#else
34 system = 0,
35 utf8,
36 utf16,
37 utf32,
38 windows1250,
39 windows1251,
40 windows1252,
41
42 _max
43#endif
44 };
45
46#ifdef _WIN32
47 constexpr charset_id wchar_t_charset = charset_id::utf16;
48#else
49 constexpr charset_id wchar_t_charset = charset_id::utf32;
50#endif
51
55 template <typename T_from, typename T_to>
57 {
58 protected:
59 charset_id m_from, m_to;
60
61 public:
62 charset_encoder(_In_ charset_id from, _In_ charset_id to) :
63 m_from(from),
64 m_to(to)
65 {
66#ifdef _WIN32
67 m_from_wincp = to_encoding(from);
68 m_to_wincp = to_encoding(to);
69#else
70 m_handle = iconv_open(to_encoding(to), to_encoding(from));
71 if (m_handle == (iconv_t)-1)
72 throw std::runtime_error("iconv_open failed");
73#endif
74 }
75
76#ifndef _WIN32
78 {
79 iconv_close(m_handle);
80 }
81#endif
82
83 inline charset_id from_encoding() const { return m_from; }
84 inline charset_id to_encoding() const { return m_to; }
85
93 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
94 void strcat(
95 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to> &dst,
96 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
97 {
98 assert(src || !count_src);
99 count_src = stdex::strnlen(src, count_src);
100 if (!count_src) _Unlikely_
101 return;
102
103#ifdef _WIN32
104 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
105 constexpr DWORD dwFlagsWCMB = 0;
106 constexpr LPCCH lpDefaultChar = NULL;
107
108 _Analysis_assume_(src);
109 if (m_from_wincp == m_to_wincp) _Unlikely_{
110 dst.append(reinterpret_cast<const T_to*>(src), count_src);
111 return;
112 }
113
114 if _Constexpr_ (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(wchar_t)) {
115 assert(count_src < INT_MAX || count_src == SIZE_MAX);
116
117 // Try to convert to stack buffer first.
118 WCHAR szStackBuffer[1024 / sizeof(WCHAR)];
119#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
120 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
121 if (cch) {
122 // Append from stack.
123 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
124 return;
125 }
126 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
127 // Query the required output size. Allocate buffer. Then convert again.
128 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
129 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
130 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBuffer.get(), cch);
131 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
132 return;
133 }
134 throw std::runtime_error("MultiByteToWideChar failed");
135 }
136
137 if _Constexpr_ (sizeof(T_from) == sizeof(wchar_t) && sizeof(T_to) == sizeof(char)) {
138 assert(count_src < INT_MAX || count_src == SIZE_MAX);
139
140 // Try to convert to stack buffer first.
141 CHAR szStackBuffer[1024 / sizeof(CHAR)];
142#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpWideCharStr parameter wrong?
143 int cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
144 if (cch) {
145 // Copy from stack. Be careful not to include zero terminator.
146 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
147 return;
148 }
149 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
150 // Query the required output size. Allocate buffer. Then convert again.
151 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
152 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
153 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
154 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
155 return;
156 }
157 throw std::runtime_error("WideCharToMultiByte failed");
158 }
159
160 if _Constexpr_ (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(char)) {
161 assert(count_src < INT_MAX || count_src == SIZE_MAX);
162
163 // Try to convert to stack buffer first.
164 WCHAR szStackBufferMBWC[512 / sizeof(WCHAR)];
165#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
166 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
167 if (cch) {
168 // Append from stack.
169 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) : static_cast<size_t>(cch) - 1;
170 assert(count_inter < INT_MAX);
171
172 // Try to convert to stack buffer first.
173 CHAR szStackBufferWCMB[512 / sizeof(CHAR)];
174#pragma warning(suppress: 6387) // Testing indicates szStackBufferMBWC may be NULL when count_inter is also 0. Is SAL of the lpWideCharStr parameter wrong?
175 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
176 if (cch) {
177 // Copy from stack. Be careful not to include zero terminator.
178 dst.append(reinterpret_cast<const T_to*>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
179 return;
180 }
181 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
182 // Query the required output size. Allocate buffer. Then convert again.
183 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
184 std::unique_ptr<CHAR[]> szBufferWCMB(new CHAR[cch]);
185 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
186 dst.append(reinterpret_cast<const T_to*>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
187 return;
188 }
189 throw std::runtime_error("WideCharToMultiByte failed");
190 }
191 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
192 // Query the required output size. Allocate buffer. Then convert again.
193 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
194 std::unique_ptr<WCHAR[]> szBufferMBWC(new WCHAR[cch]);
195 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBufferMBWC.get(), cch);
196 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) : static_cast<size_t>(cch) - 1;
197
198 // Query the required output size. Allocate buffer. Then convert again.
199 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(), 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, szBufferMBWC.get(), 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::runtime_error("MultiByteToWideChar failed");
206 }
207#else
208 dst.reserve(dst.size() + count_src);
209 T_to buf[1024 / sizeof(T_to)];
210 size_t src_size = stdex::mul(sizeof(T_from), count_src);
211 for (;;) {
212 T_to* output = &buf[0];
213 size_t output_size = sizeof(buf);
214 errno = 0;
215 iconv(m_handle, const_cast<char**>(reinterpret_cast<const char**>(&src)), &src_size, reinterpret_cast<char**>(&output), &output_size);
216 dst.append(buf, reinterpret_cast<T_to*>(reinterpret_cast<char*>(buf) + sizeof(buf) - output_size));
217 if (!errno)
218 break;
219 if (errno == E2BIG)
220 continue;
221 throw std::runtime_error("iconv failed");
222 }
223#endif
224 }
225
232 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
233 inline void strcat(
234 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
235 _In_z_ const T_from* src)
236 {
237 strcat(dst, src, SIZE_MAX);
238 }
239
246 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>>
247 inline void strcat(
248 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
249 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
250 {
251 strcat(dst, src.data(), src.size());
252 }
253
261 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
262 inline void strcpy(
263 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
264 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
265 {
266 dst.clear();
267 strcat(dst, src, count_src);
268 }
269
276 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
277 inline void strcpy(
278 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
279 _In_z_ const T_from* src)
280 {
281 strcpy(dst, src, SIZE_MAX);
282 }
283
290 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>>
291 inline void strcpy(
292 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
293 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
294 {
295 strcpy(dst, src.data(), src.size());
296 }
297
304 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
305 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)
306 {
307 std::basic_string<T_to, _Traits_to, _Alloc_to> dst;
308 strcat(dst, src, count_src);
309 return dst;
310 }
311
317 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
318 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_z_ const T_from* src)
319 {
320 return convert(src, SIZE_MAX);
321 }
322
328 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>>
329 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
330 {
331 return convert(src.data(), src.size());
332 }
333
334 inline void clear()
335 {
336#ifndef _WIN32
337 iconv(m_handle, NULL, NULL, NULL, NULL);
338#endif
339 }
340
341 static charset_id system_charset()
342 {
343#ifdef _WIN32
344 return static_cast<charset_id>(GetACP());
345#else
346 const char* lctype = nl_langinfo(CODESET);
347 if (strcmp(lctype, "UTF-8") == 0) return charset_id::utf8;
348 if (strcmp(lctype, "UTF-16") == 0) return charset_id::utf16;
349#if BYTE_ORDER == BIG_ENDIAN
350 if (strcmp(lctype, "UTF-16BE") == 0) return charset_id::utf16;
351#else
352 if (strcmp(lctype, "UTF-16LE") == 0) return charset_id::utf16;
353#endif
354 if (strcmp(lctype, "UTF-32") == 0) return charset_id::utf32;
355#if BYTE_ORDER == BIG_ENDIAN
356 if (strcmp(lctype, "UTF-32BE") == 0) return charset_id::utf32;
357#else
358 if (strcmp(lctype, "UTF-32LE") == 0) return charset_id::utf32;
359#endif
360 if (strcmp(lctype, "CP1250") == 0) return charset_id::windows1250;
361 if (strcmp(lctype, "CP1251") == 0) return charset_id::windows1251;
362 if (strcmp(lctype, "CP1252") == 0) return charset_id::windows1252;
363 return charset_id::system;
364#endif
365 }
366
367#ifdef _WIN32
368 protected:
369 static UINT to_encoding(_In_ charset_id charset)
370 {
371 return
372 charset == charset_id::system ? GetACP() :
373 charset == charset_id::oem ? GetOEMCP() :
374 static_cast<UINT>(charset);
375 }
376
377 protected:
378 UINT m_from_wincp, m_to_wincp;
379#else
380 protected:
381 static const char* to_encoding(_In_ charset_id charset)
382 {
383 static const char* const encodings[static_cast<std::underlying_type_t<charset_id>>(charset_id::_max)] = {
384 "", // system
385 "UTF-8", // utf8
386#if BYTE_ORDER == BIG_ENDIAN
387 "UTF-16BE", // utf16
388 "UTF-32BE", // utf32
389#else
390 "UTF-16LE", // utf16
391 "UTF-32LE", // utf32
392#endif
393 "CP1250", // windows1250
394 "CP1251", // windows1251
395 "CP1252", // windows1252
396 };
397 return
398 charset == charset_id::system ? nl_langinfo(CODESET) :
399 encodings[static_cast<std::underlying_type_t<charset_id>>(charset)];
400 }
401
402 protected:
403 iconv_t m_handle;
404#endif
405 };
406
417#ifndef _WIN32
418 _Deprecated_("For better performance, consider a reusable charset_encoder")
419#endif
420 inline void strcat(
421 _Inout_ std::wstring& dst,
422 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
423 _In_ charset_id charset = charset_id::system)
424 {
425 charset_encoder<char, wchar_t>(charset, wchar_t_charset).strcat(dst, src, count_src);
426 }
427
428 _Deprecated_("Use stdex::strcat")
429 inline void str2wstr(
430 _Inout_ std::wstring& dst,
431 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
432 _In_ charset_id charset = charset_id::system)
433 {
434 strcat(dst, src, count_src, charset);
435 }
436
446#ifndef _WIN32
447 _Deprecated_("For better performance, consider a reusable charset_encoder")
448#endif
449 inline void strcat(
450 _Inout_ std::wstring& dst,
451 _In_ const std::string& src,
452 _In_ charset_id charset = charset_id::system)
453 {
454 strcat(dst, src.data(), src.size(), charset);
455 }
456
457 _Deprecated_("Use stdex::strcat")
458 inline void str2wstr(
459 _Inout_ std::wstring& dst,
460 _In_ const std::string& src,
461 _In_ charset_id charset = charset_id::system)
462 {
463 strcat(dst, src, charset);
464 }
465
476#ifndef _WIN32
477 _Deprecated_("For better performance, consider a reusable charset_encoder")
478#endif
479 inline void strcpy(
480 _Inout_ std::wstring& dst,
481 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
482 _In_ charset_id charset = charset_id::system)
483 {
484 dst.clear();
485 strcat(dst, src, count_src, charset);
486 }
487
497#ifndef _WIN32
498 _Deprecated_("For better performance, consider a reusable charset_encoder")
499#endif
500 inline void strcpy(
501 _Inout_ std::wstring& dst,
502 _In_ const std::string& src,
503 _In_ charset_id charset = charset_id::system)
504 {
505 strcpy(dst, src.data(), src.size(), charset);
506 }
507
518#ifndef _WIN32
519 _Deprecated_("For better performance, consider a reusable charset_encoder")
520#endif
521 inline std::wstring str2wstr(
522 _In_z_ const char* src,
523 _In_ charset_id charset = charset_id::system)
524 {
525 std::wstring dst;
526 strcat(dst, src, SIZE_MAX, charset);
527 return dst;
528 }
529
541#ifndef _WIN32
542 _Deprecated_("For better performance, consider a reusable charset_encoder")
543#endif
544 inline std::wstring str2wstr(
545 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
546 _In_ charset_id charset = charset_id::system)
547 {
548 std::wstring dst;
549 strcat(dst, src, count_src, charset);
550 return dst;
551 }
552
563#ifndef _WIN32
564 _Deprecated_("For better performance, consider a reusable charset_encoder")
565#endif
566 inline std::wstring str2wstr(
567 _In_ const std::string& src,
568 _In_ charset_id charset = charset_id::system)
569 {
570 return str2wstr(src.c_str(), src.size(), charset);
571 }
572
583#ifndef _WIN32
584 _Deprecated_("For better performance, consider a reusable charset_encoder")
585#endif
586 inline void strcat(
587 _Inout_ std::string& dst,
588 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
589 _In_ charset_id charset = charset_id::system)
590 {
591 charset_encoder<wchar_t, char>(wchar_t_charset, charset).strcat(dst, src, count_src);
592 }
593
594 _Deprecated_("Use stdex::strcat")
595 inline void wstr2str(
596 _Inout_ std::string& dst,
597 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
598 _In_ charset_id charset = charset_id::system)
599 {
600 strcat(dst, src, count_src, charset);
601 }
602
612#ifndef _WIN32
613 _Deprecated_("For better performance, consider a reusable charset_encoder")
614#endif
615 inline void strcat(
616 _Inout_ std::string& dst,
617 _In_ const std::wstring& src,
618 _In_ charset_id charset = charset_id::system)
619 {
620 strcat(dst, src.c_str(), src.size(), charset);
621 }
622
623 _Deprecated_("Use stdex::strcat")
624 inline void wstr2str(
625 _Inout_ std::string& dst,
626 _In_ const std::wstring& src,
627 _In_ charset_id charset = charset_id::system)
628 {
629 strcat(dst, src, charset);
630 }
631
642#ifndef _WIN32
643 _Deprecated_("For better performance, consider a reusable charset_encoder")
644#endif
645 inline void strcpy(
646 _Inout_ std::string& dst,
647 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
648 _In_ charset_id charset = charset_id::system)
649 {
650 dst.clear();
651 strcat(dst, src, count_src, charset);
652 }
653
663#ifndef _WIN32
664 _Deprecated_("For better performance, consider a reusable charset_encoder")
665#endif
666 inline void strcpy(
667 _Inout_ std::string& dst,
668 _In_ const std::wstring& src,
669 _In_ charset_id charset = charset_id::system)
670 {
671 strcpy(dst, src.data(), src.size(), charset);
672 }
673
684#ifndef _WIN32
685 _Deprecated_("For better performance, consider a reusable charset_encoder")
686#endif
687 inline std::string wstr2str(
688 _In_z_ const wchar_t* src,
689 _In_ charset_id charset = charset_id::system)
690 {
691 std::string dst;
692 strcat(dst, src, SIZE_MAX, charset);
693 return dst;
694 }
695
707#ifndef _WIN32
708 _Deprecated_("For better performance, consider a reusable charset_encoder")
709#endif
710 inline std::string wstr2str(
711 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
712 _In_ charset_id charset = charset_id::system)
713 {
714 std::string dst;
715 strcat(dst, src, count_src, charset);
716 return dst;
717 }
718
729#ifndef _WIN32
730 _Deprecated_("For better performance, consider a reusable charset_encoder")
731#endif
732 inline std::string wstr2str(
733 _In_ const std::wstring& src,
734 _In_ charset_id charset = charset_id::system)
735 {
736 return wstr2str(src.c_str(), src.size(), charset);
737 }
738}
Encoding converter context.
Definition unicode.hpp:57
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:291
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:329
std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const T_from *src)
Return converted string.
Definition unicode.hpp:318
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:247
void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
Convert string.
Definition unicode.hpp:277
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:94
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:233
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:262
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:305