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_ajt_lemma = sgml_amp | sgml_quot | sgml_dollar | sgml_percnt;
79 // constexpr int sgml_ajt_form = sgml_ajt_lemma;
80 // 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;
81
92 template <class T>
93 inline void sgml2strcat(
94 _Inout_ std::wstring& dst,
95 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
96 _In_ int skip = 0,
97 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
98 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
99 {
100 _Assume_(src || !count_src);
101
102 const bool
103 skip_quot = (skip & sgml_quot) == 0,
104 skip_apos = (skip & sgml_apos) == 0,
105 skip_amp = (skip & sgml_amp) == 0,
106 skip_lt_gt = (skip & sgml_lt_gt) == 0,
107 skip_bsol = (skip & sgml_bsol) == 0,
108 skip_dollar = (skip & sgml_dollar) == 0,
109 skip_percnt = (skip & sgml_percnt) == 0,
110 skip_commat = (skip & sgml_commat) == 0,
111 skip_num = (skip & sgml_num) == 0,
112 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
113 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
114 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
115
116 count_src = strnlen(src, count_src);
117 dst.reserve(dst.size() + count_src);
118 for (size_t i = 0; i < count_src;) {
119 if (src[i] == '&') {
120 auto end = sgmlend(src + i + 1, count_src - i - 1);
121 if (end) {
122 const wchar_t* entity_w;
123 wchar_t chr[3];
124 size_t n = end - src - i - 1;
125 if (n >= 2 && src[i + 1] == '#') {
126 uint32_t unicode;
127 if (src[i + 2] == 'x' || src[i + 2] == 'X')
128 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
129 else
130 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
131#ifdef _WIN32
132 if (unicode < 0x10000) {
133 chr[0] = (wchar_t)unicode;
134 chr[1] = 0;
135 }
136 else {
137 ucs4_to_surrogate_pair(chr, unicode);
138 chr[2] = 0;
139 }
140#else
141 chr[0] = (wchar_t)unicode;
142 chr[1] = 0;
143#endif
144 entity_w = chr;
145 }
146 else
147 entity_w = sgml2uni(src + i + 1, n);
148
149 if (entity_w &&
150 (skip_quot || (entity_w[0] != L'"')) &&
151 (skip_apos || (entity_w[0] != L'\'')) &&
152 (skip_amp || (entity_w[0] != L'&')) &&
153 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
154 (skip_bsol || (entity_w[0] != L'\\')) &&
155 (skip_dollar || (entity_w[0] != L'$')) &&
156 (skip_percnt || (entity_w[0] != L'%')) &&
157 (skip_commat || (entity_w[0] != L'@')) &&
158 (skip_num || (entity_w[0] != L'#')) &&
159 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
160 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
161 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
162 {
163 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
164 dst.append(entity_w);
165 i = end - src + 1;
166 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
167 continue;
168 }
169 }
170 }
171 dst.append(1, src[i++]);
172 }
173 }
174
184 template <class T>
185 inline void sgml2strcat(
186 _Inout_ std::wstring& dst,
187 _In_ const std::basic_string<T>& src,
188 _In_ int skip = 0,
189 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
190 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
191 {
192 sgml2strcat(dst, src.data(), src.size(), skip, offset, map);
193 }
194
208 template <class T>
209 inline size_t sgml2strcat(
210 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
211 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
212 _In_ int skip = 0,
213 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
214 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
215 {
216 _Assume_(dst || !count_dst);
217 _Assume_(src || !count_src);
218
219 static const std::invalid_argument buffer_overrun("buffer overrun");
220 const bool
221 skip_quot = (skip & sgml_quot) == 0,
222 skip_apos = (skip & sgml_apos) == 0,
223 skip_amp = (skip & sgml_amp) == 0,
224 skip_lt_gt = (skip & sgml_lt_gt) == 0,
225 skip_bsol = (skip & sgml_bsol) == 0,
226 skip_dollar = (skip & sgml_dollar) == 0,
227 skip_percnt = (skip & sgml_percnt) == 0,
228 skip_commat = (skip & sgml_commat) == 0,
229 skip_num = (skip & sgml_num) == 0,
230 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
231 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
232 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
233
234 size_t j = wcsnlen(dst, count_dst);
235 count_src = strnlen(src, count_src);
236 for (size_t i = 0; i < count_src;) {
237 if (src[i] == '&') {
238 auto end = sgmlend(src + i + 1, count_src - i - 1);
239 if (end) {
240 const wchar_t* entity_w;
241 wchar_t chr[3];
242 size_t n = end - src - i - 1;
243 if (n >= 2 && src[i + 1] == '#') {
244 uint32_t unicode;
245 if (src[i + 2] == 'x' || src[i + 2] == 'X')
246 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
247 else
248 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
249#ifdef _WIN32
250 if (unicode < 0x10000) {
251 chr[0] = (wchar_t)unicode;
252 chr[1] = 0;
253 }
254 else {
255 ucs4_to_surrogate_pair(chr, unicode);
256 chr[2] = 0;
257 }
258#else
259 chr[0] = (wchar_t)unicode;
260 chr[1] = 0;
261#endif
262 entity_w = chr;
263 }
264 else
265 entity_w = sgml2uni(src + i + 1, n);
266
267 if (entity_w &&
268 (skip_quot || (entity_w[0] != L'"')) &&
269 (skip_apos || (entity_w[0] != L'\'')) &&
270 (skip_amp || (entity_w[0] != L'&')) &&
271 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
272 (skip_bsol || (entity_w[0] != L'\\')) &&
273 (skip_dollar || (entity_w[0] != L'$')) &&
274 (skip_percnt || (entity_w[0] != L'%')) &&
275 (skip_commat || (entity_w[0] != L'@')) &&
276 (skip_num || (entity_w[0] != L'#')) &&
277 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
278 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
279 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
280 {
281 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
282 size_t m = wcslen(entity_w);
283 if (j + m >= count_dst)
284 throw buffer_overrun;
285 memcpy(dst + j, entity_w, m * sizeof(wchar_t)); j += m;
286 i = end - src + 1;
287 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
288 continue;
289 }
290 }
291 }
292 if (j + 1 >= count_dst)
293 throw buffer_overrun;
294 dst[j++] = src[i++];
295 }
296 if (j >= count_dst)
297 throw buffer_overrun;
298 dst[j] = 0;
299 return j;
300 }
301
312 template <class T>
313 inline void sgml2strcpy(
314 _Inout_ std::wstring& dst,
315 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
316 _In_ int skip = 0,
317 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
318 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
319 {
320 dst.clear();
321 if (map)
322 map->clear();
323 sgml2strcat(dst, src, count_src, skip, offset, map);
324 }
325
335 template<class _Elem, class _Traits, class _Ax>
336 inline void sgml2strcpy(
337 _Inout_ std::wstring& dst,
338 _In_ const std::basic_string<_Elem, _Traits, _Ax>& src,
339 _In_ int skip = 0,
340 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
341 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
342 {
343 sgml2strcpy(dst, src.data(), src.size(), skip, offset, map);
344 }
345
359 template <class T>
360 inline size_t sgml2strcpy(
361 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
362 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
363 _In_ int skip = 0,
364 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
365 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
366 {
367 _Assume_(dst || !count_dst);
368 if (count_dst)
369 dst[0] = 0;
370 if (map)
371 map->clear();
372 return sgml2strcat(dst, count_dst, src, count_src, skip, offset, map);
373 }
374
386 template <class T>
387 inline std::wstring sgml2str(
388 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
389 _In_ int skip = 0,
390 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
391 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
392 {
393 std::wstring dst;
394 sgml2strcat(dst, src, count_src, skip, offset, map);
395 return dst;
396 }
397
408 template <class T>
409 inline std::wstring sgml2str(
410 _In_ const std::basic_string<T>& src,
411 _In_ int skip = 0,
412 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
413 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
414 {
415 return sgml2str(src.c_str(), src.size(), skip, offset, map);
416 }
417
419 inline const char* chr2sgml(_In_reads_or_z_(count) const wchar_t* entity, _In_ size_t count)
420 {
421 _Assume_(entity && count);
422
423 const wchar_t e2 = entity[0];
424 for (size_t i = 0, j = _countof(unicode_sgml); i < j; ) {
425 size_t m = (i + j) / 2;
426 wchar_t e1 = sgml_unicode[unicode_sgml[m]].unicode[0];
427 if (e1 < e2)
428 i = m + 1;
429 else if (e1 > e2)
430 j = m;
431 else {
432 auto r = strncmp(sgml_unicode[unicode_sgml[m]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1);
433 if (r < 0)
434 i = m + 1;
435 else if (r > 0)
436 j = m;
437 else {
438 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--);
439 return sgml_unicode[unicode_sgml[m]].sgml;
440 }
441 }
442 }
443 return nullptr;
444 }
446
455 inline void str2sgmlcat(
456 _Inout_ std::string& dst,
457 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
458 _In_ size_t what = 0)
459 {
460 _Assume_(src || !count_src);
461
462 const bool
463 do_ascii = (what & sgml_full) == 0,
464 do_quot = (what & sgml_quot) == 0,
465 do_apos = (what & sgml_apos) == 0,
466 do_lt_gt = (what & sgml_lt_gt) == 0,
467 do_bsol = (what & sgml_bsol) == 0,
468 do_dollar = (what & sgml_dollar) == 0,
469 do_percnt = (what & sgml_percnt) == 0,
470 do_commat = (what & sgml_commat) == 0,
471 do_num = (what & sgml_num) == 0,
472 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
473 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
474 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
475
476 count_src = wcsnlen(src, count_src);
477 dst.reserve(dst.size() + count_src);
478 for (size_t i = 0; i < count_src;) {
479 size_t n = glyphlen(src + i, count_src - i);
480 if (n == 1 &&
481 do_ascii && (unsigned int)src[i] < 128 &&
482 src[i] != L'&' &&
483 (do_quot || (src[i] != L'"')) &&
484 (do_apos || (src[i] != L'\'')) &&
485 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
486 (do_bsol || (src[i] != L'\\')) &&
487 (do_dollar || (src[i] != L'$')) &&
488 (do_percnt || (src[i] != L'%')) &&
489 (do_commat || (src[i] != L'@')) &&
490 (do_num || (src[i] != L'#')) &&
491 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
492 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
493 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
494 {
495 // 7-bit ASCII and no desire to encode it as an SGML entity.
496 dst.append(1, static_cast<char>(src[i++]));
497 }
498 else {
499 const char* entity = chr2sgml(src + i, n);
500 if (entity) {
501 dst.append(1, '&');
502 dst.append(entity);
503 dst.append(1, ';');
504 i += n;
505 }
506 else if (n == 1) {
507 // Trivial character (1 code unit, 1 glyph), no entity available.
508 if ((unsigned int)src[i] < 128)
509 dst.append(1, static_cast<char>(src[i++]));
510 else {
511 char tmp[3 + 8 + 1 + 1];
512 snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
513 dst.append(tmp);
514 }
515 }
516 else {
517 // Non-trivial character. Decompose.
518 const size_t end = i + n;
519 while (i < end) {
520 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
521 dst.append(1, '&');
522 dst.append(entity);
523 dst.append(1, ';');
524 i++;
525 }
526 else if ((unsigned int)src[i] < 128)
527 dst.append(1, static_cast<char>(src[i++]));
528 else {
529 uint32_t unicode;
530#ifdef _WIN32
531 if (i + 1 < end && is_surrogate_pair(src + i)) {
532 unicode = surrogate_pair_to_ucs4(src + i);
533 i += 2;
534 }
535 else
536#endif
537 {
538 unicode = src[i++];
539 }
540 char tmp[3 + 8 + 1 + 1];
541 snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
542 dst.append(tmp);
543 }
544 }
545 }
546 }
547 }
548 }
549
557 inline void str2sgmlcat(
558 _Inout_ std::string& dst,
559 _In_ const std::wstring& src,
560 _In_ size_t what = 0)
561 {
562 str2sgmlcat(dst, src.c_str(), src.size(), what);
563 }
564
576 inline size_t str2sgmlcat(
577 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
578 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
579 _In_ size_t what = 0)
580 {
581 _Assume_(dst || !count_dst);
582 _Assume_(src || !count_src);
583
584 static const std::invalid_argument buffer_overrun("buffer overrun");
585 const bool
586 do_ascii = (what & sgml_full) == 0,
587 do_quot = (what & sgml_quot) == 0,
588 do_apos = (what & sgml_apos) == 0,
589 do_lt_gt = (what & sgml_lt_gt) == 0,
590 do_bsol = (what & sgml_bsol) == 0,
591 do_dollar = (what & sgml_dollar) == 0,
592 do_percnt = (what & sgml_percnt) == 0,
593 do_commat = (what & sgml_commat) == 0,
594 do_num = (what & sgml_num) == 0,
595 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
596 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
597 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
598
599 size_t j = strnlen(dst, count_dst);
600 count_src = wcsnlen(src, count_src);
601 for (size_t i = 0; i < count_src;) {
602 size_t n = glyphlen(src + i, count_src - i);
603 if (n == 1 &&
604 do_ascii && (unsigned int)src[i] < 128 &&
605 src[i] != L'&' &&
606 (do_quot || (src[i] != L'"')) &&
607 (do_apos || (src[i] != L'\'')) &&
608 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
609 (do_bsol || (src[i] != L'\\')) &&
610 (do_dollar || (src[i] != L'$')) &&
611 (do_percnt || (src[i] != L'%')) &&
612 (do_commat || (src[i] != L'@')) &&
613 (do_num || (src[i] != L'#')) &&
614 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
615 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
616 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
617 {
618 // 7-bit ASCII and no desire to encode it as an SGML entity.
619 if (j + 1 >= count_dst)
620 throw buffer_overrun;
621 dst[j++] = static_cast<char>(src[i++]);
622 }
623 else {
624 const char* entity = chr2sgml(src + i, n);
625 if (entity) {
626 size_t m = strlen(entity);
627 if (j + m + 2 >= count_dst)
628 throw buffer_overrun;
629 dst[j++] = '&';
630 memcpy(dst + j, entity, m * sizeof(char)); j += m;
631 dst[j++] = ';';
632 i += n;
633 }
634 else if (n == 1) {
635 // Trivial character (1 code unit, 1 glyph), no entity available.
636 if ((unsigned int)src[i] < 128) {
637 if (j + 1 >= count_dst)
638 throw buffer_overrun;
639 dst[j++] = static_cast<char>(src[i++]);
640 }
641 else {
642 char tmp[3 + 8 + 1 + 1];
643 int m = snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
644 _Assume_(m >= 0);
645 if (static_cast<size_t>(m) >= count_dst)
646 throw buffer_overrun;
647 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
648 }
649 }
650 else {
651 // Non-trivial character. Decompose.
652 const size_t end = i + n;
653 while (i < end) {
654 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
655 size_t m = strlen(entity);
656 if (j + m + 2 >= count_dst)
657 throw buffer_overrun;
658 dst[j++] = '&';
659 memcpy(dst + j, entity, m * sizeof(char)); j += m;
660 dst[j++] = ';';
661 i++;
662 }
663 else if ((unsigned int)src[i] < 128) {
664 if (j + 1 >= count_dst)
665 throw buffer_overrun;
666 dst[j++] = static_cast<char>(src[i++]);
667 }
668 else {
669 uint32_t unicode;
670#ifdef _WIN32
671 if (i + 1 < end && is_surrogate_pair(src + i)) {
672 unicode = surrogate_pair_to_ucs4(src + i);
673 i += 2;
674 }
675 else
676#endif
677 {
678 unicode = src[i++];
679 }
680 char tmp[3 + 8 + 1 + 1];
681 int m = snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
682 _Assume_(m >= 0);
683 if (static_cast<size_t>(m) >= count_dst)
684 throw buffer_overrun;
685 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
686 }
687 }
688 }
689 }
690 }
691 if (j >= count_dst)
692 throw buffer_overrun;
693 dst[j] = 0;
694 return j;
695 }
696
705 inline void str2sgmlcpy(
706 _Inout_ std::string& dst,
707 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
708 _In_ size_t what = 0)
709 {
710 dst.clear();
711 str2sgmlcat(dst, src, count_src, what);
712 }
713
721 inline void str2sgmlcpy(
722 _Inout_ std::string& dst,
723 _In_ const std::wstring& src,
724 _In_ size_t what = 0)
725 {
726 str2sgmlcpy(dst, src.data(), src.size(), what);
727 }
728
740 inline size_t str2sgmlcpy(
741 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
742 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
743 _In_ size_t what = 0)
744 {
745 _Assume_(dst || !count_dst);
746 if (count_dst)
747 dst[0] = 0;
748 return str2sgmlcat(dst, count_dst, src, count_src, what);
749 }
750
760 inline std::string str2sgml(
761 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
762 _In_ size_t what = 0)
763 {
764 std::string dst;
765 str2sgmlcat(dst, src, count_src, what);
766 return dst;
767 }
768
777 inline std::string str2sgml(
778 _In_ const std::wstring& src,
779 _In_ size_t what = 0)
780 {
781 return str2sgml(src.c_str(), src.size(), what);
782 }
783}