10#include "sgml_unicode.hpp"
20 inline const wchar_t* sgml2uni(_In_reads_or_z_(count)
const T* entity, _In_
size_t count)
22 _Assume_(entity && count);
23 _Assume_(count < 2 || entity[0] !=
'#');
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])
29 else if (sgml_unicode[m].sgml[0] > entity[0])
32 auto r = strncmp<char, T>(sgml_unicode[m].sgml + 1, _countof(sgml_unicode[0].sgml) - 1, entity + 1, count - 1);
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;
47 inline const T* sgmlend(
48 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
50 _Assume_(str || !count);
51 for (
size_t i = 0; i < count; i++) {
54 if (!str[i] || str[i] ==
'&' || isspace(str[i]))
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;
93 inline void sgml2wstrcat(
94 _Inout_ std::wstring& dst,
95 _In_reads_or_z_opt_(count_src)
const T* src, _In_
size_t count_src,
97 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
98 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
100 _Assume_(src || !count_src);
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;
116 count_src = strnlen(src, count_src);
117 dst.reserve(dst.size() + count_src);
118 for (
size_t i = 0; i < count_src;) {
120 auto end = sgmlend(src + i + 1, count_src - i - 1);
122 const wchar_t* entity_w;
124 size_t n = end - src - i - 1;
125 if (n >= 2 && src[i + 1] ==
'#') {
127 if (src[i + 2] ==
'x' || src[i + 2] ==
'X')
128 unicode = strtou32(src + i + 3, n - 2,
nullptr, 16);
130 unicode = strtou32(src + i + 2, n - 1,
nullptr, 10);
132 if (unicode < 0x10000) {
133 chr[0] = (wchar_t)unicode;
137 ucs4_to_surrogate_pair(chr, unicode);
141 chr[0] = (wchar_t)unicode;
147 entity_w = sgml2uni(src + i + 1, n);
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
']')))
163 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
164 dst.append(entity_w);
166 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
171 dst.append(1, src[i++]);
176 _Deprecated_(
"Use stdex::sgml2wstrcat")
177 inline
void sgml2wstr(
178 _Inout_ std::wstring& dst,
179 _In_reads_or_z_opt_(count_src) const T* src, _In_
size_t count_src,
181 _In_ const mapping<
size_t>& offset = mapping<
size_t>(0, 0),
182 _Inout_opt_ mapping_vector<
size_t>* map =
nullptr)
184 sgml2wstrcat(dst, src, count_src, skip, offset, map);
197 inline void sgml2wstrcat(
198 _Inout_ std::wstring& dst,
199 _In_
const std::basic_string<T>& src,
201 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
202 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
204 sgml2wstrcat(dst, src.data(), src.size(), skip, offset, map);
208 _Deprecated_(
"Use stdex::sgml2wstrcat")
209 inline
void sgml2wstr(
210 _Inout_ std::wstring& dst,
211 _In_ const std::basic_string<T>& src,
213 _In_ const mapping<
size_t>& offset = mapping<
size_t>(0, 0),
214 _Inout_opt_ mapping_vector<
size_t>* map =
nullptr)
216 sgml2wstrcat(dst, src, skip, offset, map);
233 inline size_t sgml2wstrcat(
234 _Inout_cap_(count_dst)
wchar_t* dst, _In_
size_t count_dst,
235 _In_reads_or_z_opt_(count_src)
const T* src, _In_
size_t count_src,
237 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
238 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
240 _Assume_(dst || !count_dst);
241 _Assume_(src || !count_src);
243 static const std::invalid_argument buffer_overrun(
"buffer overrun");
245 skip_quot = (skip & sgml_quot) == 0,
246 skip_apos = (skip & sgml_apos) == 0,
247 skip_amp = (skip & sgml_amp) == 0,
248 skip_lt_gt = (skip & sgml_lt_gt) == 0,
249 skip_bsol = (skip & sgml_bsol) == 0,
250 skip_dollar = (skip & sgml_dollar) == 0,
251 skip_percnt = (skip & sgml_percnt) == 0,
252 skip_commat = (skip & sgml_commat) == 0,
253 skip_num = (skip & sgml_num) == 0,
254 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
255 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
256 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
258 size_t j = wcsnlen(dst, count_dst);
259 count_src = strnlen(src, count_src);
260 for (
size_t i = 0; i < count_src;) {
262 auto end = sgmlend(src + i + 1, count_src - i - 1);
264 const wchar_t* entity_w;
266 size_t n = end - src - i - 1;
267 if (n >= 2 && src[i + 1] ==
'#') {
269 if (src[i + 2] ==
'x' || src[i + 2] ==
'X')
270 unicode = strtou32(src + i + 3, n - 2,
nullptr, 16);
272 unicode = strtou32(src + i + 2, n - 1,
nullptr, 10);
274 if (unicode < 0x10000) {
275 chr[0] = (wchar_t)unicode;
279 ucs4_to_surrogate_pair(chr, unicode);
283 chr[0] = (wchar_t)unicode;
289 entity_w = sgml2uni(src + i + 1, n);
292 (skip_quot || (entity_w[0] != L
'"')) &&
293 (skip_apos || (entity_w[0] != L
'\'')) &&
294 (skip_amp || (entity_w[0] != L
'&')) &&
295 (skip_lt_gt || (entity_w[0] != L
'<' && entity_w[0] != L
'>')) &&
296 (skip_bsol || (entity_w[0] != L
'\\')) &&
297 (skip_dollar || (entity_w[0] != L
'$')) &&
298 (skip_percnt || (entity_w[0] != L
'%')) &&
299 (skip_commat || (entity_w[0] != L
'@')) &&
300 (skip_num || (entity_w[0] != L
'#')) &&
301 (skip_lpar_rpar || (entity_w[0] != L
'(' && entity_w[0] != L
')')) &&
302 (skip_lcub_rcub || (entity_w[0] != L
'{' && entity_w[0] != L
'}')) &&
303 (skip_lsqb_rsqb || (entity_w[0] != L
'[' && entity_w[0] != L
']')))
305 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
306 size_t m = wcslen(entity_w);
307 if (j + m >= count_dst)
308 throw buffer_overrun;
309 memcpy(dst + j, entity_w, m *
sizeof(
wchar_t)); j += m;
311 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
316 if (j + 1 >= count_dst)
317 throw buffer_overrun;
321 throw buffer_overrun;
327 _Deprecated_(
"Use stdex::sgml2wstrcat")
328 inline
size_t sgml2wstr(
329 _Inout_cap_(count_dst)
wchar_t* dst, _In_
size_t count_dst,
330 _In_reads_or_z_opt_(count_src) const T* src, _In_
size_t count_src,
332 _In_ const mapping<
size_t>& offset = mapping<
size_t>(0, 0),
333 _Inout_opt_ mapping_vector<
size_t>* map =
nullptr)
335 return sgml2wstrcat(dst, count_dst, src, count_src, skip, offset, map);
349 inline void sgml2wstrcpy(
350 _Inout_ std::wstring& dst,
351 _In_reads_or_z_opt_(count_src)
const T* src, _In_
size_t count_src,
353 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
354 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
359 sgml2wstrcat(dst, src, count_src, skip, offset, map);
371 template<
class _Elem,
class _Traits,
class _Ax>
372 inline void sgml2wstrcpy(
373 _Inout_ std::wstring& dst,
374 _In_
const std::basic_string<_Elem, _Traits, _Ax>& src,
376 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
377 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
379 sgml2wstrcpy(dst, src.data(), src.size(), skip, offset, map);
396 inline size_t sgml2wstrcpy(
397 _Inout_cap_(count_dst)
wchar_t* dst, _In_
size_t count_dst,
398 _In_reads_or_z_opt_(count_src)
const T* src, _In_
size_t count_src,
400 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
401 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
403 _Assume_(dst || !count_dst);
408 return sgml2wstrcat(dst, count_dst, src, count_src, skip, offset, map);
423 inline std::wstring sgml2wstr(
424 _In_reads_or_z_opt_(count_src)
const T* src, _In_
size_t count_src,
426 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
427 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
430 sgml2wstrcat(dst, src, count_src, skip, offset, map);
445 inline std::wstring sgml2wstr(
446 _In_
const std::basic_string<T>& src,
448 _In_
const mapping<size_t>& offset = mapping<size_t>(0, 0),
449 _Inout_opt_ mapping_vector<size_t>* map =
nullptr)
451 return sgml2wstr(src.c_str(), src.size(), skip, offset, map);
455 inline const char* chr2sgml(_In_reads_or_z_(count)
const wchar_t* entity, _In_
size_t count)
457 _Assume_(entity && count);
459 const wchar_t e2 = entity[0];
460 for (
size_t i = 0, j = _countof(unicode_sgml); i < j; ) {
461 size_t m = (i + j) / 2;
462 wchar_t e1 = sgml_unicode[unicode_sgml[m]].unicode[0];
468 auto r = strncmp(sgml_unicode[unicode_sgml[m]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1);
474 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--);
475 return sgml_unicode[unicode_sgml[m]].sgml;
491 inline void wstr2sgmlcat(
492 _Inout_ std::string& dst,
493 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
494 _In_
size_t what = 0)
496 _Assume_(src || !count_src);
499 do_ascii = (what & sgml_full) == 0,
500 do_quot = (what & sgml_quot) == 0,
501 do_apos = (what & sgml_apos) == 0,
502 do_lt_gt = (what & sgml_lt_gt) == 0,
503 do_bsol = (what & sgml_bsol) == 0,
504 do_dollar = (what & sgml_dollar) == 0,
505 do_percnt = (what & sgml_percnt) == 0,
506 do_commat = (what & sgml_commat) == 0,
507 do_num = (what & sgml_num) == 0,
508 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
509 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
510 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
512 count_src = wcsnlen(src, count_src);
513 dst.reserve(dst.size() + count_src);
514 for (
size_t i = 0; i < count_src;) {
515 size_t n = glyphlen(src + i, count_src - i);
517 do_ascii && (
unsigned int)src[i] < 128 &&
519 (do_quot || (src[i] != L
'"')) &&
520 (do_apos || (src[i] != L
'\'')) &&
521 (do_lt_gt || (src[i] != L
'<' && src[i] != L
'>')) &&
522 (do_bsol || (src[i] != L
'\\')) &&
523 (do_dollar || (src[i] != L
'$')) &&
524 (do_percnt || (src[i] != L
'%')) &&
525 (do_commat || (src[i] != L
'@')) &&
526 (do_num || (src[i] != L
'#')) &&
527 (do_lpar_rpar || (src[i] != L
'(' && src[i] != L
')')) &&
528 (do_lcub_rcub || (src[i] != L
'{' && src[i] != L
'}')) &&
529 (do_lsqb_rsqb || (src[i] != L
'[' && src[i] != L
']')))
532 dst.append(1,
static_cast<char>(src[i++]));
535 const char* entity = chr2sgml(src + i, n);
544 if ((
unsigned int)src[i] < 128)
545 dst.append(1,
static_cast<char>(src[i++]));
547 char tmp[3 + 8 + 1 + 1];
548 snprintf(tmp, _countof(tmp),
"&#x%x;", src[i++]);
554 const size_t end = i + n;
556 if ((entity = chr2sgml(src + i, 1)) !=
nullptr) {
562 else if ((
unsigned int)src[i] < 128)
563 dst.append(1,
static_cast<char>(src[i++]));
567 if (i + 1 < end && is_surrogate_pair(src + i)) {
568 unicode = surrogate_pair_to_ucs4(src + i);
576 char tmp[3 + 8 + 1 + 1];
577 snprintf(tmp, _countof(tmp),
"&#x%x;", unicode);
586 _Deprecated_(
"Use stdex::wstr2sgmlcat")
587 inline
void wstr2sgml(
588 _Inout_ std::
string& dst,
589 _In_reads_or_z_opt_(count_src) const
wchar_t* src, _In_
size_t count_src,
590 _In_
size_t what = 0)
592 wstr2sgmlcat(dst, src, count_src, what);
602 inline void wstr2sgmlcat(
603 _Inout_ std::string& dst,
604 _In_
const std::wstring& src,
605 _In_
size_t what = 0)
607 wstr2sgmlcat(dst, src.c_str(), src.size(), what);
610 _Deprecated_(
"Use stdex::wstr2sgmlcat")
611 inline
void wstr2sgml(
612 _Inout_ std::
string& dst,
613 _In_ const std::wstring& src,
614 _In_
size_t what = 0)
616 wstr2sgmlcat(dst, src, what);
630 inline size_t wstr2sgmlcat(
631 _Inout_cap_(count_dst)
char* dst, _In_
size_t count_dst,
632 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
633 _In_
size_t what = 0)
635 _Assume_(dst || !count_dst);
636 _Assume_(src || !count_src);
638 static const std::invalid_argument buffer_overrun(
"buffer overrun");
640 do_ascii = (what & sgml_full) == 0,
641 do_quot = (what & sgml_quot) == 0,
642 do_apos = (what & sgml_apos) == 0,
643 do_lt_gt = (what & sgml_lt_gt) == 0,
644 do_bsol = (what & sgml_bsol) == 0,
645 do_dollar = (what & sgml_dollar) == 0,
646 do_percnt = (what & sgml_percnt) == 0,
647 do_commat = (what & sgml_commat) == 0,
648 do_num = (what & sgml_num) == 0,
649 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
650 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
651 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
653 size_t j = strnlen(dst, count_dst);
654 count_src = wcsnlen(src, count_src);
655 for (
size_t i = 0; i < count_src;) {
656 size_t n = glyphlen(src + i, count_src - i);
658 do_ascii && (
unsigned int)src[i] < 128 &&
660 (do_quot || (src[i] != L
'"')) &&
661 (do_apos || (src[i] != L
'\'')) &&
662 (do_lt_gt || (src[i] != L
'<' && src[i] != L
'>')) &&
663 (do_bsol || (src[i] != L
'\\')) &&
664 (do_dollar || (src[i] != L
'$')) &&
665 (do_percnt || (src[i] != L
'%')) &&
666 (do_commat || (src[i] != L
'@')) &&
667 (do_num || (src[i] != L
'#')) &&
668 (do_lpar_rpar || (src[i] != L
'(' && src[i] != L
')')) &&
669 (do_lcub_rcub || (src[i] != L
'{' && src[i] != L
'}')) &&
670 (do_lsqb_rsqb || (src[i] != L
'[' && src[i] != L
']')))
673 if (j + 1 >= count_dst)
674 throw buffer_overrun;
675 dst[j++] =
static_cast<char>(src[i++]);
678 const char* entity = chr2sgml(src + i, n);
680 size_t m = strlen(entity);
681 if (j + m + 2 >= count_dst)
682 throw buffer_overrun;
684 memcpy(dst + j, entity, m *
sizeof(
char)); j += m;
690 if ((
unsigned int)src[i] < 128) {
691 if (j + 1 >= count_dst)
692 throw buffer_overrun;
693 dst[j++] =
static_cast<char>(src[i++]);
696 char tmp[3 + 8 + 1 + 1];
697 int m = snprintf(tmp, _countof(tmp),
"&#x%x;", src[i++]);
699 if (
static_cast<size_t>(m) >= count_dst)
700 throw buffer_overrun;
701 memcpy(dst + j, tmp, m *
sizeof(
char)); j += m;
706 const size_t end = i + n;
708 if ((entity = chr2sgml(src + i, 1)) !=
nullptr) {
709 size_t m = strlen(entity);
710 if (j + m + 2 >= count_dst)
711 throw buffer_overrun;
713 memcpy(dst + j, entity, m *
sizeof(
char)); j += m;
717 else if ((
unsigned int)src[i] < 128) {
718 if (j + 1 >= count_dst)
719 throw buffer_overrun;
720 dst[j++] =
static_cast<char>(src[i++]);
725 if (i + 1 < end && is_surrogate_pair(src + i)) {
726 unicode = surrogate_pair_to_ucs4(src + i);
734 char tmp[3 + 8 + 1 + 1];
735 int m = snprintf(tmp, _countof(tmp),
"&#x%x;", unicode);
737 if (
static_cast<size_t>(m) >= count_dst)
738 throw buffer_overrun;
739 memcpy(dst + j, tmp, m *
sizeof(
char)); j += m;
746 throw buffer_overrun;
751 _Deprecated_(
"Use stdex::wstr2sgmlcat")
752 inline
size_t wstr2sgml(
753 _Inout_cap_(count_dst)
char* dst, _In_
size_t count_dst,
754 _In_reads_or_z_opt_(count_src) const
wchar_t* src, _In_
size_t count_src,
755 _In_
size_t what = 0)
757 return wstr2sgmlcat(dst, count_dst, src, count_src, what);
768 inline void wstr2sgmlcpy(
769 _Inout_ std::string& dst,
770 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
771 _In_
size_t what = 0)
774 wstr2sgmlcat(dst, src, count_src, what);
784 inline void wstr2sgmlcpy(
785 _Inout_ std::string& dst,
786 _In_
const std::wstring& src,
787 _In_
size_t what = 0)
789 wstr2sgmlcpy(dst, src.data(), src.size(), what);
803 inline size_t wstr2sgmlcpy(
804 _Inout_cap_(count_dst)
char* dst, _In_
size_t count_dst,
805 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
806 _In_
size_t what = 0)
808 _Assume_(dst || !count_dst);
811 return wstr2sgmlcat(dst, count_dst, src, count_src, what);
823 inline std::string wstr2sgml(
824 _In_reads_or_z_opt_(count_src)
const wchar_t* src, _In_
size_t count_src,
825 _In_
size_t what = 0)
828 wstr2sgmlcat(dst, src, count_src, what);
840 inline std::string wstr2sgml(
841 _In_
const std::wstring& src,
842 _In_
size_t what = 0)
844 return wstr2sgml(src.c_str(), src.size(), what);