stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
sgml.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023 Amebis
4*/
5
6#pragma once
7
8#include "compat.hpp"
9#include "mapping.hpp"
10#include "sgml_unicode.hpp"
11#include "string.hpp"
12#include <string.h>
13#include <exception>
14#include <string>
15
16namespace stdex
17{
19 template <class T>
20 inline const wchar_t* sgml2uni(_In_reads_or_z_(count) const T* entity, _In_ size_t count)
21 {
22 _Assume_(entity && count);
23 _Assume_(count < 2 || entity[0] != '#'); // No numeric entities
24
25 for (size_t i = 0, j = _countof(sgml_unicode); i < j; ) {
26 size_t m = (i + j) / 2;
27 if (sgml_unicode[m].sgml[0] < entity[0])
28 i = m + 1;
29 else if (sgml_unicode[m].sgml[0] > entity[0])
30 j = m;
31 else {
32 auto r = strncmp<char, T>(sgml_unicode[m].sgml + 1, _countof(sgml_unicode[0].sgml) - 1, entity + 1, count - 1);
33 if (r < 0)
34 i = m + 1;
35 else if (r > 0)
36 j = m;
37 else {
38 for (; i < m && strncmp<char, T>(sgml_unicode[m - 1].sgml, _countof(sgml_unicode[0].sgml), entity, count) == 0; m--);
39 return sgml_unicode[m].unicode;
40 }
41 }
42 }
43 return nullptr;
44 }
45
46 template <class T>
47 inline const T* sgmlend(
48 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
49 {
50 _Assume_(str || !count);
51 for (size_t i = 0; i < count; i++) {
52 if (str[i] == ';')
53 return str + i;
54 if (!str[i] || str[i] == '&' || isspace(str[i]))
55 break;
56 }
57 return nullptr;
58 }
60
61 constexpr int sgml_full = 0x80000000;
62 constexpr int sgml_quot = 0x00000001;
63 constexpr int sgml_apos = 0x00000002;
64 constexpr int sgml_quot_apos = sgml_quot | sgml_apos;
65 constexpr int sgml_amp = 0x00000004;
66 constexpr int sgml_lt_gt = 0x00000008;
67 constexpr int sgml_bsol = 0x00000010;
68 constexpr int sgml_dollar = 0x00000020;
69 constexpr int sgml_percnt = 0x00000040;
70 constexpr int sgml_commat = 0x00000080;
71 constexpr int sgml_num = 0x00000100;
72 constexpr int sgml_lpar_rpar = 0x00000200;
73 constexpr int sgml_lcub_rcub = 0x00000400;
74 constexpr int sgml_lsqb_rsqb = 0x00000800;
75 constexpr int sgml_sgml = sgml_amp | sgml_lt_gt;
76 constexpr int sgml_ml_attrib = sgml_amp | sgml_quot_apos;
77 constexpr int sgml_c = sgml_amp | sgml_bsol | sgml_quot_apos;
78 // constexpr int sgml_kolos = sgml_amp | sgml_quot | sgml_dollar | sgml_percnt | sgml_lt_gt | sgml_bsol/* | sgml_commat | sgml_num*/ | sgml_lpar_rpar | sgml_lcub_rcub | sgml_lsqb_rsqb;
79
90 template <class T>
91 inline void sgml2strcat(
92 _Inout_ std::wstring& dst,
93 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
94 _In_ int skip = 0,
95 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
96 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
97 {
98 _Assume_(src || !count_src);
99
100 const bool
101 skip_quot = (skip & sgml_quot) == 0,
102 skip_apos = (skip & sgml_apos) == 0,
103 skip_amp = (skip & sgml_amp) == 0,
104 skip_lt_gt = (skip & sgml_lt_gt) == 0,
105 skip_bsol = (skip & sgml_bsol) == 0,
106 skip_dollar = (skip & sgml_dollar) == 0,
107 skip_percnt = (skip & sgml_percnt) == 0,
108 skip_commat = (skip & sgml_commat) == 0,
109 skip_num = (skip & sgml_num) == 0,
110 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
111 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
112 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
113
114 count_src = strnlen(src, count_src);
115 dst.reserve(dst.size() + count_src);
116 for (size_t i = 0; i < count_src;) {
117 if (src[i] == '&') {
118 auto end = sgmlend(src + i + 1, count_src - i - 1);
119 if (end) {
120 const wchar_t* entity_w;
121 wchar_t chr[3];
122 size_t n = end - src - i - 1;
123 if (n >= 2 && src[i + 1] == '#') {
124 uint32_t unicode;
125 if (src[i + 2] == 'x' || src[i + 2] == 'X')
126 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
127 else
128 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
129#ifdef _WIN32
130 if (unicode < 0x10000) {
131 chr[0] = (wchar_t)unicode;
132 chr[1] = 0;
133 }
134 else {
135 ucs4_to_surrogate_pair(chr, unicode);
136 chr[2] = 0;
137 }
138#else
139 chr[0] = (wchar_t)unicode;
140 chr[1] = 0;
141#endif
142 entity_w = chr;
143 }
144 else
145 entity_w = sgml2uni(src + i + 1, n);
146
147 if (entity_w &&
148 (skip_quot || (entity_w[0] != L'"')) &&
149 (skip_apos || (entity_w[0] != L'\'')) &&
150 (skip_amp || (entity_w[0] != L'&')) &&
151 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
152 (skip_bsol || (entity_w[0] != L'\\')) &&
153 (skip_dollar || (entity_w[0] != L'$')) &&
154 (skip_percnt || (entity_w[0] != L'%')) &&
155 (skip_commat || (entity_w[0] != L'@')) &&
156 (skip_num || (entity_w[0] != L'#')) &&
157 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
158 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
159 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
160 {
161 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
162 dst.append(entity_w);
163 i = end - src + 1;
164 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
165 continue;
166 }
167 }
168 }
169 dst.append(1, src[i++]);
170 }
171 }
172
182 template <class T>
183 inline void sgml2strcat(
184 _Inout_ std::wstring& dst,
185 _In_ const std::basic_string<T>& src,
186 _In_ int skip = 0,
187 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
188 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
189 {
190 sgml2strcat(dst, src.data(), src.size(), skip, offset, map);
191 }
192
206 template <class T>
207 inline size_t sgml2strcat(
208 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
209 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
210 _In_ int skip = 0,
211 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
212 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
213 {
214 _Assume_(dst || !count_dst);
215 _Assume_(src || !count_src);
216
217 static const std::invalid_argument buffer_overrun("buffer overrun");
218 const bool
219 skip_quot = (skip & sgml_quot) == 0,
220 skip_apos = (skip & sgml_apos) == 0,
221 skip_amp = (skip & sgml_amp) == 0,
222 skip_lt_gt = (skip & sgml_lt_gt) == 0,
223 skip_bsol = (skip & sgml_bsol) == 0,
224 skip_dollar = (skip & sgml_dollar) == 0,
225 skip_percnt = (skip & sgml_percnt) == 0,
226 skip_commat = (skip & sgml_commat) == 0,
227 skip_num = (skip & sgml_num) == 0,
228 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
229 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
230 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
231
232 size_t j = wcsnlen(dst, count_dst);
233 count_src = strnlen(src, count_src);
234 for (size_t i = 0; i < count_src;) {
235 if (src[i] == '&') {
236 auto end = sgmlend(src + i + 1, count_src - i - 1);
237 if (end) {
238 const wchar_t* entity_w;
239 wchar_t chr[3];
240 size_t n = end - src - i - 1;
241 if (n >= 2 && src[i + 1] == '#') {
242 uint32_t unicode;
243 if (src[i + 2] == 'x' || src[i + 2] == 'X')
244 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
245 else
246 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
247#ifdef _WIN32
248 if (unicode < 0x10000) {
249 chr[0] = (wchar_t)unicode;
250 chr[1] = 0;
251 }
252 else {
253 ucs4_to_surrogate_pair(chr, unicode);
254 chr[2] = 0;
255 }
256#else
257 chr[0] = (wchar_t)unicode;
258 chr[1] = 0;
259#endif
260 entity_w = chr;
261 }
262 else
263 entity_w = sgml2uni(src + i + 1, n);
264
265 if (entity_w &&
266 (skip_quot || (entity_w[0] != L'"')) &&
267 (skip_apos || (entity_w[0] != L'\'')) &&
268 (skip_amp || (entity_w[0] != L'&')) &&
269 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
270 (skip_bsol || (entity_w[0] != L'\\')) &&
271 (skip_dollar || (entity_w[0] != L'$')) &&
272 (skip_percnt || (entity_w[0] != L'%')) &&
273 (skip_commat || (entity_w[0] != L'@')) &&
274 (skip_num || (entity_w[0] != L'#')) &&
275 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
276 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
277 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
278 {
279 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
280 size_t m = wcslen(entity_w);
281 if (j + m >= count_dst)
282 throw buffer_overrun;
283 memcpy(dst + j, entity_w, m * sizeof(wchar_t)); j += m;
284 i = end - src + 1;
285 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
286 continue;
287 }
288 }
289 }
290 if (j + 1 >= count_dst)
291 throw buffer_overrun;
292 dst[j++] = src[i++];
293 }
294 if (j >= count_dst)
295 throw buffer_overrun;
296 dst[j] = 0;
297 return j;
298 }
299
310 template <class T>
311 inline void sgml2strcpy(
312 _Inout_ std::wstring& dst,
313 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
314 _In_ int skip = 0,
315 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
316 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
317 {
318 dst.clear();
319 if (map)
320 map->clear();
321 sgml2strcat(dst, src, count_src, skip, offset, map);
322 }
323
333 template<class _Elem, class _Traits, class _Ax>
334 inline void sgml2strcpy(
335 _Inout_ std::wstring& dst,
336 _In_ const std::basic_string<_Elem, _Traits, _Ax>& src,
337 _In_ int skip = 0,
338 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
339 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
340 {
341 sgml2strcpy(dst, src.data(), src.size(), skip, offset, map);
342 }
343
357 template <class T>
358 inline size_t sgml2strcpy(
359 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
360 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
361 _In_ int skip = 0,
362 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
363 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
364 {
365 _Assume_(dst || !count_dst);
366 if (count_dst)
367 dst[0] = 0;
368 if (map)
369 map->clear();
370 return sgml2strcat(dst, count_dst, src, count_src, skip, offset, map);
371 }
372
384 template <class T>
385 inline std::wstring sgml2str(
386 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
387 _In_ int skip = 0,
388 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
389 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
390 {
391 std::wstring dst;
392 sgml2strcat(dst, src, count_src, skip, offset, map);
393 return dst;
394 }
395
406 template <class T>
407 inline std::wstring sgml2str(
408 _In_ const std::basic_string<T>& src,
409 _In_ int skip = 0,
410 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
411 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
412 {
413 return sgml2str(src.c_str(), src.size(), skip, offset, map);
414 }
415
417 inline const char* chr2sgml(_In_reads_or_z_(count) const wchar_t* entity, _In_ size_t count)
418 {
419 _Assume_(entity && count);
420
421 const wchar_t e2 = entity[0];
422 for (size_t i = 0, j = _countof(unicode_sgml); i < j; ) {
423 size_t m = (i + j) / 2;
424 wchar_t e1 = sgml_unicode[unicode_sgml[m]].unicode[0];
425 if (e1 < e2)
426 i = m + 1;
427 else if (e1 > e2)
428 j = m;
429 else {
430 auto r = strncmp(sgml_unicode[unicode_sgml[m]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1);
431 if (r < 0)
432 i = m + 1;
433 else if (r > 0)
434 j = m;
435 else {
436 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--);
437 return sgml_unicode[unicode_sgml[m]].sgml;
438 }
439 }
440 }
441 return nullptr;
442 }
444
453 inline void str2sgmlcat(
454 _Inout_ std::string& dst,
455 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
456 _In_ int what = 0)
457 {
458 _Assume_(src || !count_src);
459
460 const bool
461 do_ascii = (what & sgml_full) == 0,
462 do_quot = (what & sgml_quot) == 0,
463 do_apos = (what & sgml_apos) == 0,
464 do_lt_gt = (what & sgml_lt_gt) == 0,
465 do_bsol = (what & sgml_bsol) == 0,
466 do_dollar = (what & sgml_dollar) == 0,
467 do_percnt = (what & sgml_percnt) == 0,
468 do_commat = (what & sgml_commat) == 0,
469 do_num = (what & sgml_num) == 0,
470 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
471 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
472 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
473
474 count_src = wcsnlen(src, count_src);
475 dst.reserve(dst.size() + count_src);
476 for (size_t i = 0; i < count_src;) {
477 size_t n = glyphlen(src + i, count_src - i);
478 if (n == 1 &&
479 do_ascii && (unsigned int)src[i] < 128 &&
480 src[i] != L'&' &&
481 (do_quot || (src[i] != L'"')) &&
482 (do_apos || (src[i] != L'\'')) &&
483 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
484 (do_bsol || (src[i] != L'\\')) &&
485 (do_dollar || (src[i] != L'$')) &&
486 (do_percnt || (src[i] != L'%')) &&
487 (do_commat || (src[i] != L'@')) &&
488 (do_num || (src[i] != L'#')) &&
489 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
490 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
491 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
492 {
493 // 7-bit ASCII and no desire to encode it as an SGML entity.
494 dst.append(1, static_cast<char>(src[i++]));
495 }
496 else {
497 const char* entity = chr2sgml(src + i, n);
498 if (entity) {
499 dst.append(1, '&');
500 dst.append(entity);
501 dst.append(1, ';');
502 i += n;
503 }
504 else if (n == 1) {
505 // Trivial character (1 code unit, 1 glyph), no entity available.
506 if ((unsigned int)src[i] < 128)
507 dst.append(1, static_cast<char>(src[i++]));
508 else {
509 char tmp[3 + 8 + 1 + 1];
510 snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
511 dst.append(tmp);
512 }
513 }
514 else {
515 // Non-trivial character. Decompose.
516 const size_t end = i + n;
517 while (i < end) {
518 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
519 dst.append(1, '&');
520 dst.append(entity);
521 dst.append(1, ';');
522 i++;
523 }
524 else if ((unsigned int)src[i] < 128)
525 dst.append(1, static_cast<char>(src[i++]));
526 else {
527 uint32_t unicode;
528#ifdef _WIN32
529 if (i + 1 < end && is_surrogate_pair(src + i)) {
530 unicode = surrogate_pair_to_ucs4(src + i);
531 i += 2;
532 }
533 else
534#endif
535 {
536 unicode = src[i++];
537 }
538 char tmp[3 + 8 + 1 + 1];
539 snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
540 dst.append(tmp);
541 }
542 }
543 }
544 }
545 }
546 }
547
555 inline void str2sgmlcat(
556 _Inout_ std::string& dst,
557 _In_ const std::wstring& src,
558 _In_ int what = 0)
559 {
560 str2sgmlcat(dst, src.c_str(), src.size(), what);
561 }
562
574 inline size_t str2sgmlcat(
575 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
576 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
577 _In_ int what = 0)
578 {
579 _Assume_(dst || !count_dst);
580 _Assume_(src || !count_src);
581
582 static const std::invalid_argument buffer_overrun("buffer overrun");
583 const bool
584 do_ascii = (what & sgml_full) == 0,
585 do_quot = (what & sgml_quot) == 0,
586 do_apos = (what & sgml_apos) == 0,
587 do_lt_gt = (what & sgml_lt_gt) == 0,
588 do_bsol = (what & sgml_bsol) == 0,
589 do_dollar = (what & sgml_dollar) == 0,
590 do_percnt = (what & sgml_percnt) == 0,
591 do_commat = (what & sgml_commat) == 0,
592 do_num = (what & sgml_num) == 0,
593 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
594 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
595 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
596
597 size_t j = strnlen(dst, count_dst);
598 count_src = wcsnlen(src, count_src);
599 for (size_t i = 0; i < count_src;) {
600 size_t n = glyphlen(src + i, count_src - i);
601 if (n == 1 &&
602 do_ascii && (unsigned int)src[i] < 128 &&
603 src[i] != L'&' &&
604 (do_quot || (src[i] != L'"')) &&
605 (do_apos || (src[i] != L'\'')) &&
606 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
607 (do_bsol || (src[i] != L'\\')) &&
608 (do_dollar || (src[i] != L'$')) &&
609 (do_percnt || (src[i] != L'%')) &&
610 (do_commat || (src[i] != L'@')) &&
611 (do_num || (src[i] != L'#')) &&
612 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
613 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
614 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
615 {
616 // 7-bit ASCII and no desire to encode it as an SGML entity.
617 if (j + 1 >= count_dst)
618 throw buffer_overrun;
619 dst[j++] = static_cast<char>(src[i++]);
620 }
621 else {
622 const char* entity = chr2sgml(src + i, n);
623 if (entity) {
624 size_t m = strlen(entity);
625 if (j + m + 2 >= count_dst)
626 throw buffer_overrun;
627 dst[j++] = '&';
628 memcpy(dst + j, entity, m * sizeof(char)); j += m;
629 dst[j++] = ';';
630 i += n;
631 }
632 else if (n == 1) {
633 // Trivial character (1 code unit, 1 glyph), no entity available.
634 if ((unsigned int)src[i] < 128) {
635 if (j + 1 >= count_dst)
636 throw buffer_overrun;
637 dst[j++] = static_cast<char>(src[i++]);
638 }
639 else {
640 char tmp[3 + 8 + 1 + 1];
641 int m = snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
642 _Assume_(m >= 0);
643 if (static_cast<size_t>(m) >= count_dst)
644 throw buffer_overrun;
645 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
646 }
647 }
648 else {
649 // Non-trivial character. Decompose.
650 const size_t end = i + n;
651 while (i < end) {
652 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
653 size_t m = strlen(entity);
654 if (j + m + 2 >= count_dst)
655 throw buffer_overrun;
656 dst[j++] = '&';
657 memcpy(dst + j, entity, m * sizeof(char)); j += m;
658 dst[j++] = ';';
659 i++;
660 }
661 else if ((unsigned int)src[i] < 128) {
662 if (j + 1 >= count_dst)
663 throw buffer_overrun;
664 dst[j++] = static_cast<char>(src[i++]);
665 }
666 else {
667 uint32_t unicode;
668#ifdef _WIN32
669 if (i + 1 < end && is_surrogate_pair(src + i)) {
670 unicode = surrogate_pair_to_ucs4(src + i);
671 i += 2;
672 }
673 else
674#endif
675 {
676 unicode = src[i++];
677 }
678 char tmp[3 + 8 + 1 + 1];
679 int m = snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
680 _Assume_(m >= 0);
681 if (static_cast<size_t>(m) >= count_dst)
682 throw buffer_overrun;
683 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
684 }
685 }
686 }
687 }
688 }
689 if (j >= count_dst)
690 throw buffer_overrun;
691 dst[j] = 0;
692 return j;
693 }
694
703 inline void str2sgmlcpy(
704 _Inout_ std::string& dst,
705 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
706 _In_ int what = 0)
707 {
708 dst.clear();
709 str2sgmlcat(dst, src, count_src, what);
710 }
711
719 inline void str2sgmlcpy(
720 _Inout_ std::string& dst,
721 _In_ const std::wstring& src,
722 _In_ int what = 0)
723 {
724 str2sgmlcpy(dst, src.data(), src.size(), what);
725 }
726
738 inline size_t str2sgmlcpy(
739 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
740 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
741 _In_ int what = 0)
742 {
743 _Assume_(dst || !count_dst);
744 if (count_dst)
745 dst[0] = 0;
746 return str2sgmlcat(dst, count_dst, src, count_src, what);
747 }
748
758 inline std::string str2sgml(
759 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
760 _In_ int what = 0)
761 {
762 std::string dst;
763 str2sgmlcat(dst, src, count_src, what);
764 return dst;
765 }
766
775 inline std::string str2sgml(
776 _In_ const std::wstring& src,
777 _In_ int what = 0)
778 {
779 return str2sgml(src.c_str(), src.size(), what);
780 }
781}