10#include "sgml_unicode.hpp"
17#pragma GCC diagnostic push
18#pragma GCC diagnostic ignored "-Wexit-time-destructors"
25 const utf32_t* sgml2uni(_In_reads_or_z_(count)
const T* entity, _In_
size_t count, utf32_t buf[2])
27 _Assume_(entity && count);
29 if (count < 2 || entity[0] !=
'#') {
30 for (
size_t i = 0, j = _countof(sgml_unicode); i < j; ) {
31 size_t m = (i + j) / 2;
32 if (sgml_unicode[m].sgml[0] < entity[0])
34 else if (sgml_unicode[m].sgml[0] > entity[0])
37 auto r = strncmp<char, T>(sgml_unicode[m].sgml + 1, _countof(sgml_unicode[0].sgml) - 1, entity + 1, count - 1);
43 for (; i < m && strncmp<char, T>(sgml_unicode[m - 1].sgml, _countof(sgml_unicode[0].sgml), entity, count) == 0; m--);
44 return reinterpret_cast<const utf32_t*
>(sgml_unicode[m].unicode);
51 buf[0] = entity[1] ==
'x' || entity[1] ==
'X' ?
52 static_cast<utf32_t
>(strtou32(&entity[2], count - 2,
nullptr, 16)) :
53 static_cast<utf32_t>(strtou32(&entity[1], count - 1, nullptr, 10));
58 inline const utf16_t* utf32_to_wstr(_In_opt_z_
const utf32_t* str, utf16_t* buf)
62 for (
size_t i = 0, j = 0;; ++i) {
68 buf[j++] =
static_cast<utf16_t
>(str[i]);
70 ucs4_to_surrogate_pair(&buf[j], str[i]);
76 inline const utf32_t* utf32_to_wstr(_In_opt_z_
const utf32_t* str, utf32_t* buf)
84 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
86 _Assume_(str || !count);
87 for (
size_t i = 0; i < count; i++) {
90 if (!str[i] || str[i] ==
'&' || isspace(str[i]))
97 constexpr int sgml_full = 0x40000000;
98 constexpr int sgml_quot = 0x00000001;
99 constexpr int sgml_apos = 0x00000002;
100 constexpr int sgml_quot_apos = sgml_quot | sgml_apos;
101 constexpr int sgml_amp = 0x00000004;
102 constexpr int sgml_lt_gt = 0x00000008;
103 constexpr int sgml_bsol = 0x00000010;
104 constexpr int sgml_dollar = 0x00000020;
105 constexpr int sgml_percnt = 0x00000040;
106 constexpr int sgml_commat = 0x00000080;
107 constexpr int sgml_num = 0x00000100;
108 constexpr int sgml_lpar_rpar = 0x00000200;
109 constexpr int sgml_lcub_rcub = 0x00000400;
110 constexpr int sgml_lsqb_rsqb = 0x00000800;
111 constexpr int sgml_sgml = sgml_amp | sgml_lt_gt;
112 constexpr int sgml_ml_attrib = sgml_amp | sgml_quot_apos;
113 constexpr int sgml_c = sgml_amp | sgml_bsol | sgml_quot_apos;
125 template <
class T_from>
127 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
130 _Assume_(src || !count_src);
133 do_ascii = (what & sgml_full) == 0;
135 for (
size_t i = 0; i < count_src && src[i];) {
137 auto end = sgmlend(&src[i + 1], count_src - i - 1);
140 size_t n = end - src - i - 1;
141 auto entity_w = sgml2uni(&src[i + 1], n, chr);
155 if (do_ascii && !is7bit(src[i])) {
173 template <
class T_from,
class TR_from = std::
char_traits<T_from>,
class AX_from = std::allocator<T_from>>
175 _In_
const std::basic_string<T_from, TR_from, AX_from>& src,
178 return sgmlerr(src.data(), src.size(), what);
191 template <
class T_to,
class T_from,
class TR_to = std::
char_traits<T_to>,
class AX_to = std::allocator<T_to>>
193 _Inout_ std::basic_string<T_to, TR_to, AX_to>& dst,
194 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
196 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
197 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
199 _Assume_(src || !count_src);
202 skip_quot = (skip & sgml_quot) == 0,
203 skip_apos = (skip & sgml_apos) == 0,
204 skip_amp = (skip & sgml_amp) == 0,
205 skip_lt_gt = (skip & sgml_lt_gt) == 0,
206 skip_bsol = (skip & sgml_bsol) == 0,
207 skip_dollar = (skip & sgml_dollar) == 0,
208 skip_percnt = (skip & sgml_percnt) == 0,
209 skip_commat = (skip & sgml_commat) == 0,
210 skip_num = (skip & sgml_num) == 0,
211 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
212 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
213 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
215 count_src = strnlen(src, count_src);
216 dst.reserve(dst.size() + count_src);
217 for (
size_t i = 0; i < count_src;) {
219 auto end = sgmlend(&src[i + 1], count_src - i - 1);
222 _Assume_(&src[i + 1] <= end);
223 size_t n =
static_cast<size_t>(end - src) - i - 1;
225 auto entity_w = utf32_to_wstr(sgml2uni(&src[i + 1], n, chr32), chr);
227 (skip_quot || (entity_w[0] !=
'"')) &&
228 (skip_apos || (entity_w[0] !=
'\'')) &&
229 (skip_amp || (entity_w[0] !=
'&')) &&
230 (skip_lt_gt || (entity_w[0] !=
'<' && entity_w[0] !=
'>')) &&
231 (skip_bsol || (entity_w[0] !=
'\\')) &&
232 (skip_dollar || (entity_w[0] !=
'$')) &&
233 (skip_percnt || (entity_w[0] !=
'%')) &&
234 (skip_commat || (entity_w[0] !=
'@')) &&
235 (skip_num || (entity_w[0] !=
'#')) &&
236 (skip_lpar_rpar || (entity_w[0] !=
'(' && entity_w[0] !=
')')) &&
237 (skip_lcub_rcub || (entity_w[0] !=
'{' && entity_w[0] !=
'}')) &&
238 (skip_lsqb_rsqb || (entity_w[0] !=
'[' && entity_w[0] !=
']')))
240 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
241 dst.append(entity_w);
242 _Assume_(src <= end);
243 i =
static_cast<size_t>(end - src) + 1;
244 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
249 dst.append(1, src[i++]);
262 template <
class T_to,
class T_from,
class TR_to = std::
char_traits<T_to>,
class AX_to = std::allocator<T_to>,
class TR_from = std::
char_traits<T_from>,
class AX_from = std::allocator<T_from>>
264 _Inout_ std::basic_string<T_to, TR_to, AX_to>& dst,
265 _In_
const std::basic_string<T_from, TR_from, AX_from>& src,
267 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
268 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
270 sgml2strcat(dst, src.data(), src.size(), skip, offset, map);
286 template <
class T_to,
class T_from>
288 _Inout_cap_(count_dst) T_to* dst, _In_
size_t count_dst,
289 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
291 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
292 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
294 _Assume_(dst || !count_dst);
295 _Assume_(src || !count_src);
297 static const std::invalid_argument buffer_overrun(
"buffer overrun");
299 skip_quot = (skip & sgml_quot) == 0,
300 skip_apos = (skip & sgml_apos) == 0,
301 skip_amp = (skip & sgml_amp) == 0,
302 skip_lt_gt = (skip & sgml_lt_gt) == 0,
303 skip_bsol = (skip & sgml_bsol) == 0,
304 skip_dollar = (skip & sgml_dollar) == 0,
305 skip_percnt = (skip & sgml_percnt) == 0,
306 skip_commat = (skip & sgml_commat) == 0,
307 skip_num = (skip & sgml_num) == 0,
308 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
309 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
310 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
312 size_t j = strnlen(dst, count_dst);
313 count_src = strnlen(src, count_src);
314 for (
size_t i = 0; i < count_src;) {
316 auto end = sgmlend(&src[i + 1], count_src - i - 1);
320 size_t n = end - src - i - 1;
321 auto entity_w = utf32_to_wstr(sgml2uni(&src[i + 1], n, chr32), chr);
323 (skip_quot || (entity_w[0] !=
'"')) &&
324 (skip_apos || (entity_w[0] !=
'\'')) &&
325 (skip_amp || (entity_w[0] !=
'&')) &&
326 (skip_lt_gt || (entity_w[0] !=
'<' && entity_w[0] !=
'>')) &&
327 (skip_bsol || (entity_w[0] !=
'\\')) &&
328 (skip_dollar || (entity_w[0] !=
'$')) &&
329 (skip_percnt || (entity_w[0] !=
'%')) &&
330 (skip_commat || (entity_w[0] !=
'@')) &&
331 (skip_num || (entity_w[0] !=
'#')) &&
332 (skip_lpar_rpar || (entity_w[0] !=
'(' && entity_w[0] !=
')')) &&
333 (skip_lcub_rcub || (entity_w[0] !=
'{' && entity_w[0] !=
'}')) &&
334 (skip_lsqb_rsqb || (entity_w[0] !=
'[' && entity_w[0] !=
']')))
336 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
337 size_t m = strlen(entity_w);
338 if (j + m >= count_dst)
339 throw buffer_overrun;
340 memcpy(dst + j, entity_w, m *
sizeof(*entity_w)); j += m;
342 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
347 if (j + 1 >= count_dst)
348 throw buffer_overrun;
352 throw buffer_overrun;
367 template <
class T_to,
class T_from,
class TR_to = std::
char_traits<T_to>,
class AX_to = std::allocator<T_to>>
369 _Inout_ std::basic_string<T_to, TR_to, AX_to>& dst,
370 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
372 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
373 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
378 sgml2strcat(dst, src, count_src, skip, offset, map);
390 template<
class T_to,
class T_from,
class TR_to = std::
char_traits<T_to>,
class AX_to = std::allocator<T_to>,
class TR_from = std::
char_traits<T_from>,
class AX_from = std::allocator<T_from>>
392 _Inout_ std::basic_string<T_to, TR_to, AX_to>& dst,
393 _In_
const std::basic_string<T_from, TR_from, AX_from>& src,
395 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
396 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
398 sgml2strcpy(dst, src.data(), src.size(), skip, offset, map);
414 template <
class T_to,
class T_from>
416 _Inout_cap_(count_dst) T_to* dst, _In_
size_t count_dst,
417 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
419 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
420 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
422 _Assume_(dst || !count_dst);
427 return sgml2strcat(dst, count_dst, src, count_src, skip, offset, map);
441 template <
class T_to =
wchar_t,
class T_from,
class TR_to = std::
char_traits<T_to>,
class AX_to = std::allocator<T_to>>
442 std::basic_string<T_to, TR_to, AX_to> sgml2str(
443 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
445 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
446 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
448 std::basic_string<T_to, TR_to, AX_to> dst;
449 sgml2strcat(dst, src, count_src, skip, offset, map);
463 template <
class T_to =
wchar_t,
class T_from,
class TR_to = std::
char_traits<T_to>,
class AX_to = std::allocator<T_to>,
class TR_from = std::
char_traits<T_from>,
class AX_from = std::allocator<T_from>>
464 std::basic_string<T_to, TR_to, AX_to> sgml2str(
465 _In_
const std::basic_string<T_from, TR_from, AX_from>& src,
467 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
468 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
470 return sgml2str<T_to, T_from, TR_to, AX_to>(src.data(), src.size(), skip, offset, map);
474 inline const char* chr2sgml(_In_reads_or_z_(count)
const utf16_t* entity, _In_
size_t count)
476 _Assume_(entity && count);
480 if (count < 2 || !is_surrogate_pair(entity)) {
481 e2 =
static_cast<utf32_t
>(entity[0]);
485 e2 = surrogate_pair_to_ucs4(entity);
488 for (
size_t i = 0, j = _countof(unicode_sgml); i < j; ) {
489 size_t m = (i + j) / 2;
490 auto e1 = sgml_unicode[unicode_sgml[m]].unicode[0];
496 auto r = strncmp(sgml_unicode[unicode_sgml[m]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + offset, count - offset);
502 for (; i < m && sgml_unicode[unicode_sgml[m - 1]].unicode[0] == e2 && strncmp(sgml_unicode[unicode_sgml[m - 1]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + offset, count - offset) == 0; m--);
503 return sgml_unicode[unicode_sgml[m]].sgml;
510 inline const char* chr2sgml(_In_reads_or_z_(count)
const utf32_t* entity, _In_
size_t count)
512 _Assume_(entity && count);
514 utf32_t e2 = entity[0];
515 for (
size_t i = 0, j = _countof(unicode_sgml); i < j; ) {
516 size_t m = (i + j) / 2;
517 auto e1 = sgml_unicode[unicode_sgml[m]].unicode[0];
523 auto r = strncmp(sgml_unicode[unicode_sgml[m]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1);
529 for (; i < m && sgml_unicode[unicode_sgml[m - 1]].unicode[0] == e2 && strncmp(sgml_unicode[unicode_sgml[m - 1]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1) == 0; m--);
530 return sgml_unicode[unicode_sgml[m]].sgml;
537 inline utf32_t wstr_to_utf32(_In_reads_(end)
const utf16_t* src, _Inout_
size_t& i, _In_
size_t end)
540 if (i + 1 >= end || !is_surrogate_pair(src + i))
543 utf32_t unicode = surrogate_pair_to_ucs4(src + i);
548 inline utf32_t wstr_to_utf32(_In_reads_(end)
const utf32_t* src, _Inout_
size_t& i, _In_
size_t end)
564 template <
class T_from,
class TR_to = std::
char_traits<
char>,
class AX_to = std::allocator<
char>>
566 _Inout_ std::basic_string<char, TR_to, AX_to>& dst,
567 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
570 _Assume_(src || !count_src);
573 do_ascii = (what & sgml_full) == 0,
574 do_quot = (what & sgml_quot) == 0,
575 do_apos = (what & sgml_apos) == 0,
576 do_lt_gt = (what & sgml_lt_gt) == 0,
577 do_bsol = (what & sgml_bsol) == 0,
578 do_dollar = (what & sgml_dollar) == 0,
579 do_percnt = (what & sgml_percnt) == 0,
580 do_commat = (what & sgml_commat) == 0,
581 do_num = (what & sgml_num) == 0,
582 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
583 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
584 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
586 count_src = strnlen(src, count_src);
587 dst.reserve(dst.size() + count_src);
588 for (
size_t i = 0; i < count_src;) {
589 size_t n = glyphlen(src + i, count_src - i);
591 do_ascii && is7bit(src[i]) &&
593 (do_quot || (src[i] !=
'"')) &&
594 (do_apos || (src[i] !=
'\'')) &&
595 (do_lt_gt || (src[i] !=
'<' && src[i] !=
'>')) &&
596 (do_bsol || (src[i] !=
'\\')) &&
597 (do_dollar || (src[i] !=
'$')) &&
598 (do_percnt || (src[i] !=
'%')) &&
599 (do_commat || (src[i] !=
'@')) &&
600 (do_num || (src[i] !=
'#')) &&
601 (do_lpar_rpar || (src[i] !=
'(' && src[i] !=
')')) &&
602 (do_lcub_rcub || (src[i] !=
'{' && src[i] !=
'}')) &&
603 (do_lsqb_rsqb || (src[i] !=
'[' && src[i] !=
']')))
606 dst.append(1,
static_cast<char>(src[i++]));
609 const char* entity = chr2sgml(src + i, n);
619 dst.append(1,
static_cast<char>(src[i++]));
621 char tmp[3 + 8 + 1 + 1];
622 snprintf(tmp, _countof(tmp),
"&#x%x;",
static_cast<unsigned int>(src[i++]));
628 const size_t end = i + n;
630 if ((entity = chr2sgml(src + i, 1)) !=
nullptr) {
636 else if (is7bit(src[i]))
637 dst.append(1,
static_cast<char>(src[i++]));
639 char tmp[3 + 8 + 1 + 1];
640 snprintf(tmp, _countof(tmp),
"&#x%x;",
static_cast<unsigned int>(wstr_to_utf32(src, i, end)));
656 template <
class T_from,
class TR_to = std::
char_traits<
char>,
class AX_to = std::allocator<
char>,
class TR_from = std::
char_traits<T_from>,
class AX_from = std::allocator<T_from>>
658 _Inout_ std::basic_string<char, TR_to, AX_to>& dst,
659 _In_
const std::basic_string<T_from, TR_from, AX_from>& src,
662 str2sgmlcat(dst, src.data(), src.size(), what);
676 template <
class T_from>
678 _Inout_cap_(count_dst)
char* dst, _In_
size_t count_dst,
679 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
682 _Assume_(dst || !count_dst);
683 _Assume_(src || !count_src);
685 static const std::invalid_argument buffer_overrun(
"buffer overrun");
687 do_ascii = (what & sgml_full) == 0,
688 do_quot = (what & sgml_quot) == 0,
689 do_apos = (what & sgml_apos) == 0,
690 do_lt_gt = (what & sgml_lt_gt) == 0,
691 do_bsol = (what & sgml_bsol) == 0,
692 do_dollar = (what & sgml_dollar) == 0,
693 do_percnt = (what & sgml_percnt) == 0,
694 do_commat = (what & sgml_commat) == 0,
695 do_num = (what & sgml_num) == 0,
696 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
697 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
698 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
700 size_t j = strnlen(dst, count_dst);
701 count_src = strnlen(src, count_src);
702 for (
size_t i = 0; i < count_src;) {
703 size_t n = glyphlen(src + i, count_src - i);
705 do_ascii && is7bit(src[i]) &&
707 (do_quot || (src[i] !=
'"')) &&
708 (do_apos || (src[i] !=
'\'')) &&
709 (do_lt_gt || (src[i] !=
'<' && src[i] !=
'>')) &&
710 (do_bsol || (src[i] !=
'\\')) &&
711 (do_dollar || (src[i] !=
'$')) &&
712 (do_percnt || (src[i] !=
'%')) &&
713 (do_commat || (src[i] !=
'@')) &&
714 (do_num || (src[i] !=
'#')) &&
715 (do_lpar_rpar || (src[i] !=
'(' && src[i] !=
')')) &&
716 (do_lcub_rcub || (src[i] !=
'{' && src[i] !=
'}')) &&
717 (do_lsqb_rsqb || (src[i] !=
'[' && src[i] !=
']')))
720 if (j + 1 >= count_dst)
721 throw buffer_overrun;
722 dst[j++] =
static_cast<char>(src[i++]);
725 const char* entity = chr2sgml(src + i, n);
727 size_t m = strlen(entity);
728 if (j + m + 2 >= count_dst)
729 throw buffer_overrun;
731 memcpy(dst + j, entity, m *
sizeof(
char)); j += m;
737 if (is7bit(src[i])) {
738 if (j + 1 >= count_dst)
739 throw buffer_overrun;
740 dst[j++] =
static_cast<char>(src[i++]);
743 char tmp[3 + 8 + 1 + 1];
744 int m = snprintf(tmp, _countof(tmp),
"&#x%x;",
static_cast<unsigned int>(src[i++]));
746 if (
static_cast<size_t>(m) >= count_dst)
747 throw buffer_overrun;
748 memcpy(dst + j, tmp,
static_cast<size_t>(m) *
sizeof(
char));
749 j +=
static_cast<size_t>(m);
754 const size_t end = i + n;
756 if ((entity = chr2sgml(src + i, 1)) !=
nullptr) {
757 size_t m = strlen(entity);
758 if (j + m + 2 >= count_dst)
759 throw buffer_overrun;
761 memcpy(dst + j, entity, m *
sizeof(
char)); j += m;
765 else if (is7bit(src[i])) {
766 if (j + 1 >= count_dst)
767 throw buffer_overrun;
768 dst[j++] =
static_cast<char>(src[i++]);
771 char tmp[3 + 8 + 1 + 1];
772 int m = snprintf(tmp, _countof(tmp),
"&#x%x;",
static_cast<unsigned int>(wstr_to_utf32(src, i, end)));
774 if (
static_cast<size_t>(m) >= count_dst)
775 throw buffer_overrun;
776 memcpy(dst + j, tmp,
static_cast<size_t>(m) *
sizeof(
char));
777 j +=
static_cast<size_t>(m);
784 throw buffer_overrun;
797 template <
class T_from,
class TR_to = std::
char_traits<
char>,
class AX_to = std::allocator<
char>>
799 _Inout_ std::basic_string<char, TR_to, AX_to>& dst,
800 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
804 str2sgmlcat(dst, src, count_src, what);
814 template <
class T_from,
class TR_to = std::
char_traits<
char>,
class AX_to = std::allocator<
char>,
class TR_from = std::
char_traits<T_from>,
class AX_from = std::allocator<T_from>>
816 _Inout_ std::basic_string<char, TR_to, AX_to>& dst,
817 _In_
const std::basic_string<T_from, TR_from, AX_from>& src,
820 str2sgmlcpy(dst, src.data(), src.size(), what);
834 template <
class T_from>
836 _Inout_cap_(count_dst)
char* dst, _In_
size_t count_dst,
837 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
840 _Assume_(dst || !count_dst);
843 return str2sgmlcat(dst, count_dst, src, count_src, what);
855 template <
class T_from>
856 std::string str2sgml(
857 _In_reads_or_z_opt_(count_src)
const T_from* src, _In_
size_t count_src,
861 str2sgmlcat(dst, src, count_src, what);
873 template <
class T_from,
class TR_from = std::
char_traits<T_from>,
class AX_from = std::allocator<T_from>>
874 std::string str2sgml(
875 _In_
const std::basic_string<T_from, TR_from, AX_from>& src,
878 return str2sgml(src.data(), src.size(), what);
883#pragma GCC diagnostic pop