diff --git a/annotated.html b/annotated.html index b193f85c0..013e7d071 100644 --- a/annotated.html +++ b/annotated.html @@ -186,7 +186,7 @@ $(function() { diff --git a/base64_8hpp_source.html b/base64_8hpp_source.html index be4eeb0c0..fb42ecc9b 100644 --- a/base64_8hpp_source.html +++ b/base64_8hpp_source.html @@ -318,7 +318,7 @@ $(function() { diff --git a/classes.html b/classes.html index 1377f2c17..b0c996e79 100644 --- a/classes.html +++ b/classes.html @@ -118,7 +118,7 @@ $(function() { diff --git a/classstdex_1_1base64__dec-members.html b/classstdex_1_1base64__dec-members.html index 6067d0c61..0ecbb0417 100644 --- a/classstdex_1_1base64__dec-members.html +++ b/classstdex_1_1base64__dec-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1base64__dec.html b/classstdex_1_1base64__dec.html index 05064d54b..d5463be76 100644 --- a/classstdex_1_1base64__dec.html +++ b/classstdex_1_1base64__dec.html @@ -230,7 +230,7 @@ template<class _Ty , class _Ax , class _Tchr > diff --git a/classstdex_1_1base64__enc-members.html b/classstdex_1_1base64__enc-members.html index c24b67cc9..69bf6b73c 100644 --- a/classstdex_1_1base64__enc-members.html +++ b/classstdex_1_1base64__enc-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1base64__enc.html b/classstdex_1_1base64__enc.html index a2214f8a2..f6b673a11 100644 --- a/classstdex_1_1base64__enc.html +++ b/classstdex_1_1base64__enc.html @@ -235,7 +235,7 @@ template<class _Elem , class _Traits , class _Ax > diff --git a/classstdex_1_1errno__error-members.html b/classstdex_1_1errno__error-members.html index bb771f6da..8fbc78ddd 100644 --- a/classstdex_1_1errno__error-members.html +++ b/classstdex_1_1errno__error-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1errno__error.html b/classstdex_1_1errno__error.html index b06be7a1e..86a68c1a1 100644 --- a/classstdex_1_1errno__error.html +++ b/classstdex_1_1errno__error.html @@ -286,7 +286,7 @@ errno_t m_num diff --git a/classstdex_1_1global__progress-members.html b/classstdex_1_1global__progress-members.html index de420a6a1..c373198a2 100644 --- a/classstdex_1_1global__progress-members.html +++ b/classstdex_1_1global__progress-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1global__progress.html b/classstdex_1_1global__progress.html index 5379df754..fb8f89ada 100644 --- a/classstdex_1_1global__progress.html +++ b/classstdex_1_1global__progress.html @@ -562,7 +562,7 @@ template<class T > diff --git a/classstdex_1_1hex__dec-members.html b/classstdex_1_1hex__dec-members.html index c722b53b8..54fcd2c05 100644 --- a/classstdex_1_1hex__dec-members.html +++ b/classstdex_1_1hex__dec-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1hex__dec.html b/classstdex_1_1hex__dec.html index 91ac578c2..9a4a15427 100644 --- a/classstdex_1_1hex__dec.html +++ b/classstdex_1_1hex__dec.html @@ -221,7 +221,7 @@ template<class _Ty , class _Ax , class _Tchr > diff --git a/classstdex_1_1hex__enc-members.html b/classstdex_1_1hex__enc-members.html index 9b3be632f..a4380aba4 100644 --- a/classstdex_1_1hex__enc-members.html +++ b/classstdex_1_1hex__enc-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1hex__enc.html b/classstdex_1_1hex__enc.html index 38347fd23..a2248338a 100644 --- a/classstdex_1_1hex__enc.html +++ b/classstdex_1_1hex__enc.html @@ -198,7 +198,7 @@ template<class _Elem , class _Traits , class _Ax > diff --git a/classstdex_1_1idrec_1_1record-members.html b/classstdex_1_1idrec_1_1record-members.html index 6464a5f6e..432aa4f61 100644 --- a/classstdex_1_1idrec_1_1record-members.html +++ b/classstdex_1_1idrec_1_1record-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1idrec_1_1record.html b/classstdex_1_1idrec_1_1record.html index d40087ffd..a8c432fbb 100644 --- a/classstdex_1_1idrec_1_1record.html +++ b/classstdex_1_1idrec_1_1record.html @@ -380,7 +380,7 @@ template<class T , class T_ID , const T_ID ID, class T_SIZE , unsigned int AL diff --git a/classstdex_1_1lazy__progress-members.html b/classstdex_1_1lazy__progress-members.html index e03f84b22..ed5c37a14 100644 --- a/classstdex_1_1lazy__progress-members.html +++ b/classstdex_1_1lazy__progress-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1lazy__progress.html b/classstdex_1_1lazy__progress.html index 4e705121d..e4740ef09 100644 --- a/classstdex_1_1lazy__progress.html +++ b/classstdex_1_1lazy__progress.html @@ -285,7 +285,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__angle-members.html b/classstdex_1_1parser_1_1basic__angle-members.html index 48ef202d3..bbfbb3f15 100644 --- a/classstdex_1_1parser_1_1basic__angle-members.html +++ b/classstdex_1_1parser_1_1basic__angle-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__angle.html b/classstdex_1_1parser_1_1basic__angle.html index f658ad8b3..5a54bf74b 100644 --- a/classstdex_1_1parser_1_1basic__angle.html +++ b/classstdex_1_1parser_1_1basic__angle.html @@ -250,7 +250,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__any__cu-members.html b/classstdex_1_1parser_1_1basic__any__cu-members.html index efccdba93..dc7049fff 100644 --- a/classstdex_1_1parser_1_1basic__any__cu-members.html +++ b/classstdex_1_1parser_1_1basic__any__cu-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__any__cu.html b/classstdex_1_1parser_1_1basic__any__cu.html index 94fa90253..feb709c7b 100644 --- a/classstdex_1_1parser_1_1basic__any__cu.html +++ b/classstdex_1_1parser_1_1basic__any__cu.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__bol-members.html b/classstdex_1_1parser_1_1basic__bol-members.html index 5f508ce2f..653d221c3 100644 --- a/classstdex_1_1parser_1_1basic__bol-members.html +++ b/classstdex_1_1parser_1_1basic__bol-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__bol.html b/classstdex_1_1parser_1_1basic__bol.html index 7ce929d57..2b3086a85 100644 --- a/classstdex_1_1parser_1_1basic__bol.html +++ b/classstdex_1_1parser_1_1basic__bol.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__branch-members.html b/classstdex_1_1parser_1_1basic__branch-members.html index 83379d9aa..a389eedd8 100644 --- a/classstdex_1_1parser_1_1basic__branch-members.html +++ b/classstdex_1_1parser_1_1basic__branch-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__branch.html b/classstdex_1_1parser_1_1basic__branch.html index f26ab3725..6f0bccacd 100644 --- a/classstdex_1_1parser_1_1basic__branch.html +++ b/classstdex_1_1parser_1_1basic__branch.html @@ -261,7 +261,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__chemical__formula-members.html b/classstdex_1_1parser_1_1basic__chemical__formula-members.html index 2c7f452d4..b912b6996 100644 --- a/classstdex_1_1parser_1_1basic__chemical__formula-members.html +++ b/classstdex_1_1parser_1_1basic__chemical__formula-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__chemical__formula.html b/classstdex_1_1parser_1_1basic__chemical__formula.html index 850ea98b8..3a2460d5d 100644 --- a/classstdex_1_1parser_1_1basic__chemical__formula.html +++ b/classstdex_1_1parser_1_1basic__chemical__formula.html @@ -245,7 +245,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__cu-members.html b/classstdex_1_1parser_1_1basic__cu-members.html index 51f61b28f..93dc9fa65 100644 --- a/classstdex_1_1parser_1_1basic__cu-members.html +++ b/classstdex_1_1parser_1_1basic__cu-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__cu.html b/classstdex_1_1parser_1_1basic__cu.html index 83d4b7dcf..f976e58f5 100644 --- a/classstdex_1_1parser_1_1basic__cu.html +++ b/classstdex_1_1parser_1_1basic__cu.html @@ -204,7 +204,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__cu__set-members.html b/classstdex_1_1parser_1_1basic__cu__set-members.html index a658325c8..459f049cb 100644 --- a/classstdex_1_1parser_1_1basic__cu__set-members.html +++ b/classstdex_1_1parser_1_1basic__cu__set-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__cu__set.html b/classstdex_1_1parser_1_1basic__cu__set.html index 07c994299..d4f0b1922 100644 --- a/classstdex_1_1parser_1_1basic__cu__set.html +++ b/classstdex_1_1parser_1_1basic__cu__set.html @@ -218,7 +218,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__date-members.html b/classstdex_1_1parser_1_1basic__date-members.html index f73ffe6e7..0ecfe4ecd 100644 --- a/classstdex_1_1parser_1_1basic__date-members.html +++ b/classstdex_1_1parser_1_1basic__date-members.html @@ -100,7 +100,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__date.html b/classstdex_1_1parser_1_1basic__date.html index 600554253..c623ba7a9 100644 --- a/classstdex_1_1parser_1_1basic__date.html +++ b/classstdex_1_1parser_1_1basic__date.html @@ -258,7 +258,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__dns__domain__char-members.html b/classstdex_1_1parser_1_1basic__dns__domain__char-members.html index 44aa6aa99..de5158325 100644 --- a/classstdex_1_1parser_1_1basic__dns__domain__char-members.html +++ b/classstdex_1_1parser_1_1basic__dns__domain__char-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__dns__domain__char.html b/classstdex_1_1parser_1_1basic__dns__domain__char.html index 96427a3a2..040d443f5 100644 --- a/classstdex_1_1parser_1_1basic__dns__domain__char.html +++ b/classstdex_1_1parser_1_1basic__dns__domain__char.html @@ -206,7 +206,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__dns__name-members.html b/classstdex_1_1parser_1_1basic__dns__name-members.html index 8b3947f35..0b3424d44 100644 --- a/classstdex_1_1parser_1_1basic__dns__name-members.html +++ b/classstdex_1_1parser_1_1basic__dns__name-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__dns__name.html b/classstdex_1_1parser_1_1basic__dns__name.html index bc92b4420..fb4dc77da 100644 --- a/classstdex_1_1parser_1_1basic__dns__name.html +++ b/classstdex_1_1parser_1_1basic__dns__name.html @@ -208,7 +208,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__email__address-members.html b/classstdex_1_1parser_1_1basic__email__address-members.html index 7d9c93b27..4fad91691 100644 --- a/classstdex_1_1parser_1_1basic__email__address-members.html +++ b/classstdex_1_1parser_1_1basic__email__address-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__email__address.html b/classstdex_1_1parser_1_1basic__email__address.html index 3857fcb2e..a4d88243b 100644 --- a/classstdex_1_1parser_1_1basic__email__address.html +++ b/classstdex_1_1parser_1_1basic__email__address.html @@ -251,7 +251,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__emoticon-members.html b/classstdex_1_1parser_1_1basic__emoticon-members.html index cc2c4e99a..6fba44eae 100644 --- a/classstdex_1_1parser_1_1basic__emoticon-members.html +++ b/classstdex_1_1parser_1_1basic__emoticon-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__emoticon.html b/classstdex_1_1parser_1_1basic__emoticon.html index d4dd85d20..891f27bd5 100644 --- a/classstdex_1_1parser_1_1basic__emoticon.html +++ b/classstdex_1_1parser_1_1basic__emoticon.html @@ -249,7 +249,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__eol-members.html b/classstdex_1_1parser_1_1basic__eol-members.html index b6c356028..77d3f8afe 100644 --- a/classstdex_1_1parser_1_1basic__eol-members.html +++ b/classstdex_1_1parser_1_1basic__eol-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__eol.html b/classstdex_1_1parser_1_1basic__eol.html index 949326578..250edfc8d 100644 --- a/classstdex_1_1parser_1_1basic__eol.html +++ b/classstdex_1_1parser_1_1basic__eol.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__fraction-members.html b/classstdex_1_1parser_1_1basic__fraction-members.html index d54a7a72d..4c3711719 100644 --- a/classstdex_1_1parser_1_1basic__fraction-members.html +++ b/classstdex_1_1parser_1_1basic__fraction-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__fraction.html b/classstdex_1_1parser_1_1basic__fraction.html index efe114e1e..27c6c6c55 100644 --- a/classstdex_1_1parser_1_1basic__fraction.html +++ b/classstdex_1_1parser_1_1basic__fraction.html @@ -238,7 +238,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__integer-members.html b/classstdex_1_1parser_1_1basic__integer-members.html index 18515ebd3..9ec949f8a 100644 --- a/classstdex_1_1parser_1_1basic__integer-members.html +++ b/classstdex_1_1parser_1_1basic__integer-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer.html b/classstdex_1_1parser_1_1basic__integer.html index 00510db00..31f679a60 100644 --- a/classstdex_1_1parser_1_1basic__integer.html +++ b/classstdex_1_1parser_1_1basic__integer.html @@ -183,7 +183,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__integer10-members.html b/classstdex_1_1parser_1_1basic__integer10-members.html index 03ad3b572..7674b7d50 100644 --- a/classstdex_1_1parser_1_1basic__integer10-members.html +++ b/classstdex_1_1parser_1_1basic__integer10-members.html @@ -104,7 +104,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer10.html b/classstdex_1_1parser_1_1basic__integer10.html index fd03e0022..13bd142dd 100644 --- a/classstdex_1_1parser_1_1basic__integer10.html +++ b/classstdex_1_1parser_1_1basic__integer10.html @@ -240,7 +240,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__integer10ts-members.html b/classstdex_1_1parser_1_1basic__integer10ts-members.html index 4f53cb122..499cfb928 100644 --- a/classstdex_1_1parser_1_1basic__integer10ts-members.html +++ b/classstdex_1_1parser_1_1basic__integer10ts-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer10ts.html b/classstdex_1_1parser_1_1basic__integer10ts.html index 7f7a5b8db..d66a7b2a2 100644 --- a/classstdex_1_1parser_1_1basic__integer10ts.html +++ b/classstdex_1_1parser_1_1basic__integer10ts.html @@ -256,7 +256,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__integer16-members.html b/classstdex_1_1parser_1_1basic__integer16-members.html index 34d3032ef..6e1b4ecbe 100644 --- a/classstdex_1_1parser_1_1basic__integer16-members.html +++ b/classstdex_1_1parser_1_1basic__integer16-members.html @@ -110,7 +110,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer16.html b/classstdex_1_1parser_1_1basic__integer16.html index 0649b2ef5..58b064187 100644 --- a/classstdex_1_1parser_1_1basic__integer16.html +++ b/classstdex_1_1parser_1_1basic__integer16.html @@ -258,7 +258,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__ipv4__address-members.html b/classstdex_1_1parser_1_1basic__ipv4__address-members.html index 9f2674bfe..9c6e71e41 100644 --- a/classstdex_1_1parser_1_1basic__ipv4__address-members.html +++ b/classstdex_1_1parser_1_1basic__ipv4__address-members.html @@ -105,7 +105,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__ipv4__address.html b/classstdex_1_1parser_1_1basic__ipv4__address.html index 5bd6a211d..f989913f9 100644 --- a/classstdex_1_1parser_1_1basic__ipv4__address.html +++ b/classstdex_1_1parser_1_1basic__ipv4__address.html @@ -271,7 +271,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__ipv6__address-members.html b/classstdex_1_1parser_1_1basic__ipv6__address-members.html index e90002a66..4677807bb 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__address-members.html +++ b/classstdex_1_1parser_1_1basic__ipv6__address-members.html @@ -113,7 +113,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__ipv6__address.html b/classstdex_1_1parser_1_1basic__ipv6__address.html index b98c88c90..c8296a79e 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__address.html +++ b/classstdex_1_1parser_1_1basic__ipv6__address.html @@ -296,7 +296,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html index 6f45e4d29..780dd1f61 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html +++ b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html index 57040f1d4..a1375f3e1 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html +++ b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__iterations-members.html b/classstdex_1_1parser_1_1basic__iterations-members.html index 89cea53a3..0d4871f8e 100644 --- a/classstdex_1_1parser_1_1basic__iterations-members.html +++ b/classstdex_1_1parser_1_1basic__iterations-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__iterations.html b/classstdex_1_1parser_1_1basic__iterations.html index 43bb5312c..c287fa197 100644 --- a/classstdex_1_1parser_1_1basic__iterations.html +++ b/classstdex_1_1parser_1_1basic__iterations.html @@ -214,7 +214,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__json__string-members.html b/classstdex_1_1parser_1_1basic__json__string-members.html index 94dc8a14a..d6ff360d8 100644 --- a/classstdex_1_1parser_1_1basic__json__string-members.html +++ b/classstdex_1_1parser_1_1basic__json__string-members.html @@ -104,7 +104,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__json__string.html b/classstdex_1_1parser_1_1basic__json__string.html index 5008976fe..63ca0645b 100644 --- a/classstdex_1_1parser_1_1basic__json__string.html +++ b/classstdex_1_1parser_1_1basic__json__string.html @@ -266,7 +266,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__mixed__numeral-members.html b/classstdex_1_1parser_1_1basic__mixed__numeral-members.html index 46e2c414c..7a3dbad6f 100644 --- a/classstdex_1_1parser_1_1basic__mixed__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__mixed__numeral-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__mixed__numeral.html b/classstdex_1_1parser_1_1basic__mixed__numeral.html index e45b38d68..015177c1e 100644 --- a/classstdex_1_1parser_1_1basic__mixed__numeral.html +++ b/classstdex_1_1parser_1_1basic__mixed__numeral.html @@ -253,7 +253,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__monetary__numeral-members.html b/classstdex_1_1parser_1_1basic__monetary__numeral-members.html index 194a562ab..182f354ba 100644 --- a/classstdex_1_1parser_1_1basic__monetary__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__monetary__numeral-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__monetary__numeral.html b/classstdex_1_1parser_1_1basic__monetary__numeral.html index e03d85e09..352bca0c0 100644 --- a/classstdex_1_1parser_1_1basic__monetary__numeral.html +++ b/classstdex_1_1parser_1_1basic__monetary__numeral.html @@ -257,7 +257,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__noop-members.html b/classstdex_1_1parser_1_1basic__noop-members.html index fb74123a0..8ed670e13 100644 --- a/classstdex_1_1parser_1_1basic__noop-members.html +++ b/classstdex_1_1parser_1_1basic__noop-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__noop.html b/classstdex_1_1parser_1_1basic__noop.html index 934422cde..51387caf8 100644 --- a/classstdex_1_1parser_1_1basic__noop.html +++ b/classstdex_1_1parser_1_1basic__noop.html @@ -191,7 +191,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__parser-members.html b/classstdex_1_1parser_1_1basic__parser-members.html index 4f736404c..04f3fa9e9 100644 --- a/classstdex_1_1parser_1_1basic__parser-members.html +++ b/classstdex_1_1parser_1_1basic__parser-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__parser.html b/classstdex_1_1parser_1_1basic__parser.html index e73554d89..0d92d8a2b 100644 --- a/classstdex_1_1parser_1_1basic__parser.html +++ b/classstdex_1_1parser_1_1basic__parser.html @@ -183,7 +183,7 @@ class stdex::parser::basic_parser< T >

Base template for all parse

diff --git a/classstdex_1_1parser_1_1basic__permutation-members.html b/classstdex_1_1parser_1_1basic__permutation-members.html index ac34a7427..3ffd4d273 100644 --- a/classstdex_1_1parser_1_1basic__permutation-members.html +++ b/classstdex_1_1parser_1_1basic__permutation-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__permutation.html b/classstdex_1_1parser_1_1basic__permutation.html index c7c155c24..6b0eb62cf 100644 --- a/classstdex_1_1parser_1_1basic__permutation.html +++ b/classstdex_1_1parser_1_1basic__permutation.html @@ -222,7 +222,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__phone__number-members.html b/classstdex_1_1parser_1_1basic__phone__number-members.html index 2a00158a4..d7ff4a56e 100644 --- a/classstdex_1_1parser_1_1basic__phone__number-members.html +++ b/classstdex_1_1parser_1_1basic__phone__number-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__phone__number.html b/classstdex_1_1parser_1_1basic__phone__number.html index b66e17656..3caf24168 100644 --- a/classstdex_1_1parser_1_1basic__phone__number.html +++ b/classstdex_1_1parser_1_1basic__phone__number.html @@ -252,7 +252,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__punct__cu-members.html b/classstdex_1_1parser_1_1basic__punct__cu-members.html index 395fe1727..76ac40a1b 100644 --- a/classstdex_1_1parser_1_1basic__punct__cu-members.html +++ b/classstdex_1_1parser_1_1basic__punct__cu-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__punct__cu.html b/classstdex_1_1parser_1_1basic__punct__cu.html index 6ddaba36a..8c6d71a9a 100644 --- a/classstdex_1_1parser_1_1basic__punct__cu.html +++ b/classstdex_1_1parser_1_1basic__punct__cu.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__roman__numeral-members.html b/classstdex_1_1parser_1_1basic__roman__numeral-members.html index bdf921748..898b9c25e 100644 --- a/classstdex_1_1parser_1_1basic__roman__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__roman__numeral-members.html @@ -103,7 +103,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__roman__numeral.html b/classstdex_1_1parser_1_1basic__roman__numeral.html index 79c50102f..a36e248a4 100644 --- a/classstdex_1_1parser_1_1basic__roman__numeral.html +++ b/classstdex_1_1parser_1_1basic__roman__numeral.html @@ -237,7 +237,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__scientific__numeral-members.html b/classstdex_1_1parser_1_1basic__scientific__numeral-members.html index 710143c87..3593c4592 100644 --- a/classstdex_1_1parser_1_1basic__scientific__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__scientific__numeral-members.html @@ -103,7 +103,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__scientific__numeral.html b/classstdex_1_1parser_1_1basic__scientific__numeral.html index b0983d089..eb89cbca6 100644 --- a/classstdex_1_1parser_1_1basic__scientific__numeral.html +++ b/classstdex_1_1parser_1_1basic__scientific__numeral.html @@ -273,7 +273,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__score-members.html b/classstdex_1_1parser_1_1basic__score-members.html index f84f8f3ba..075b0a7ba 100644 --- a/classstdex_1_1parser_1_1basic__score-members.html +++ b/classstdex_1_1parser_1_1basic__score-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__score.html b/classstdex_1_1parser_1_1basic__score.html index f26f58c65..a06886d85 100644 --- a/classstdex_1_1parser_1_1basic__score.html +++ b/classstdex_1_1parser_1_1basic__score.html @@ -242,7 +242,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__sequence-members.html b/classstdex_1_1parser_1_1basic__sequence-members.html index 805f4e4b0..61caed691 100644 --- a/classstdex_1_1parser_1_1basic__sequence-members.html +++ b/classstdex_1_1parser_1_1basic__sequence-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__sequence.html b/classstdex_1_1parser_1_1basic__sequence.html index 3ea16917c..a16c8d959 100644 --- a/classstdex_1_1parser_1_1basic__sequence.html +++ b/classstdex_1_1parser_1_1basic__sequence.html @@ -215,7 +215,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__set-members.html b/classstdex_1_1parser_1_1basic__set-members.html index fc8b9eb12..58af4d856 100644 --- a/classstdex_1_1parser_1_1basic__set-members.html +++ b/classstdex_1_1parser_1_1basic__set-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__set.html b/classstdex_1_1parser_1_1basic__set.html index 2ac64f839..ccb5a37c7 100644 --- a/classstdex_1_1parser_1_1basic__set.html +++ b/classstdex_1_1parser_1_1basic__set.html @@ -229,7 +229,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__signed__numeral-members.html b/classstdex_1_1parser_1_1basic__signed__numeral-members.html index ada1722a3..c11ead5bc 100644 --- a/classstdex_1_1parser_1_1basic__signed__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__signed__numeral-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__signed__numeral.html b/classstdex_1_1parser_1_1basic__signed__numeral.html index 3c7388e71..830e69bff 100644 --- a/classstdex_1_1parser_1_1basic__signed__numeral.html +++ b/classstdex_1_1parser_1_1basic__signed__numeral.html @@ -245,7 +245,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__space__cu-members.html b/classstdex_1_1parser_1_1basic__space__cu-members.html index 523250b33..bbced6ef6 100644 --- a/classstdex_1_1parser_1_1basic__space__cu-members.html +++ b/classstdex_1_1parser_1_1basic__space__cu-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__space__cu.html b/classstdex_1_1parser_1_1basic__space__cu.html index bba4de342..0bbfc6cca 100644 --- a/classstdex_1_1parser_1_1basic__space__cu.html +++ b/classstdex_1_1parser_1_1basic__space__cu.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html b/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html index b018e9bcd..26ff8d79f 100644 --- a/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html +++ b/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__space__or__punct__cu.html b/classstdex_1_1parser_1_1basic__space__or__punct__cu.html index a6488facd..f37c3adc6 100644 --- a/classstdex_1_1parser_1_1basic__space__or__punct__cu.html +++ b/classstdex_1_1parser_1_1basic__space__or__punct__cu.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__string-members.html b/classstdex_1_1parser_1_1basic__string-members.html index 6a7a434bc..91777f24e 100644 --- a/classstdex_1_1parser_1_1basic__string-members.html +++ b/classstdex_1_1parser_1_1basic__string-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__string.html b/classstdex_1_1parser_1_1basic__string.html index da8cfdb21..735c84bba 100644 --- a/classstdex_1_1parser_1_1basic__string.html +++ b/classstdex_1_1parser_1_1basic__string.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__string__branch-members.html b/classstdex_1_1parser_1_1basic__string__branch-members.html index 0de76ed0b..9bbf3b6d5 100644 --- a/classstdex_1_1parser_1_1basic__string__branch-members.html +++ b/classstdex_1_1parser_1_1basic__string__branch-members.html @@ -104,7 +104,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__string__branch.html b/classstdex_1_1parser_1_1basic__string__branch.html index f48e111a3..dc92e0786 100644 --- a/classstdex_1_1parser_1_1basic__string__branch.html +++ b/classstdex_1_1parser_1_1basic__string__branch.html @@ -193,7 +193,7 @@ class stdex::parser::basic_string_branch< T, T_parser >

Test for a

diff --git a/classstdex_1_1parser_1_1basic__time-members.html b/classstdex_1_1parser_1_1basic__time-members.html index 4c9aa8f9e..683bbb9c5 100644 --- a/classstdex_1_1parser_1_1basic__time-members.html +++ b/classstdex_1_1parser_1_1basic__time-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__time.html b/classstdex_1_1parser_1_1basic__time.html index c5a5e8631..84574003d 100644 --- a/classstdex_1_1parser_1_1basic__time.html +++ b/classstdex_1_1parser_1_1basic__time.html @@ -248,7 +248,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url-members.html b/classstdex_1_1parser_1_1basic__url-members.html index 7795cfc8a..9561f5bf0 100644 --- a/classstdex_1_1parser_1_1basic__url-members.html +++ b/classstdex_1_1parser_1_1basic__url-members.html @@ -108,7 +108,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url.html b/classstdex_1_1parser_1_1basic__url.html index fc55a5211..d69242a3f 100644 --- a/classstdex_1_1parser_1_1basic__url.html +++ b/classstdex_1_1parser_1_1basic__url.html @@ -278,7 +278,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url__password__char-members.html b/classstdex_1_1parser_1_1basic__url__password__char-members.html index 78b97fb5d..febac401c 100644 --- a/classstdex_1_1parser_1_1basic__url__password__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__password__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__password__char.html b/classstdex_1_1parser_1_1basic__url__password__char.html index 733bf0391..abd925855 100644 --- a/classstdex_1_1parser_1_1basic__url__password__char.html +++ b/classstdex_1_1parser_1_1basic__url__password__char.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url__path-members.html b/classstdex_1_1parser_1_1basic__url__path-members.html index 121a96e66..1ae80dfa7 100644 --- a/classstdex_1_1parser_1_1basic__url__path-members.html +++ b/classstdex_1_1parser_1_1basic__url__path-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__path.html b/classstdex_1_1parser_1_1basic__url__path.html index b623828d5..9de2fd6fa 100644 --- a/classstdex_1_1parser_1_1basic__url__path.html +++ b/classstdex_1_1parser_1_1basic__url__path.html @@ -248,7 +248,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url__path__char-members.html b/classstdex_1_1parser_1_1basic__url__path__char-members.html index ebce3a81a..76170b9ce 100644 --- a/classstdex_1_1parser_1_1basic__url__path__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__path__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__path__char.html b/classstdex_1_1parser_1_1basic__url__path__char.html index b56462f30..93b4ed4cb 100644 --- a/classstdex_1_1parser_1_1basic__url__path__char.html +++ b/classstdex_1_1parser_1_1basic__url__path__char.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url__username__char-members.html b/classstdex_1_1parser_1_1basic__url__username__char-members.html index af16eadc4..d35484b32 100644 --- a/classstdex_1_1parser_1_1basic__url__username__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__username__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__username__char.html b/classstdex_1_1parser_1_1basic__url__username__char.html index b6eff0cb7..5db1a43f3 100644 --- a/classstdex_1_1parser_1_1basic__url__username__char.html +++ b/classstdex_1_1parser_1_1basic__url__username__char.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1http__agent-members.html b/classstdex_1_1parser_1_1http__agent-members.html index 206773771..556885dfe 100644 --- a/classstdex_1_1parser_1_1http__agent-members.html +++ b/classstdex_1_1parser_1_1http__agent-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__agent.html b/classstdex_1_1parser_1_1http__agent.html index bde864532..17ed579f6 100644 --- a/classstdex_1_1parser_1_1http__agent.html +++ b/classstdex_1_1parser_1_1http__agent.html @@ -226,7 +226,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__any__type-members.html b/classstdex_1_1parser_1_1http__any__type-members.html index ebbf55a0a..aa37de904 100644 --- a/classstdex_1_1parser_1_1http__any__type-members.html +++ b/classstdex_1_1parser_1_1http__any__type-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__any__type.html b/classstdex_1_1parser_1_1http__any__type.html index f7ff8979e..b6ee47feb 100644 --- a/classstdex_1_1parser_1_1http__any__type.html +++ b/classstdex_1_1parser_1_1http__any__type.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__asterisk-members.html b/classstdex_1_1parser_1_1http__asterisk-members.html index 4069f36b7..ec1f45f5d 100644 --- a/classstdex_1_1parser_1_1http__asterisk-members.html +++ b/classstdex_1_1parser_1_1http__asterisk-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__asterisk.html b/classstdex_1_1parser_1_1http__asterisk.html index 2aa8cd25b..f5e17f3f9 100644 --- a/classstdex_1_1parser_1_1http__asterisk.html +++ b/classstdex_1_1parser_1_1http__asterisk.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__cookie-members.html b/classstdex_1_1parser_1_1http__cookie-members.html index a550b3779..1db1a92e7 100644 --- a/classstdex_1_1parser_1_1http__cookie-members.html +++ b/classstdex_1_1parser_1_1http__cookie-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__cookie.html b/classstdex_1_1parser_1_1http__cookie.html index 5f0c2232b..f6042527d 100644 --- a/classstdex_1_1parser_1_1http__cookie.html +++ b/classstdex_1_1parser_1_1http__cookie.html @@ -236,7 +236,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__cookie__parameter-members.html b/classstdex_1_1parser_1_1http__cookie__parameter-members.html index ccb85311f..646106730 100644 --- a/classstdex_1_1parser_1_1http__cookie__parameter-members.html +++ b/classstdex_1_1parser_1_1http__cookie__parameter-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__cookie__parameter.html b/classstdex_1_1parser_1_1http__cookie__parameter.html index 830b1ce56..18fbaa3e2 100644 --- a/classstdex_1_1parser_1_1http__cookie__parameter.html +++ b/classstdex_1_1parser_1_1http__cookie__parameter.html @@ -230,7 +230,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__header-members.html b/classstdex_1_1parser_1_1http__header-members.html index 8d2813d44..2e9c97aac 100644 --- a/classstdex_1_1parser_1_1http__header-members.html +++ b/classstdex_1_1parser_1_1http__header-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__header.html b/classstdex_1_1parser_1_1http__header.html index 7dd1fdfcc..243c76575 100644 --- a/classstdex_1_1parser_1_1http__header.html +++ b/classstdex_1_1parser_1_1http__header.html @@ -230,7 +230,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__language-members.html b/classstdex_1_1parser_1_1http__language-members.html index ffc3262fc..acded5e8e 100644 --- a/classstdex_1_1parser_1_1http__language-members.html +++ b/classstdex_1_1parser_1_1http__language-members.html @@ -87,7 +87,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__language.html b/classstdex_1_1parser_1_1http__language.html index 1f5b90061..e2d4e2b2f 100644 --- a/classstdex_1_1parser_1_1http__language.html +++ b/classstdex_1_1parser_1_1http__language.html @@ -223,7 +223,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__line__break-members.html b/classstdex_1_1parser_1_1http__line__break-members.html index f560edcef..46720166d 100644 --- a/classstdex_1_1parser_1_1http__line__break-members.html +++ b/classstdex_1_1parser_1_1http__line__break-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__line__break.html b/classstdex_1_1parser_1_1http__line__break.html index 96167bedf..60a4da34f 100644 --- a/classstdex_1_1parser_1_1http__line__break.html +++ b/classstdex_1_1parser_1_1http__line__break.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__media__range-members.html b/classstdex_1_1parser_1_1http__media__range-members.html index 4b6a65ad7..b1edbea55 100644 --- a/classstdex_1_1parser_1_1http__media__range-members.html +++ b/classstdex_1_1parser_1_1http__media__range-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__media__range.html b/classstdex_1_1parser_1_1http__media__range.html index 67ba3568d..8ca0b2633 100644 --- a/classstdex_1_1parser_1_1http__media__range.html +++ b/classstdex_1_1parser_1_1http__media__range.html @@ -231,7 +231,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__media__type-members.html b/classstdex_1_1parser_1_1http__media__type-members.html index d1c447d4c..98d8465c3 100644 --- a/classstdex_1_1parser_1_1http__media__type-members.html +++ b/classstdex_1_1parser_1_1http__media__type-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__media__type.html b/classstdex_1_1parser_1_1http__media__type.html index caa4211ea..1ad4601bf 100644 --- a/classstdex_1_1parser_1_1http__media__type.html +++ b/classstdex_1_1parser_1_1http__media__type.html @@ -239,7 +239,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__parameter-members.html b/classstdex_1_1parser_1_1http__parameter-members.html index b261231ff..bcd94b5c4 100644 --- a/classstdex_1_1parser_1_1http__parameter-members.html +++ b/classstdex_1_1parser_1_1http__parameter-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__parameter.html b/classstdex_1_1parser_1_1http__parameter.html index f8f8a77c6..16f73e18d 100644 --- a/classstdex_1_1parser_1_1http__parameter.html +++ b/classstdex_1_1parser_1_1http__parameter.html @@ -232,7 +232,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__protocol-members.html b/classstdex_1_1parser_1_1http__protocol-members.html index aa09f419c..5a216b699 100644 --- a/classstdex_1_1parser_1_1http__protocol-members.html +++ b/classstdex_1_1parser_1_1http__protocol-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__protocol.html b/classstdex_1_1parser_1_1http__protocol.html index 2d12dbb1c..ff94cc581 100644 --- a/classstdex_1_1parser_1_1http__protocol.html +++ b/classstdex_1_1parser_1_1http__protocol.html @@ -236,7 +236,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__quoted__string-members.html b/classstdex_1_1parser_1_1http__quoted__string-members.html index dfed67d2a..d7b37b810 100644 --- a/classstdex_1_1parser_1_1http__quoted__string-members.html +++ b/classstdex_1_1parser_1_1http__quoted__string-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__quoted__string.html b/classstdex_1_1parser_1_1http__quoted__string.html index 7e986148d..f2272f8a1 100644 --- a/classstdex_1_1parser_1_1http__quoted__string.html +++ b/classstdex_1_1parser_1_1http__quoted__string.html @@ -228,7 +228,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__request-members.html b/classstdex_1_1parser_1_1http__request-members.html index dc4403e92..a9842745d 100644 --- a/classstdex_1_1parser_1_1http__request-members.html +++ b/classstdex_1_1parser_1_1http__request-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__request.html b/classstdex_1_1parser_1_1http__request.html index d8112217f..be242b8a6 100644 --- a/classstdex_1_1parser_1_1http__request.html +++ b/classstdex_1_1parser_1_1http__request.html @@ -236,7 +236,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__space-members.html b/classstdex_1_1parser_1_1http__space-members.html index 02a9a1f45..0c9c94274 100644 --- a/classstdex_1_1parser_1_1http__space-members.html +++ b/classstdex_1_1parser_1_1http__space-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__space.html b/classstdex_1_1parser_1_1http__space.html index fdc622270..584583acf 100644 --- a/classstdex_1_1parser_1_1http__space.html +++ b/classstdex_1_1parser_1_1http__space.html @@ -194,7 +194,7 @@ Additional Inherited Members diff --git a/classstdex_1_1parser_1_1http__text__char-members.html b/classstdex_1_1parser_1_1http__text__char-members.html index d001d7276..4e364189f 100644 --- a/classstdex_1_1parser_1_1http__text__char-members.html +++ b/classstdex_1_1parser_1_1http__text__char-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__text__char.html b/classstdex_1_1parser_1_1http__text__char.html index 0b7354315..3e0ea9ab3 100644 --- a/classstdex_1_1parser_1_1http__text__char.html +++ b/classstdex_1_1parser_1_1http__text__char.html @@ -194,7 +194,7 @@ Additional Inherited Members diff --git a/classstdex_1_1parser_1_1http__token-members.html b/classstdex_1_1parser_1_1http__token-members.html index e762260a7..137fd4c94 100644 --- a/classstdex_1_1parser_1_1http__token-members.html +++ b/classstdex_1_1parser_1_1http__token-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__token.html b/classstdex_1_1parser_1_1http__token.html index 756611184..2b7cdbe71 100644 --- a/classstdex_1_1parser_1_1http__token.html +++ b/classstdex_1_1parser_1_1http__token.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url-members.html b/classstdex_1_1parser_1_1http__url-members.html index 22caa73cf..688a326d1 100644 --- a/classstdex_1_1parser_1_1http__url-members.html +++ b/classstdex_1_1parser_1_1http__url-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url.html b/classstdex_1_1parser_1_1http__url.html index 3ee0d56ec..4c3bef587 100644 --- a/classstdex_1_1parser_1_1http__url.html +++ b/classstdex_1_1parser_1_1http__url.html @@ -235,7 +235,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__parameter-members.html b/classstdex_1_1parser_1_1http__url__parameter-members.html index cd616ec4d..08f7788f5 100644 --- a/classstdex_1_1parser_1_1http__url__parameter-members.html +++ b/classstdex_1_1parser_1_1http__url__parameter-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__parameter.html b/classstdex_1_1parser_1_1http__url__parameter.html index b61f7a1d4..f4233a50f 100644 --- a/classstdex_1_1parser_1_1http__url__parameter.html +++ b/classstdex_1_1parser_1_1http__url__parameter.html @@ -226,7 +226,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__path-members.html b/classstdex_1_1parser_1_1http__url__path-members.html index db0632cd8..fa3a7d093 100644 --- a/classstdex_1_1parser_1_1http__url__path-members.html +++ b/classstdex_1_1parser_1_1http__url__path-members.html @@ -87,7 +87,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__path.html b/classstdex_1_1parser_1_1http__url__path.html index 61fb59b19..20b53d534 100644 --- a/classstdex_1_1parser_1_1http__url__path.html +++ b/classstdex_1_1parser_1_1http__url__path.html @@ -224,7 +224,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__path__segment-members.html b/classstdex_1_1parser_1_1http__url__path__segment-members.html index 646d90a49..aaf7afe6d 100644 --- a/classstdex_1_1parser_1_1http__url__path__segment-members.html +++ b/classstdex_1_1parser_1_1http__url__path__segment-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__path__segment.html b/classstdex_1_1parser_1_1http__url__path__segment.html index 31ba425b3..2db14d7c8 100644 --- a/classstdex_1_1parser_1_1http__url__path__segment.html +++ b/classstdex_1_1parser_1_1http__url__path__segment.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__port-members.html b/classstdex_1_1parser_1_1http__url__port-members.html index d7da06d29..a400c610a 100644 --- a/classstdex_1_1parser_1_1http__url__port-members.html +++ b/classstdex_1_1parser_1_1http__url__port-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__port.html b/classstdex_1_1parser_1_1http__url__port.html index 801bceaca..01feb9305 100644 --- a/classstdex_1_1parser_1_1http__url__port.html +++ b/classstdex_1_1parser_1_1http__url__port.html @@ -226,7 +226,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__server-members.html b/classstdex_1_1parser_1_1http__url__server-members.html index d23f30496..e19a9911e 100644 --- a/classstdex_1_1parser_1_1http__url__server-members.html +++ b/classstdex_1_1parser_1_1http__url__server-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__server.html b/classstdex_1_1parser_1_1http__url__server.html index eee96cbf3..376e0d161 100644 --- a/classstdex_1_1parser_1_1http__url__server.html +++ b/classstdex_1_1parser_1_1http__url__server.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__value-members.html b/classstdex_1_1parser_1_1http__value-members.html index 0c94931d2..3c30be4fe 100644 --- a/classstdex_1_1parser_1_1http__value-members.html +++ b/classstdex_1_1parser_1_1http__value-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__value.html b/classstdex_1_1parser_1_1http__value.html index c3c830b91..d56ae3cea 100644 --- a/classstdex_1_1parser_1_1http__value.html +++ b/classstdex_1_1parser_1_1http__value.html @@ -228,7 +228,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__value__collection-members.html b/classstdex_1_1parser_1_1http__value__collection-members.html index 6b1db5cf5..60d55471f 100644 --- a/classstdex_1_1parser_1_1http__value__collection-members.html +++ b/classstdex_1_1parser_1_1http__value__collection-members.html @@ -84,7 +84,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__value__collection.html b/classstdex_1_1parser_1_1http__value__collection.html index 936f8ada5..aee9ac530 100644 --- a/classstdex_1_1parser_1_1http__value__collection.html +++ b/classstdex_1_1parser_1_1http__value__collection.html @@ -107,7 +107,7 @@ class stdex::parser::http_value_collection< T >

Collection of HTTP

diff --git a/classstdex_1_1parser_1_1http__weight-members.html b/classstdex_1_1parser_1_1http__weight-members.html index 6dc25f68b..23491ddd1 100644 --- a/classstdex_1_1parser_1_1http__weight-members.html +++ b/classstdex_1_1parser_1_1http__weight-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__weight.html b/classstdex_1_1parser_1_1http__weight.html index 4acd28d66..053b7049e 100644 --- a/classstdex_1_1parser_1_1http__weight.html +++ b/classstdex_1_1parser_1_1http__weight.html @@ -227,7 +227,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__weighted__value-members.html b/classstdex_1_1parser_1_1http__weighted__value-members.html index 9ba177b03..fe56f5aa5 100644 --- a/classstdex_1_1parser_1_1http__weighted__value-members.html +++ b/classstdex_1_1parser_1_1http__weighted__value-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__weighted__value.html b/classstdex_1_1parser_1_1http__weighted__value.html index c48514184..fc2cf0930 100644 --- a/classstdex_1_1parser_1_1http__weighted__value.html +++ b/classstdex_1_1parser_1_1http__weighted__value.html @@ -237,7 +237,7 @@ template<class T , class T_asterisk = http_asterisk> diff --git a/classstdex_1_1parser_1_1parser__collection-members.html b/classstdex_1_1parser_1_1parser__collection-members.html index 7d5746c86..6546d1ed5 100644 --- a/classstdex_1_1parser_1_1parser__collection-members.html +++ b/classstdex_1_1parser_1_1parser__collection-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1parser__collection.html b/classstdex_1_1parser_1_1parser__collection.html index 57abf1a16..86f2b8b2c 100644 --- a/classstdex_1_1parser_1_1parser__collection.html +++ b/classstdex_1_1parser_1_1parser__collection.html @@ -192,7 +192,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1sgml__any__cp-members.html b/classstdex_1_1parser_1_1sgml__any__cp-members.html index 74829034d..c820e14e5 100644 --- a/classstdex_1_1parser_1_1sgml__any__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__any__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__any__cp.html b/classstdex_1_1parser_1_1sgml__any__cp.html index 246f496b5..a57e67749 100644 --- a/classstdex_1_1parser_1_1sgml__any__cp.html +++ b/classstdex_1_1parser_1_1sgml__any__cp.html @@ -199,7 +199,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__cp-members.html b/classstdex_1_1parser_1_1sgml__cp-members.html index 16c7f7402..fc063078e 100644 --- a/classstdex_1_1parser_1_1sgml__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__cp-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__cp.html b/classstdex_1_1parser_1_1sgml__cp.html index f6f80fedb..d70a53986 100644 --- a/classstdex_1_1parser_1_1sgml__cp.html +++ b/classstdex_1_1parser_1_1sgml__cp.html @@ -200,7 +200,7 @@ Additional Inherited Members diff --git a/classstdex_1_1parser_1_1sgml__cp__set-members.html b/classstdex_1_1parser_1_1sgml__cp__set-members.html index 4c6e3a421..37a2a4b3e 100644 --- a/classstdex_1_1parser_1_1sgml__cp__set-members.html +++ b/classstdex_1_1parser_1_1sgml__cp__set-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__cp__set.html b/classstdex_1_1parser_1_1sgml__cp__set.html index e38324d55..4394bfd7e 100644 --- a/classstdex_1_1parser_1_1sgml__cp__set.html +++ b/classstdex_1_1parser_1_1sgml__cp__set.html @@ -216,7 +216,7 @@ size_t hit_offset diff --git a/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html b/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html index a0c27550c..9af7e77aa 100644 --- a/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html +++ b/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__dns__domain__char.html b/classstdex_1_1parser_1_1sgml__dns__domain__char.html index 550d506ae..489c8da07 100644 --- a/classstdex_1_1parser_1_1sgml__dns__domain__char.html +++ b/classstdex_1_1parser_1_1sgml__dns__domain__char.html @@ -208,7 +208,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html index 853c8a9ad..7a0edd8c3 100644 --- a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html +++ b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html index a88afac71..80a645416 100644 --- a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html +++ b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html @@ -190,7 +190,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__punct__cp-members.html b/classstdex_1_1parser_1_1sgml__punct__cp-members.html index 9bfd73d9a..f5da96457 100644 --- a/classstdex_1_1parser_1_1sgml__punct__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__punct__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__punct__cp.html b/classstdex_1_1parser_1_1sgml__punct__cp.html index 242068674..7ea8f5cec 100644 --- a/classstdex_1_1parser_1_1sgml__punct__cp.html +++ b/classstdex_1_1parser_1_1sgml__punct__cp.html @@ -203,7 +203,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__space__cp-members.html b/classstdex_1_1parser_1_1sgml__space__cp-members.html index fd07bc873..3bf9b55d8 100644 --- a/classstdex_1_1parser_1_1sgml__space__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__space__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__space__cp.html b/classstdex_1_1parser_1_1sgml__space__cp.html index 3e5a310a3..829c41f7d 100644 --- a/classstdex_1_1parser_1_1sgml__space__cp.html +++ b/classstdex_1_1parser_1_1sgml__space__cp.html @@ -203,7 +203,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html b/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html index 14ff580a6..5a014ab3a 100644 --- a/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html b/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html index 493971384..2b2815d22 100644 --- a/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html +++ b/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html @@ -203,7 +203,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__string-members.html b/classstdex_1_1parser_1_1sgml__string-members.html index f0ceb68ae..5ad2dd2e2 100644 --- a/classstdex_1_1parser_1_1sgml__string-members.html +++ b/classstdex_1_1parser_1_1sgml__string-members.html @@ -87,7 +87,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__string.html b/classstdex_1_1parser_1_1sgml__string.html index 050e80ac2..3befa3195 100644 --- a/classstdex_1_1parser_1_1sgml__string.html +++ b/classstdex_1_1parser_1_1sgml__string.html @@ -197,7 +197,7 @@ Additional Inherited Members diff --git a/classstdex_1_1parser_1_1sgml__url__password__char-members.html b/classstdex_1_1parser_1_1sgml__url__password__char-members.html index 1349cce7c..89d00d79d 100644 --- a/classstdex_1_1parser_1_1sgml__url__password__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__password__char-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__url__password__char.html b/classstdex_1_1parser_1_1sgml__url__password__char.html index 9ca5b2f48..6cb831f89 100644 --- a/classstdex_1_1parser_1_1sgml__url__password__char.html +++ b/classstdex_1_1parser_1_1sgml__url__password__char.html @@ -199,7 +199,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__url__path__char-members.html b/classstdex_1_1parser_1_1sgml__url__path__char-members.html index f7ecdd68c..405bb4620 100644 --- a/classstdex_1_1parser_1_1sgml__url__path__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__path__char-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__url__path__char.html b/classstdex_1_1parser_1_1sgml__url__path__char.html index 0c1837367..20b3d917a 100644 --- a/classstdex_1_1parser_1_1sgml__url__path__char.html +++ b/classstdex_1_1parser_1_1sgml__url__path__char.html @@ -199,7 +199,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__url__username__char-members.html b/classstdex_1_1parser_1_1sgml__url__username__char-members.html index 31b11931c..0f0bdd3ab 100644 --- a/classstdex_1_1parser_1_1sgml__url__username__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__username__char-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__url__username__char.html b/classstdex_1_1parser_1_1sgml__url__username__char.html index 49edabaf0..15cfe9dcc 100644 --- a/classstdex_1_1parser_1_1sgml__url__username__char.html +++ b/classstdex_1_1parser_1_1sgml__url__username__char.html @@ -199,7 +199,7 @@ std::locale m_locale diff --git a/classstdex_1_1progress-members.html b/classstdex_1_1progress-members.html index df5c69cc8..7fa8920a9 100644 --- a/classstdex_1_1progress-members.html +++ b/classstdex_1_1progress-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1progress.html b/classstdex_1_1progress.html index 1e15915db..f42375658 100644 --- a/classstdex_1_1progress.html +++ b/classstdex_1_1progress.html @@ -319,7 +319,7 @@ template<class T > diff --git a/classstdex_1_1progress__switcher-members.html b/classstdex_1_1progress__switcher-members.html index 1347103fc..eb6ae9a2b 100644 --- a/classstdex_1_1progress__switcher-members.html +++ b/classstdex_1_1progress__switcher-members.html @@ -100,7 +100,7 @@ $(function() { diff --git a/classstdex_1_1progress__switcher.html b/classstdex_1_1progress__switcher.html index 4ecefae7b..86fa64375 100644 --- a/classstdex_1_1progress__switcher.html +++ b/classstdex_1_1progress__switcher.html @@ -178,7 +178,7 @@ class stdex::progress_switcher< T >

Progress indicator switcher. <

diff --git a/classstdex_1_1user__cancelled-members.html b/classstdex_1_1user__cancelled-members.html index 05b83c840..da1bb70c1 100644 --- a/classstdex_1_1user__cancelled-members.html +++ b/classstdex_1_1user__cancelled-members.html @@ -84,7 +84,7 @@ $(function() { diff --git a/classstdex_1_1user__cancelled.html b/classstdex_1_1user__cancelled.html index 63b7684ad..3bdc7d399 100644 --- a/classstdex_1_1user__cancelled.html +++ b/classstdex_1_1user__cancelled.html @@ -141,7 +141,7 @@ Public Member Functions diff --git a/classstdex_1_1vector__queue-members.html b/classstdex_1_1vector__queue-members.html index cc3567d21..6530338b0 100644 --- a/classstdex_1_1vector__queue-members.html +++ b/classstdex_1_1vector__queue-members.html @@ -122,7 +122,7 @@ $(function() { diff --git a/classstdex_1_1vector__queue.html b/classstdex_1_1vector__queue.html index cde233047..e8a332e40 100644 --- a/classstdex_1_1vector__queue.html +++ b/classstdex_1_1vector__queue.html @@ -795,7 +795,7 @@ template<class T > diff --git a/dir_4be4f7b278e009bf0f1906cf31fb73bd.html b/dir_4be4f7b278e009bf0f1906cf31fb73bd.html index b4701de9e..9987ad0c9 100644 --- a/dir_4be4f7b278e009bf0f1906cf31fb73bd.html +++ b/dir_4be4f7b278e009bf0f1906cf31fb73bd.html @@ -86,7 +86,7 @@ Files diff --git a/dir_d44c64559bbebec7f509842c48db8b23.html b/dir_d44c64559bbebec7f509842c48db8b23.html index d92f08b84..8e745c276 100644 --- a/dir_d44c64559bbebec7f509842c48db8b23.html +++ b/dir_d44c64559bbebec7f509842c48db8b23.html @@ -86,7 +86,7 @@ Directories diff --git a/dir_fca3c47b2ea228727bd6729832f89576.html b/dir_fca3c47b2ea228727bd6729832f89576.html index a0c8f2147..3e0f781e9 100644 --- a/dir_fca3c47b2ea228727bd6729832f89576.html +++ b/dir_fca3c47b2ea228727bd6729832f89576.html @@ -116,7 +116,7 @@ Files diff --git a/errno_8hpp_source.html b/errno_8hpp_source.html index ddfe4189d..7202b5da8 100644 --- a/errno_8hpp_source.html +++ b/errno_8hpp_source.html @@ -136,7 +136,7 @@ $(function() { diff --git a/exception_8hpp_source.html b/exception_8hpp_source.html index c9da09ba4..8d40b3183 100644 --- a/exception_8hpp_source.html +++ b/exception_8hpp_source.html @@ -102,7 +102,7 @@ $(function() { diff --git a/files.html b/files.html index 78c86310a..15ec4a3e2 100644 --- a/files.html +++ b/files.html @@ -100,7 +100,7 @@ $(function() { diff --git a/functions.html b/functions.html index 320326dc8..d5095a529 100644 --- a/functions.html +++ b/functions.html @@ -256,7 +256,7 @@ $(function() { diff --git a/functions_func.html b/functions_func.html index 963e51d90..cb86b7441 100644 --- a/functions_func.html +++ b/functions_func.html @@ -205,7 +205,7 @@ $(function() { diff --git a/functions_type.html b/functions_type.html index 2839b0f68..ed3f94c44 100644 --- a/functions_type.html +++ b/functions_type.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_vars.html b/functions_vars.html index 02b9d05f7..5ee53a068 100644 --- a/functions_vars.html +++ b/functions_vars.html @@ -176,7 +176,7 @@ $(function() { diff --git a/hex_8hpp_source.html b/hex_8hpp_source.html index 266f1cc2c..3afdf1052 100644 --- a/hex_8hpp_source.html +++ b/hex_8hpp_source.html @@ -209,7 +209,7 @@ $(function() { diff --git a/hierarchy.html b/hierarchy.html index 93317c97c..fc5e10ad7 100644 --- a/hierarchy.html +++ b/hierarchy.html @@ -197,7 +197,7 @@ $(function() { diff --git a/idrec_8hpp_source.html b/idrec_8hpp_source.html index 92dfd17a7..104754702 100644 --- a/idrec_8hpp_source.html +++ b/idrec_8hpp_source.html @@ -275,7 +275,7 @@ $(function() { diff --git a/index.html b/index.html index 2b04a20f0..85b42664a 100644 --- a/index.html +++ b/index.html @@ -76,7 +76,7 @@ $(function() { diff --git a/interval_8hpp_source.html b/interval_8hpp_source.html index 7730f0561..6bb4af122 100644 --- a/interval_8hpp_source.html +++ b/interval_8hpp_source.html @@ -128,7 +128,7 @@ $(function() { diff --git a/mapping_8hpp_source.html b/mapping_8hpp_source.html index 04770c7e8..d27baf401 100644 --- a/mapping_8hpp_source.html +++ b/mapping_8hpp_source.html @@ -117,7 +117,7 @@ $(function() { diff --git a/memory_8hpp_source.html b/memory_8hpp_source.html index facb63e35..0c353c91c 100644 --- a/memory_8hpp_source.html +++ b/memory_8hpp_source.html @@ -119,7 +119,7 @@ $(function() { diff --git a/parser_8hpp_source.html b/parser_8hpp_source.html index e8ad15186..7576352fa 100644 --- a/parser_8hpp_source.html +++ b/parser_8hpp_source.html @@ -92,6458 +92,6460 @@ $(function() {
13#include <assert.h>
14#include <stdarg.h>
15#include <stdint.h>
-
16#include <limits>
-
17#include <list>
-
18#include <memory>
-
19#include <set>
-
20#include <string>
-
21#ifdef _WIN32
-
22#include <winsock2.h>
-
23#else
-
24#include <inaddr.h>
-
25#include <in6addr.h>
-
26#endif
-
27
-
28#ifdef _MSC_VER
-
29#pragma warning(push)
-
30#pragma warning(disable: 4100)
-
31#endif
-
32
-
33#define ENUM_FLAG_OPERATOR(T,X) \
-
34inline T operator X (const T lhs, const T rhs) { return static_cast<T>(static_cast<std::underlying_type_t<T>>(lhs) X static_cast<std::underlying_type_t<T>>(rhs)); } \
-
35inline T operator X (const T lhs, const std::underlying_type_t<T> rhs) { return static_cast<T>(static_cast<std::underlying_type_t<T>>(lhs) X rhs); } \
-
36inline T operator X (const std::underlying_type_t<T> lhs, const T rhs) { return static_cast<T>(lhs X static_cast<std::underlying_type_t<T>>(rhs)); } \
-
37inline T& operator X= (T& lhs, const T rhs) { return lhs = lhs X rhs; } \
-
38inline T& operator X= (T& lhs, const std::underlying_type_t<T> rhs) { return lhs = lhs X rhs; }
-
39#define ENUM_FLAGS(T, type) \
-
40enum class T : type; \
-
41inline T operator ~ (T t) { return (T) (~static_cast<std::underlying_type_t <T>>(t)); } \
-
42ENUM_FLAG_OPERATOR(T,|) \
-
43ENUM_FLAG_OPERATOR(T,^) \
-
44ENUM_FLAG_OPERATOR(T,&) \
-
45enum class T : type
-
46
-
47namespace stdex
-
48{
-
49 namespace parser
-
50 {
-
54 constexpr int match_default = 0;
-
55 constexpr int match_case_insensitive = 0x1;
-
56 constexpr int match_multiline = 0x2;
-
57
-
61 template <class T>
-
62 class basic_parser
-
63 {
-
64 public:
-
65 basic_parser(_In_ const std::locale& locale = std::locale()) : m_locale(locale) {}
-
66 virtual ~basic_parser() {}
-
67
-
68 bool search(
-
69 _In_reads_or_z_(end) const T* text,
-
70 _In_ size_t start = 0,
-
71 _In_ size_t end = (size_t)-1,
-
72 _In_ int flags = match_default)
-
73 {
-
74 for (size_t i = start; i < end && text[i]; i++)
-
75 if (match(text, i, end, flags))
-
76 return true;
-
77 return false;
-
78 }
-
79
-
80 virtual bool match(
-
81 _In_reads_or_z_(end) const T* text,
-
82 _In_ size_t start = 0,
-
83 _In_ size_t end = (size_t)-1,
-
84 _In_ int flags = match_default) = 0;
-
85
-
86 template<class _Traits, class _Ax>
-
87 inline bool match(
-
88 const std::basic_string<T, _Traits, _Ax>& text,
-
89 _In_ size_t start = 0,
-
90 _In_ size_t end = (size_t)-1,
-
91 _In_ int flags = match_default)
-
92 {
-
93 return match(text.c_str(), start, std::min<size_t>(end, text.size()), flags);
-
94 }
-
95
-
96 virtual void invalidate()
-
97 {
-
98 interval.start = 1;
-
99 interval.end = 0;
-
100 }
-
101
-
102 protected:
-
104 const wchar_t* next_sgml_cp(_In_ const char* text, _In_ size_t start, _In_ size_t end, _Out_ size_t& chr_end, _Out_ wchar_t(&buf)[3])
-
105 {
-
106 if (text[start] == '&') {
-
107 // Potential entity start
-
108 const auto& ctype = std::use_facet<std::ctype<T>>(m_locale);
-
109 for (chr_end = start + 1;; chr_end++) {
-
110 if (chr_end >= end || text[chr_end] == 0) {
-
111 // Unterminated entity
-
112 break;
-
113 }
-
114 if (text[chr_end] == ';') {
-
115 // Entity end
-
116 size_t n = chr_end - start - 1;
-
117 if (n >= 2 && text[start + 1] == '#') {
-
118 // Numerical entity
-
119 char32_t unicode;
-
120 if (text[start + 2] == 'x' || text[start + 2] == 'X')
-
121 unicode = strtou32(text + start + 3, n - 2, nullptr, 16);
-
122 else
-
123 unicode = strtou32(text + start + 2, n - 1, nullptr, 10);
-
124#ifdef _WIN32
-
125 if (unicode < 0x10000) {
-
126 buf[0] = (wchar_t)unicode;
-
127 buf[1] = 0;
-
128 }
-
129 else {
-
130 ucs4_to_surrogate_pair(buf, unicode);
-
131 buf[2] = 0;
-
132 }
-
133#else
-
134 buf[0] = (wchar_t)unicode;
-
135 buf[1] = 0;
-
136#endif
-
137 chr_end++;
-
138 return buf;
-
139 }
-
140 const wchar_t* entity_w = sgml2uni(text + start + 1, n);
-
141 if (entity_w) {
-
142 chr_end++;
-
143 return entity_w;
-
144 }
-
145 // Unknown entity.
-
146 break;
-
147 }
-
148 else if (text[chr_end] == '&' || ctype.is(ctype.space, text[chr_end])) {
-
149 // This char cannot possibly be a part of entity.
-
150 break;
-
151 }
-
152 }
-
153 }
-
154 buf[0] = text[start];
-
155 buf[1] = 0;
-
156 chr_end = start + 1;
-
157 return buf;
-
158 }
-
160
-
161 public:
-
162 interval<size_t> interval;
-
163
-
164 protected:
-
165 std::locale m_locale;
-
166 };
-
167
-
168 using parser = basic_parser<char>;
-
169 using wparser = basic_parser<wchar_t>;
-
170#ifdef _UNICODE
-
171 using tparser = wparser;
-
172#else
-
173 using tparser = parser;
-
174#endif
-
175 using sgml_parser = basic_parser<char>;
-
176
-
180 template <class T>
-
181 class basic_noop : public basic_parser<T>
-
182 {
-
183 public:
-
184 virtual bool match(
-
185 _In_reads_or_z_(end) const T* text,
-
186 _In_ size_t start = 0,
-
187 _In_ size_t end = (size_t)-1,
-
188 _In_ int flags = match_default)
-
189 {
-
190 assert(text || start >= end);
-
191 if (start < end && text[start]) {
-
192 interval.start = interval.end = start;
-
193 return true;
-
194 }
-
195 interval.start = (interval.end = start) + 1;
-
196 return false;
-
197 }
-
198 };
-
199
-
200 using noop = basic_noop<char>;
-
201 using wnoop = basic_noop<wchar_t>;
-
202#ifdef _UNICODE
-
203 using tnoop = wnoop;
-
204#else
-
205 using tnoop = noop;
-
206#endif
-
207 using sgml_noop = basic_noop<char>;
-
208
-
212 template <class T>
-
213 class basic_any_cu : public basic_parser<T>
-
214 {
-
215 public:
-
216 basic_any_cu(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
-
217
-
218 virtual bool match(
-
219 _In_reads_or_z_(end) const T* text,
-
220 _In_ size_t start = 0,
-
221 _In_ size_t end = (size_t)-1,
-
222 _In_ int flags = match_default)
-
223 {
-
224 assert(text || start >= end);
-
225 if (start < end && text[start]) {
-
226 interval.end = (interval.start = start) + 1;
-
227 return true;
-
228 }
-
229 interval.start = (interval.end = start) + 1;
-
230 return false;
-
231 }
-
232 };
-
233
-
234 using any_cu = basic_any_cu<char>;
-
235 using wany_cu = basic_any_cu<wchar_t>;
-
236#ifdef _UNICODE
-
237 using tany_cu = wany_cu;
-
238#else
-
239 using tany_cu = any_cu;
-
240#endif
-
241
-
245 class sgml_any_cp : public basic_any_cu<char>
-
246 {
-
247 public:
-
248 sgml_any_cp(_In_ const std::locale& locale = std::locale()) : basic_any_cu<char>(locale) {}
-
249
-
250 virtual bool match(
-
251 _In_reads_or_z_(end) const char* text,
-
252 _In_ size_t start = 0,
-
253 _In_ size_t end = (size_t)-1,
-
254 _In_ int flags = match_default)
-
255 {
-
256 assert(text || start >= end);
-
257 if (start < end && text[start]) {
-
258 if (text[start] == '&') {
-
259 // SGML entity
-
260 const auto& ctype = std::use_facet<std::ctype<char>>(m_locale);
-
261 for (interval.end = start + 1; interval.end < end && text[interval.end]; interval.end++)
-
262 if (text[interval.end] == ';') {
-
263 interval.end++;
-
264 interval.start = start;
-
265 return true;
-
266 }
-
267 else if (text[interval.end] == '&' || ctype.is(ctype.space, text[interval.end]))
-
268 break;
-
269 // Unterminated entity
-
270 }
-
271 interval.end = (interval.start = start) + 1;
-
272 return true;
-
273 }
-
274 interval.start = (interval.end = start) + 1;
-
275 return false;
-
276 }
-
277 };
-
278
-
282 template <class T>
-
283 class basic_cu : public basic_parser<T>
-
284 {
-
285 public:
-
286 basic_cu(T chr, bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
287 basic_parser<T>(locale),
-
288 m_chr(chr),
-
289 m_invert(invert)
-
290 {}
-
291
-
292 virtual bool match(
-
293 _In_reads_or_z_(end) const T* text,
-
294 _In_ size_t start = 0,
-
295 _In_ size_t end = (size_t)-1,
-
296 _In_ int flags = match_default)
-
297 {
-
298 assert(text || start >= end);
-
299 if (start < end && text[start]) {
-
300 bool r;
-
301 if (flags & match_case_insensitive) {
-
302 const auto& ctype = std::use_facet<std::ctype<T>>(m_locale);
-
303 r = ctype.tolower(text[start]) == ctype.tolower(m_chr);
-
304 }
-
305 else
-
306 r = text[start] == m_chr;
-
307 if (r && !m_invert || !r && m_invert) {
-
308 interval.end = (interval.start = start) + 1;
-
309 return true;
-
310 }
-
311 }
-
312 interval.start = (interval.end = start) + 1;
-
313 return false;
-
314 }
-
315
-
316 protected:
-
317 T m_chr;
-
318 bool m_invert;
-
319 };
-
320
-
321 using cu = basic_cu<char>;
-
322 using wcu = basic_cu<wchar_t>;
-
323#ifdef _UNICODE
-
324 using tcu = wcu;
-
325#else
-
326 using tcu = cu;
-
327#endif
-
328
-
332 class sgml_cp : public sgml_parser
-
333 {
-
334 public:
-
335 sgml_cp(const char* chr, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
336 sgml_parser(locale),
-
337 m_invert(invert)
-
338 {
-
339 assert(chr || !count);
-
340 wchar_t buf[3];
-
341 size_t chr_end;
-
342 m_chr.assign(count ? next_sgml_cp(chr, 0, count, chr_end, buf) : L"");
-
343 }
-
344
-
345 virtual bool match(
-
346 _In_reads_or_z_(end) const char* text,
-
347 _In_ size_t start = 0,
-
348 _In_ size_t end = (size_t)-1,
-
349 _In_ int flags = match_default)
-
350 {
-
351 assert(text || start >= end);
-
352 if (start < end && text[start]) {
-
353 wchar_t buf[3];
-
354 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
355 bool r = ((flags & match_case_insensitive) ?
-
356 stdex::strnicmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size(), m_locale) :
-
357 stdex::strncmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size())) == 0;
-
358 if (r && !m_invert || !r && m_invert) {
-
359 interval.start = start;
-
360 return true;
-
361 }
-
362 }
-
363 interval.start = (interval.end = start) + 1;
-
364 return false;
-
365 }
-
366
-
367 protected:
-
368 std::wstring m_chr;
-
369 bool m_invert;
-
370 };
-
371
-
375 template <class T>
-
376 class basic_space_cu : public basic_parser<T>
-
377 {
-
378 public:
-
379 basic_space_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
380 basic_parser<T>(locale),
-
381 m_invert(invert)
-
382 {}
-
383
-
384 virtual bool match(
-
385 _In_reads_or_z_(end) const T* text,
-
386 _In_ size_t start = 0,
-
387 _In_ size_t end = (size_t)-1,
-
388 _In_ int flags = match_default)
-
389 {
-
390 assert(text || start >= end);
-
391 if (start < end && text[start]) {
-
392 bool r =
-
393 ((flags & match_multiline) || !islbreak(text[start])) &&
-
394 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::space, text[start]);
-
395 if (r && !m_invert || !r && m_invert) {
-
396 interval.end = (interval.start = start) + 1;
-
397 return true;
-
398 }
-
399 }
-
400 interval.start = (interval.end = start) + 1;
-
401 return false;
-
402 }
-
403
-
404 protected:
-
405 bool m_invert;
-
406 };
-
407
-
408 using space_cu = basic_space_cu<char>;
-
409 using wspace_cu = basic_space_cu<wchar_t>;
-
410#ifdef _UNICODE
-
411 using tspace_cu = wspace_cu;
-
412#else
-
413 using tspace_cu = space_cu;
-
414#endif
-
415
-
419 class sgml_space_cp : public basic_space_cu<char>
-
420 {
-
421 public:
-
422 sgml_space_cp(_In_ bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
423 basic_space_cu<char>(invert, locale)
-
424 {}
-
425
-
426 virtual bool match(
-
427 _In_reads_or_z_(end) const char* text,
-
428 _In_ size_t start = 0,
-
429 _In_ size_t end = (size_t)-1,
-
430 _In_ int flags = match_default)
-
431 {
-
432 assert(text || start >= end);
-
433 if (start < end && text[start]) {
-
434 wchar_t buf[3];
-
435 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
436 const wchar_t* chr_end = chr + stdex::strlen(chr);
-
437 bool r =
-
438 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
-
439 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space, chr, chr_end) == chr_end;
-
440 if (r && !m_invert || !r && m_invert) {
-
441 interval.start = start;
-
442 return true;
-
443 }
-
444 }
-
445
-
446 interval.start = (interval.end = start) + 1;
-
447 return false;
-
448 }
-
449 };
-
450
-
454 template <class T>
-
455 class basic_punct_cu : public basic_parser<T>
-
456 {
-
457 public:
-
458 basic_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
459 basic_parser<T>(locale),
-
460 m_invert(invert)
-
461 {}
-
462
-
463 virtual bool match(
-
464 _In_reads_or_z_(end) const T* text,
-
465 _In_ size_t start = 0,
-
466 _In_ size_t end = (size_t)-1,
-
467 _In_ int flags = match_default)
-
468 {
-
469 assert(text || start >= end);
-
470 if (start < end && text[start]) {
-
471 bool r = std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::punct, text[start]);
-
472 if (r && !m_invert || !r && m_invert) {
-
473 interval.end = (interval.start = start) + 1;
-
474 return true;
-
475 }
-
476 }
-
477 interval.start = (interval.end = start) + 1;
-
478 return false;
-
479 }
-
480
-
481 protected:
-
482 bool m_invert;
-
483 };
-
484
-
485 using punct_cu = basic_punct_cu<char>;
-
486 using wpunct_cu = basic_punct_cu<wchar_t>;
-
487#ifdef _UNICODE
-
488 using tpunct_cu = wpunct_cu;
-
489#else
-
490 using tpunct_cu = punct_cu;
-
491#endif
-
492
-
496 class sgml_punct_cp : public basic_punct_cu<char>
-
497 {
-
498 public:
-
499 sgml_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
500 basic_punct_cu<char>(invert, locale)
-
501 {}
-
502
-
503 virtual bool match(
-
504 _In_reads_or_z_(end) const char* text,
-
505 _In_ size_t start = 0,
-
506 _In_ size_t end = (size_t)-1,
-
507 _In_ int flags = match_default)
-
508 {
-
509 assert(text || start >= end);
-
510 if (start < end && text[start]) {
-
511 wchar_t buf[3];
-
512 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
513 const wchar_t* chr_end = chr + stdex::strlen(chr);
-
514 bool r = std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::punct, chr, chr_end) == chr_end;
-
515 if (r && !m_invert || !r && m_invert) {
-
516 interval.start = start;
-
517 return true;
-
518 }
-
519 }
-
520 interval.start = (interval.end = start) + 1;
-
521 return false;
-
522 }
-
523 };
-
524
-
528 template <class T>
-
529 class basic_space_or_punct_cu : public basic_parser<T>
-
530 {
-
531 public:
-
532 basic_space_or_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
533 basic_parser<T>(locale),
-
534 m_invert(invert)
-
535 {}
-
536
-
537 virtual bool match(
-
538 _In_reads_or_z_(end) const T* text,
-
539 _In_ size_t start = 0,
-
540 _In_ size_t end = (size_t)-1,
-
541 _In_ int flags = match_default)
-
542 {
-
543 assert(text || start >= end);
-
544 if (start < end && text[start]) {
-
545 bool r =
-
546 ((flags & match_multiline) || !islbreak(text[start])) &&
-
547 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::space | std::ctype_base::punct, text[start]);
-
548 if (r && !m_invert || !r && m_invert) {
-
549 interval.end = (interval.start = start) + 1;
-
550 return true;
-
551 }
-
552 }
-
553 interval.start = (interval.end = start) + 1;
-
554 return false;
-
555 }
-
556
-
557 protected:
-
558 bool m_invert;
-
559 };
-
560
-
561 using space_or_punct_cu = basic_space_or_punct_cu<char>;
-
562 using wspace_or_punct_cu = basic_space_or_punct_cu<wchar_t>;
-
563#ifdef _UNICODE
-
564 using tspace_or_punct_cu = wspace_or_punct_cu;
-
565#else
-
566 using tspace_or_punct_cu = space_or_punct_cu;
-
567#endif
-
568
-
572 class sgml_space_or_punct_cp : public basic_space_or_punct_cu<char>
-
573 {
-
574 public:
-
575 sgml_space_or_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
576 basic_space_or_punct_cu<char>(invert, locale)
-
577 {}
-
578
-
579 virtual bool match(
-
580 _In_reads_or_z_(end) const char* text,
-
581 _In_ size_t start = 0,
-
582 _In_ size_t end = (size_t)-1,
-
583 _In_ int flags = match_default)
-
584 {
-
585 assert(text || start >= end);
-
586 if (start < end && text[start]) {
-
587 wchar_t buf[3];
-
588 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
589 const wchar_t* chr_end = chr + stdex::strlen(chr);
-
590 bool r =
-
591 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
-
592 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space | std::ctype_base::punct, chr, chr_end) == chr_end;
-
593 if (r && !m_invert || !r && m_invert) {
-
594 interval.start = start;
-
595 return true;
-
596 }
-
597 }
-
598 interval.start = (interval.end = start) + 1;
-
599 return false;
-
600 }
-
601 };
-
602
-
606 template <class T>
-
607 class basic_bol : public basic_parser<T>
-
608 {
-
609 public:
-
610 basic_bol(bool invert = false) : m_invert(invert) {}
-
611
-
612 virtual bool match(
-
613 _In_reads_or_z_(end) const T* text,
-
614 _In_ size_t start = 0,
-
615 _In_ size_t end = (size_t)-1,
-
616 _In_ int flags = match_default)
-
617 {
-
618 assert(text || start >= end);
-
619 bool r = start == 0 || start <= end && islbreak(text[start - 1]);
-
620 if (r && !m_invert || !r && m_invert) {
-
621 interval.end = interval.start = start;
-
622 return true;
-
623 }
-
624 interval.start = (interval.end = start) + 1;
-
625 return false;
-
626 }
-
627
-
628 protected:
-
629 bool m_invert;
-
630 };
-
631
-
632 using bol = basic_bol<char>;
-
633 using wbol = basic_bol<wchar_t>;
-
634#ifdef _UNICODE
-
635 using tbol = wbol;
-
636#else
-
637 using tbol = bol;
-
638#endif
-
639 using sgml_bol = basic_bol<char>;
-
640
-
644 template <class T>
-
645 class basic_eol : public basic_parser<T>
-
646 {
-
647 public:
-
648 basic_eol(bool invert = false) : m_invert(invert) {}
-
649
-
650 virtual bool match(
-
651 _In_reads_or_z_(end) const T* text,
-
652 _In_ size_t start = 0,
-
653 _In_ size_t end = (size_t)-1,
-
654 _In_ int flags = match_default)
-
655 {
-
656 assert(text || start >= end);
-
657 bool r = islbreak(text[start]);
-
658 if (r && !m_invert || !r && m_invert) {
-
659 interval.end = interval.start = start;
-
660 return true;
-
661 }
-
662 interval.start = (interval.end = start) + 1;
-
663 return false;
-
664 }
-
665
-
666 protected:
-
667 bool m_invert;
-
668 };
-
669
-
670 using eol = basic_eol<char>;
-
671 using weol = basic_eol<wchar_t>;
-
672#ifdef _UNICODE
-
673 using teol = weol;
-
674#else
-
675 using teol = eol;
-
676#endif
-
677 using sgml_eol = basic_eol<char>;
-
678
-
679 template <class T>
-
680 class basic_set : public basic_parser<T>
-
681 {
-
682 public:
-
683 basic_set(bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
684 basic_parser<T>(locale),
-
685 hit_offset((size_t)-1),
-
686 m_invert(invert)
-
687 {}
-
688
-
689 virtual bool match(
-
690 _In_reads_or_z_(end) const T* text,
-
691 _In_ size_t start = 0,
-
692 _In_ size_t end = (size_t)-1,
-
693 _In_ int flags = match_default) = 0;
-
694
-
695 virtual void invalidate()
-
696 {
-
697 hit_offset = (size_t)-1;
-
698 basic_parser<T>::invalidate();
-
699 }
-
700
-
701 public:
-
702 size_t hit_offset;
-
703
-
704 protected:
-
705 bool m_invert;
-
706 };
-
707
-
711 template <class T>
-
712 class basic_cu_set : public basic_set<T>
-
713 {
-
714 public:
-
715 basic_cu_set(
-
716 _In_reads_or_z_(count) const T* set,
-
717 _In_ size_t count = (size_t)-1,
-
718 _In_ bool invert = false,
-
719 _In_ const std::locale& locale = std::locale()) :
-
720 basic_set<T>(invert, locale)
-
721 {
-
722 if (set)
-
723 m_set.assign(set, set + stdex::strnlen(set, count));
-
724 }
-
725
-
726 virtual bool match(
-
727 _In_reads_or_z_(end) const T* text,
-
728 _In_ size_t start = 0,
-
729 _In_ size_t end = (size_t)-1,
-
730 _In_ int flags = match_default)
-
731 {
-
732 assert(text || start >= end);
-
733 if (start < end && text[start]) {
-
734 const T* set = m_set.c_str();
-
735 size_t r = (flags & match_case_insensitive) ?
-
736 stdex::strnichr(set, m_set.size(), text[start], m_locale) :
-
737 stdex::strnchr(set, m_set.size(), text[start]);
-
738 if (r != stdex::npos && !m_invert || r == stdex::npos && m_invert) {
-
739 hit_offset = r;
-
740 interval.end = (interval.start = start) + 1;
-
741 return true;
-
742 }
-
743 }
-
744 hit_offset = (size_t)-1;
-
745 interval.start = (interval.end = start) + 1;
-
746 return false;
-
747 }
-
748
-
749 protected:
-
750 std::basic_string<T> m_set;
-
751 };
-
752
-
753 using cu_set = basic_cu_set<char>;
-
754 using wcu_set = basic_cu_set<wchar_t>;
-
755#ifdef _UNICODE
-
756 using tcu_set = wcu_set;
-
757#else
-
758 using tcu_set = cu_set;
-
759#endif
-
760
-
764 class sgml_cp_set : public basic_set<char>
-
765 {
-
766 public:
-
767 sgml_cp_set(const char* set, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
-
768 basic_set<char>(invert, locale)
-
769 {
-
770 if (set)
-
771 m_set = sgml2wstr(set, count);
-
772 }
-
773
-
774 virtual bool match(
-
775 _In_reads_or_z_(end) const char* text,
-
776 _In_ size_t start = 0,
-
777 _In_ size_t end = (size_t)-1,
-
778 _In_ int flags = match_default)
-
779 {
-
780 assert(text || start >= end);
-
781 if (start < end && text[start]) {
-
782 wchar_t buf[3];
-
783 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
784 const wchar_t* set = m_set.c_str();
-
785 size_t r = (flags & match_case_insensitive) ?
-
786 stdex::strnistr(set, m_set.size(), chr, m_locale) :
-
787 stdex::strnstr(set, m_set.size(), chr);
-
788 if (r != stdex::npos && !m_invert || r == stdex::npos && m_invert) {
-
789 hit_offset = r;
-
790 interval.start = start;
-
791 return true;
-
792 }
-
793 }
-
794 hit_offset = (size_t)-1;
-
795 interval.start = (interval.end = start) + 1;
-
796 return false;
-
797 }
-
798
-
799 protected:
-
800 std::wstring m_set;
-
801 };
-
802
-
806 template <class T>
-
807 class basic_string : public basic_parser<T>
-
808 {
-
809 public:
-
810 basic_string(
-
811 _In_reads_or_z_(count) const T* str,
-
812 _In_ size_t count = (size_t)-1,
-
813 _In_ const std::locale& locale = std::locale()) :
-
814 basic_parser<T>(locale),
-
815 m_str(str, str + stdex::strnlen(str, count))
-
816 {}
-
817
-
818 virtual bool match(
-
819 _In_reads_or_z_(end) const T* text,
-
820 _In_ size_t start = 0,
-
821 _In_ size_t end = (size_t)-1,
-
822 _In_ int flags = match_default)
-
823 {
-
824 assert(text || start >= end);
-
825 size_t
-
826 m = m_str.size(),
-
827 n = std::min<size_t>(end - start, m);
-
828 bool r = ((flags & match_case_insensitive) ?
-
829 stdex::strnicmp(text + start, n, m_str.c_str(), m, m_locale) :
-
830 stdex::strncmp(text + start, n, m_str.c_str(), m)) == 0;
-
831 if (r) {
-
832 interval.end = (interval.start = start) + n;
-
833 return true;
-
834 }
-
835 interval.start = (interval.end = start) + 1;
-
836 return false;
-
837 }
-
838
-
839 protected:
-
840 std::basic_string<T> m_str;
-
841 };
-
842
-
843 using string = basic_string<char>;
-
844 using wstring = basic_string<wchar_t>;
-
845#ifdef _UNICODE
-
846 using tstring = wstring;
-
847#else
-
848 using tstring = string;
-
849#endif
-
850
-
854 class sgml_string : public sgml_parser
-
855 {
-
856 public:
-
857 sgml_string(const char* str, size_t count = (size_t)-1, _In_ const std::locale& locale = std::locale()) :
-
858 sgml_parser(locale),
-
859 m_str(sgml2wstr(str, count))
-
860 {}
-
861
-
862 virtual bool match(
-
863 _In_reads_or_z_(end) const char* text,
-
864 _In_ size_t start = 0,
-
865 _In_ size_t end = (size_t)-1,
-
866 _In_ int flags = match_default)
-
867 {
-
868 assert(text || start >= end);
-
869 const wchar_t* str = m_str.c_str();
-
870 const bool case_insensitive = flags & match_case_insensitive ? true : false;
-
871 const auto& ctype = std::use_facet<std::ctype<wchar_t>>(m_locale);
-
872 for (interval.end = start;;) {
-
873 if (!*str) {
-
874 interval.start = start;
-
875 return true;
-
876 }
-
877 if (interval.end >= end || !text[interval.end]) {
-
878 interval.start = (interval.end = start) + 1;
-
879 return false;
-
880 }
-
881 wchar_t buf[3];
-
882 const wchar_t* chr = next_sgml_cp(text, interval.end, end, interval.end, buf);
-
883 for (; *chr; ++str, ++chr) {
-
884 if (!*str ||
-
885 (case_insensitive ? ctype.tolower(*str) != ctype.tolower(*chr) : *str != *chr))
-
886 {
-
887 interval.start = (interval.end = start) + 1;
-
888 return false;
-
889 }
-
890 }
-
891 }
-
892 }
-
893
-
894 protected:
-
895 std::wstring m_str;
-
896 };
-
897
-
901 template <class T>
-
902 class basic_iterations : public basic_parser<T>
-
903 {
-
904 public:
-
905 basic_iterations(const std::shared_ptr<basic_parser<T>>& el, size_t min_iterations = 0, size_t max_iterations = (size_t)-1, bool greedy = true) :
-
906 m_el(el),
-
907 m_min_iterations(min_iterations),
-
908 m_max_iterations(max_iterations),
-
909 m_greedy(greedy)
-
910 {}
-
911
-
912 virtual bool match(
-
913 _In_reads_or_z_(end) const T* text,
-
914 _In_ size_t start = 0,
-
915 _In_ size_t end = (size_t)-1,
-
916 _In_ int flags = match_default)
-
917 {
-
918 assert(text || start >= end);
-
919 interval.start = interval.end = start;
-
920 for (size_t i = 0; ; i++) {
-
921 if (!m_greedy && i >= m_min_iterations || i >= m_max_iterations)
-
922 return true;
-
923 if (!m_el->match(text, interval.end, end, flags)) {
-
924 if (i >= m_min_iterations)
-
925 return true;
-
926 break;
-
927 }
-
928 if (m_el->interval.end == interval.end) {
-
929 // Element did match, but the matching interval was empty. Quit instead of spinning.
-
930 return true;
-
931 }
-
932 interval.end = m_el->interval.end;
-
933 }
-
934 interval.start = (interval.end = start) + 1;
-
935 return false;
-
936 }
-
937
-
938 protected:
-
939 std::shared_ptr<basic_parser<T>> m_el;
-
940 size_t m_min_iterations;
-
941 size_t m_max_iterations;
-
942 bool m_greedy;
-
943 };
-
944
-
945 using iterations = basic_iterations<char>;
-
946 using witerations = basic_iterations<wchar_t>;
-
947#ifdef _UNICODE
-
948 using titerations = witerations;
-
949#else
-
950 using titerations = iterations;
-
951#endif
-
952 using sgml_iterations = basic_iterations<char>;
-
953
-
957 template <class T>
-
958 class parser_collection : public basic_parser<T>
-
959 {
-
960 protected:
-
961 parser_collection(_In_ const std::locale& locale) : basic_parser<T>(locale) {}
-
962
-
963 public:
-
964 parser_collection(
-
965 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el,
-
966 _In_ size_t count,
-
967 _In_ const std::locale& locale = std::locale()) :
-
968 basic_parser<T>(locale)
-
969 {
-
970 assert(el || !count);
-
971 m_collection.reserve(count);
-
972 for (size_t i = 0; i < count; i++)
-
973 m_collection.push_back(el[i]);
-
974 }
-
975
-
976 parser_collection(
-
977 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
-
978 _In_ const std::locale& locale = std::locale()) :
-
979 basic_parser<T>(locale),
-
980 m_collection(std::move(collection))
-
981 {}
-
982
-
983 virtual void invalidate()
-
984 {
-
985 for (auto& el: m_collection)
-
986 el->invalidate();
-
987 basic_parser<T>::invalidate();
-
988 }
-
989
-
990 protected:
-
991 std::vector<std::shared_ptr<basic_parser<T>>> m_collection;
-
992 };
-
993
-
997 template <class T>
-
998 class basic_sequence : public parser_collection<T>
-
999 {
-
1000 public:
-
1001 basic_sequence(
-
1002 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
-
1003 _In_ size_t count = 0,
-
1004 _In_ const std::locale& locale = std::locale()) :
-
1005 parser_collection<T>(el, count, locale)
-
1006 {}
-
1007
-
1008 basic_sequence(
-
1009 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
-
1010 _In_ const std::locale& locale = std::locale()) :
-
1011 parser_collection<T>(std::move(collection), locale)
-
1012 {}
-
1013
-
1014 virtual bool match(
-
1015 _In_reads_or_z_(end) const T* text,
-
1016 _In_ size_t start = 0,
-
1017 _In_ size_t end = (size_t)-1,
-
1018 _In_ int flags = match_default)
-
1019 {
-
1020 assert(text || start >= end);
-
1021 interval.end = start;
-
1022 for (auto i = m_collection.begin(); i != m_collection.end(); ++i) {
-
1023 if (!(*i)->match(text, interval.end, end, flags)) {
-
1024 for (++i; i != m_collection.end(); ++i)
-
1025 (*i)->invalidate();
-
1026 interval.start = (interval.end = start) + 1;
-
1027 return false;
-
1028 }
-
1029 interval.end = (*i)->interval.end;
-
1030 }
-
1031 interval.start = start;
-
1032 return true;
-
1033 }
-
1034 };
-
1035
-
1036 using sequence = basic_sequence<char>;
-
1037 using wsequence = basic_sequence<wchar_t>;
-
1038#ifdef _UNICODE
-
1039 using tsequence = wsequence;
-
1040#else
-
1041 using tsequence = sequence;
-
1042#endif
-
1043 using sgml_sequence = basic_sequence<char>;
-
1044
-
1048 template <class T>
-
1049 class basic_branch : public parser_collection<T>
-
1050 {
-
1051 protected:
-
1052 basic_branch(_In_ const std::locale& locale) :
-
1053 parser_collection<T>(locale),
-
1054 hit_offset((size_t)-1)
-
1055 {}
-
1056
-
1057 public:
-
1058 basic_branch(
-
1059 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
-
1060 _In_ size_t count = 0,
-
1061 _In_ const std::locale& locale = std::locale()) :
-
1062 parser_collection<T>(el, count, locale),
-
1063 hit_offset((size_t)-1)
-
1064 {}
-
1065
-
1066 basic_branch(
-
1067 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
-
1068 _In_ const std::locale& locale = std::locale()) :
-
1069 parser_collection<T>(std::move(collection), locale),
-
1070 hit_offset((size_t)-1)
-
1071 {}
-
1072
-
1073 virtual bool match(
-
1074 _In_reads_or_z_(end) const T* text,
-
1075 _In_ size_t start = 0,
-
1076 _In_ size_t end = (size_t)-1,
-
1077 _In_ int flags = match_default)
-
1078 {
-
1079 assert(text || start >= end);
-
1080 hit_offset = 0;
-
1081 for (auto i = m_collection.begin(); i != m_collection.end(); ++i, ++hit_offset) {
-
1082 if ((*i)->match(text, start, end, flags)) {
-
1083 interval = (*i)->interval;
-
1084 for (++i; i != m_collection.end(); ++i)
-
1085 (*i)->invalidate();
-
1086 return true;
-
1087 }
-
1088 }
-
1089 hit_offset = (size_t)-1;
-
1090 interval.start = (interval.end = start) + 1;
-
1091 return false;
-
1092 }
-
1093
-
1094 virtual void invalidate()
-
1095 {
-
1096 hit_offset = (size_t)-1;
-
1097 parser_collection<T>::invalidate();
-
1098 }
-
1099
-
1100 public:
-
1101 size_t hit_offset;
-
1102 };
-
1103
-
1104 using branch = basic_branch<char>;
-
1105 using wbranch = basic_branch<wchar_t>;
-
1106#ifdef _UNICODE
-
1107 using tbranch = wbranch;
-
1108#else
-
1109 using tbranch = branch;
-
1110#endif
-
1111 using sgml_branch = basic_branch<char>;
-
1112
-
1116 template <class T, class T_parser = basic_string<T>>
-
1117 class basic_string_branch : public basic_branch<T>
-
1118 {
-
1119 public:
-
1120 inline basic_string_branch(
-
1121 _In_reads_(count) const T* str_z = nullptr,
-
1122 _In_ size_t count = 0,
-
1123 _In_ const std::locale& locale = std::locale()) :
-
1124 basic_branch<T>(locale)
-
1125 {
-
1126 build(str_z, count);
-
1127 }
-
1128
-
1129 inline basic_string_branch(_In_z_ const T* str, ...) :
-
1130 basic_branch<T>(std::locale())
-
1131 {
-
1132 va_list params;
-
1133 va_start(params, str);
-
1134 build(str, params);
-
1135 va_end(params);
-
1136 }
-
1137
-
1138 inline basic_string_branch(_In_ const std::locale& locale, _In_z_ const T* str, ...) :
-
1139 basic_branch<T>(locale)
-
1140 {
-
1141 va_list params;
-
1142 va_start(params, str);
-
1143 build(str, params);
-
1144 va_end(params);
-
1145 }
-
1146
-
1147 protected:
-
1148 void build(_In_reads_(count) const T* str_z, _In_ size_t count)
-
1149 {
-
1150 assert(str_z || !count);
-
1151 if (count) {
-
1152 size_t offset, n;
-
1153 for (
-
1154 offset = n = 0;
-
1155 offset < count && str_z[offset];
-
1156 offset += stdex::strnlen(str_z + offset, count - offset) + 1, ++n);
-
1157 m_collection.reserve(n);
-
1158 for (
-
1159 offset = 0;
-
1160 offset < count && str_z[offset];
-
1161 offset += stdex::strnlen(str_z + offset, count - offset) + 1)
-
1162 m_collection.push_back(std::move(std::make_shared<T_parser>(str_z + offset, count - offset, m_locale)));
-
1163 }
-
1164 }
-
1165
-
1166 void build(_In_z_ const T* str, _In_ va_list params)
-
1167 {
-
1168 const T* p;
-
1169 for (
-
1170 m_collection.push_back(std::move(std::make_shared<T_parser>(str, (size_t)-1, m_locale)));
-
1171 (p = va_arg(params, const T*)) != nullptr;
-
1172 m_collection.push_back(std::move(std::make_shared<T_parser>(p, (size_t)-1, m_locale))));
-
1173 }
-
1174 };
-
1175
-
1176 using string_branch = basic_string_branch<char>;
-
1177 using wstring_branch = basic_string_branch<wchar_t>;
-
1178#ifdef _UNICODE
-
1179 using tstring_branch = wstring_branch;
-
1180#else
-
1181 using tstring_branch = string_branch;
-
1182#endif
-
1183 using sgml_string_branch = basic_string_branch<char, sgml_string>;
-
1184
-
1188 template <class T>
-
1189 class basic_permutation : public parser_collection<T>
-
1190 {
-
1191 public:
-
1192 basic_permutation(
-
1193 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
-
1194 _In_ size_t count = 0,
-
1195 _In_ const std::locale& locale = std::locale()) :
-
1196 parser_collection<T>(el, count, locale)
-
1197 {}
-
1198
-
1199 basic_permutation(
-
1200 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
-
1201 _In_ const std::locale& locale = std::locale()) :
-
1202 parser_collection<T>(std::move(collection), locale)
-
1203 {}
-
1204
-
1205 virtual bool match(
-
1206 _In_reads_or_z_(end) const T* text,
-
1207 _In_ size_t start = 0,
-
1208 _In_ size_t end = (size_t)-1,
-
1209 _In_ int flags = match_default)
-
1210 {
-
1211 assert(text || start >= end);
-
1212 for (auto& el: m_collection)
-
1213 el->invalidate();
-
1214 if (match_recursively(text, start, end, flags)) {
-
1215 interval.start = start;
-
1216 return true;
-
1217 }
-
1218 interval.start = (interval.end = start) + 1;
-
1219 return false;
-
1220 }
-
1221
-
1222 protected:
-
1223 bool match_recursively(
-
1224 _In_reads_or_z_(end) const T* text,
-
1225 _In_ size_t start = 0,
-
1226 _In_ size_t end = (size_t)-1,
-
1227 _In_ int flags = match_default)
-
1228 {
-
1229 bool all_matched = true;
-
1230 for (auto& el: m_collection) {
-
1231 if (!el->interval) {
-
1232 // Element was not matched in permutatuion yet.
-
1233 all_matched = false;
-
1234 if (el->match(text, start, end, flags)) {
-
1235 // Element matched for the first time.
-
1236 if (match_recursively(text, el->interval.end, end, flags)) {
-
1237 // Rest of the elements matched too.
-
1238 return true;
-
1239 }
-
1240 el->invalidate();
-
1241 }
-
1242 }
-
1243 }
-
1244 if (all_matched) {
-
1245 interval.end = start;
-
1246 return true;
-
1247 }
-
1248 return false;
-
1249 }
-
1250 };
-
1251
-
1252 using permutation = basic_permutation<char>;
-
1253 using wpermutation = basic_permutation<wchar_t>;
-
1254#ifdef _UNICODE
-
1255 using tpermutation = wpermutation;
-
1256#else
-
1257 using tpermutation = permutation;
-
1258#endif
-
1259 using sgml_permutation = basic_permutation<char>;
-
1260
-
1264 template <class T>
-
1265 class basic_integer : public basic_parser<T>
-
1266 {
-
1267 public:
-
1268 basic_integer(_In_ const std::locale& locale = std::locale()) :
-
1269 basic_parser<T>(locale),
-
1270 value(0)
-
1271 {}
-
1272
-
1273 virtual void invalidate()
-
1274 {
-
1275 value = 0;
-
1276 basic_parser<T>::invalidate();
-
1277 }
-
1278
-
1279 public:
-
1280 size_t value;
-
1281 };
-
1282
-
1286 template <class T>
-
1287 class basic_integer10 : public basic_integer<T>
-
1288 {
-
1289 public:
-
1290 basic_integer10(
-
1291 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
-
1292 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
-
1293 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
-
1294 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
-
1295 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
-
1296 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
-
1297 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
-
1298 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
-
1299 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
-
1300 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
-
1301 _In_ const std::locale& locale = std::locale()) :
-
1302 basic_integer<T>(locale),
-
1303 m_digit_0(digit_0),
-
1304 m_digit_1(digit_1),
-
1305 m_digit_2(digit_2),
-
1306 m_digit_3(digit_3),
-
1307 m_digit_4(digit_4),
-
1308 m_digit_5(digit_5),
-
1309 m_digit_6(digit_6),
-
1310 m_digit_7(digit_7),
-
1311 m_digit_8(digit_8),
-
1312 m_digit_9(digit_9)
-
1313 {}
-
1314
-
1315 virtual bool match(
-
1316 _In_reads_or_z_(end) const T* text,
-
1317 _In_ size_t start = 0,
-
1318 _In_ size_t end = (size_t)-1,
-
1319 _In_ int flags = match_default)
-
1320 {
-
1321 assert(text || start >= end);
-
1322 for (interval.end = start, value = 0; interval.end < end && text[interval.end];) {
-
1323 size_t dig;
-
1324 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; interval.end = m_digit_0->interval.end; }
-
1325 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; interval.end = m_digit_1->interval.end; }
-
1326 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; interval.end = m_digit_2->interval.end; }
-
1327 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; interval.end = m_digit_3->interval.end; }
-
1328 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; interval.end = m_digit_4->interval.end; }
-
1329 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; interval.end = m_digit_5->interval.end; }
-
1330 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; interval.end = m_digit_6->interval.end; }
-
1331 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; interval.end = m_digit_7->interval.end; }
-
1332 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; interval.end = m_digit_8->interval.end; }
-
1333 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; interval.end = m_digit_9->interval.end; }
-
1334 else break;
-
1335 value = value * 10 + dig;
-
1336 }
-
1337 if (start < interval.end) {
-
1338 interval.start = start;
-
1339 return true;
-
1340 }
-
1341 interval.start = (interval.end = start) + 1;
-
1342 return false;
-
1343 }
-
1344
-
1345 protected:
-
1346 std::shared_ptr<basic_parser<T>>
-
1347 m_digit_0,
-
1348 m_digit_1,
-
1349 m_digit_2,
-
1350 m_digit_3,
-
1351 m_digit_4,
-
1352 m_digit_5,
-
1353 m_digit_6,
-
1354 m_digit_7,
-
1355 m_digit_8,
-
1356 m_digit_9;
-
1357 };
-
1358
-
1359 using integer10 = basic_integer10<char>;
-
1360 using winteger10 = basic_integer10<wchar_t>;
-
1361#ifdef _UNICODE
-
1362 using tinteger10 = winteger10;
-
1363#else
-
1364 using tinteger10 = integer10;
-
1365#endif
-
1366 using sgml_integer10 = basic_integer10<char>;
-
1367
-
1371 template <class T>
-
1372 class basic_integer10ts : public basic_integer<T>
-
1373 {
-
1374 public:
-
1375 basic_integer10ts(
-
1376 _In_ const std::shared_ptr<basic_integer10<T>>& digits,
-
1377 _In_ const std::shared_ptr<basic_set<T>>& separator,
-
1378 _In_ const std::locale& locale = std::locale()) :
-
1379 basic_integer<T>(locale),
-
1380 digit_count(0),
-
1381 has_separators(false),
-
1382 m_digits(digits),
-
1383 m_separator(separator)
-
1384 {}
-
1385
-
1386 virtual bool match(
-
1387 _In_reads_or_z_(end) const T* text,
-
1388 _In_ size_t start = 0,
-
1389 _In_ size_t end = (size_t)-1,
-
1390 _In_ int flags = match_default)
-
1391 {
-
1392 assert(text || start >= end);
-
1393 if (m_digits->match(text, start, end, flags)) {
-
1394 // Leading part match.
-
1395 value = m_digits->value;
-
1396 digit_count = m_digits->interval.size();
-
1397 has_separators = false;
-
1398 interval.start = start;
-
1399 interval.end = m_digits->interval.end;
-
1400 if (m_digits->interval.size() <= 3) {
-
1401 // Maybe separated with thousand separators?
-
1402 size_t hit_offset = (size_t)-1;
-
1403 while (m_separator->match(text, interval.end, end, flags) &&
-
1404 (hit_offset == (size_t)-1 || hit_offset == m_separator->hit_offset) && // All separators must be the same, no mixing.
-
1405 m_digits->match(text, m_separator->interval.end, end, flags) &&
-
1406 m_digits->interval.size() == 3)
-
1407 {
-
1408 // Thousand separator and three-digit integer followed.
-
1409 value = value * 1000 + m_digits->value;
-
1410 digit_count += 3;
-
1411 has_separators = true;
-
1412 interval.end = m_digits->interval.end;
-
1413 hit_offset = m_separator->hit_offset;
-
1414 }
-
1415 }
-
1416
-
1417 return true;
-
1418 }
-
1419 value = 0;
-
1420 interval.start = (interval.end = start) + 1;
-
1421 return false;
-
1422 }
-
1423
-
1424 virtual void invalidate()
-
1425 {
-
1426 digit_count = 0;
-
1427 has_separators = false;
-
1428 basic_integer<T>::invalidate();
-
1429 }
-
1430
-
1431 public:
-
1432 size_t digit_count;
-
1433 bool has_separators;
-
1434
-
1435 protected:
-
1436 std::shared_ptr<basic_integer10<T>> m_digits;
-
1437 std::shared_ptr<basic_set<T>> m_separator;
-
1438 };
-
1439
-
1440 using integer10ts = basic_integer10ts<char>;
-
1441 using winteger10ts = basic_integer10ts<wchar_t>;
-
1442#ifdef _UNICODE
-
1443 using tinteger10ts = winteger10ts;
-
1444#else
-
1445 using tinteger10ts = integer10ts;
-
1446#endif
-
1447 using sgml_integer10ts = basic_integer10ts<char>;
-
1448
-
1452 template <class T>
-
1453 class basic_integer16 : public basic_integer<T>
-
1454 {
-
1455 public:
-
1456 basic_integer16(
-
1457 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
-
1458 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
-
1459 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
-
1460 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
-
1461 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
-
1462 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
-
1463 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
-
1464 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
-
1465 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
-
1466 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
-
1467 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
-
1468 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
-
1469 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
-
1470 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
-
1471 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
-
1472 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
-
1473 _In_ const std::locale& locale = std::locale()) :
-
1474 basic_integer<T>(locale),
-
1475 m_digit_0(digit_0),
-
1476 m_digit_1(digit_1),
-
1477 m_digit_2(digit_2),
-
1478 m_digit_3(digit_3),
-
1479 m_digit_4(digit_4),
-
1480 m_digit_5(digit_5),
-
1481 m_digit_6(digit_6),
-
1482 m_digit_7(digit_7),
-
1483 m_digit_8(digit_8),
-
1484 m_digit_9(digit_9),
-
1485 m_digit_10(digit_10),
-
1486 m_digit_11(digit_11),
-
1487 m_digit_12(digit_12),
-
1488 m_digit_13(digit_13),
-
1489 m_digit_14(digit_14),
-
1490 m_digit_15(digit_15)
-
1491 {}
-
1492
-
1493 virtual bool match(
-
1494 _In_reads_or_z_(end) const T* text,
-
1495 _In_ size_t start = 0,
-
1496 _In_ size_t end = (size_t)-1,
-
1497 _In_ int flags = match_default)
-
1498 {
-
1499 assert(text || start >= end);
-
1500 for (interval.end = start, value = 0; interval.end < end && text[interval.end];) {
-
1501 size_t dig;
-
1502 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; interval.end = m_digit_0->interval.end; }
-
1503 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; interval.end = m_digit_1->interval.end; }
-
1504 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; interval.end = m_digit_2->interval.end; }
-
1505 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; interval.end = m_digit_3->interval.end; }
-
1506 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; interval.end = m_digit_4->interval.end; }
-
1507 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; interval.end = m_digit_5->interval.end; }
-
1508 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; interval.end = m_digit_6->interval.end; }
-
1509 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; interval.end = m_digit_7->interval.end; }
-
1510 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; interval.end = m_digit_8->interval.end; }
-
1511 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; interval.end = m_digit_9->interval.end; }
-
1512 else if (m_digit_10->match(text, interval.end, end, flags)) { dig = 10; interval.end = m_digit_10->interval.end; }
-
1513 else if (m_digit_11->match(text, interval.end, end, flags)) { dig = 11; interval.end = m_digit_11->interval.end; }
-
1514 else if (m_digit_12->match(text, interval.end, end, flags)) { dig = 12; interval.end = m_digit_12->interval.end; }
-
1515 else if (m_digit_13->match(text, interval.end, end, flags)) { dig = 13; interval.end = m_digit_13->interval.end; }
-
1516 else if (m_digit_14->match(text, interval.end, end, flags)) { dig = 14; interval.end = m_digit_14->interval.end; }
-
1517 else if (m_digit_15->match(text, interval.end, end, flags)) { dig = 15; interval.end = m_digit_15->interval.end; }
-
1518 else break;
-
1519 value = value * 16 + dig;
-
1520 }
-
1521 if (start < interval.end) {
-
1522 interval.start = start;
-
1523 return true;
-
1524 }
-
1525 interval.start = (interval.end = start) + 1;
-
1526 return false;
-
1527 }
-
1528
-
1529 protected:
-
1530 std::shared_ptr<basic_parser<T>>
-
1531 m_digit_0,
-
1532 m_digit_1,
-
1533 m_digit_2,
-
1534 m_digit_3,
-
1535 m_digit_4,
-
1536 m_digit_5,
-
1537 m_digit_6,
-
1538 m_digit_7,
-
1539 m_digit_8,
-
1540 m_digit_9,
-
1541 m_digit_10,
-
1542 m_digit_11,
-
1543 m_digit_12,
-
1544 m_digit_13,
-
1545 m_digit_14,
-
1546 m_digit_15;
-
1547 };
-
1548
-
1549 using integer16 = basic_integer16<char>;
-
1550 using winteger16 = basic_integer16<wchar_t>;
-
1551#ifdef _UNICODE
-
1552 using tinteger16 = winteger16;
-
1553#else
-
1554 using tinteger16 = integer16;
-
1555#endif
-
1556 using sgml_integer16 = basic_integer16<char>;
-
1557
-
1561 template <class T>
-
1562 class basic_roman_numeral : public basic_integer<T>
-
1563 {
-
1564 public:
-
1565 basic_roman_numeral(
-
1566 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
-
1567 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
-
1568 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
-
1569 _In_ const std::shared_ptr<basic_parser<T>>& digit_50,
-
1570 _In_ const std::shared_ptr<basic_parser<T>>& digit_100,
-
1571 _In_ const std::shared_ptr<basic_parser<T>>& digit_500,
-
1572 _In_ const std::shared_ptr<basic_parser<T>>& digit_1000,
-
1573 _In_ const std::shared_ptr<basic_parser<T>>& digit_5000,
-
1574 _In_ const std::shared_ptr<basic_parser<T>>& digit_10000,
-
1575 _In_ const std::locale& locale = std::locale()) :
-
1576 basic_integer<T>(locale),
-
1577 m_digit_1(digit_1),
-
1578 m_digit_5(digit_5),
-
1579 m_digit_10(digit_10),
-
1580 m_digit_50(digit_50),
-
1581 m_digit_100(digit_100),
-
1582 m_digit_500(digit_500),
-
1583 m_digit_1000(digit_1000),
-
1584 m_digit_5000(digit_5000),
-
1585 m_digit_10000(digit_10000)
-
1586 {}
-
1587
-
1588 virtual bool match(
-
1589 _In_reads_or_z_(end) const T* text,
-
1590 _In_ size_t start = 0,
-
1591 _In_ size_t end = (size_t)-1,
-
1592 _In_ int flags = match_default)
-
1593 {
-
1594 assert(text || start >= end);
-
1595 size_t
-
1596 dig[5] = { (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1 },
-
1597 end2;
-
1598
-
1599 for (interval.end = start, value = 0; interval.end < end && text[interval.end]; dig[3] = dig[2], dig[2] = dig[1], dig[1] = dig[0], interval.end = end2) {
-
1600 if (m_digit_1 && m_digit_1->match(text, interval.end, end, flags)) { dig[0] = 1; end2 = m_digit_1->interval.end; }
-
1601 else if (m_digit_5 && m_digit_5->match(text, interval.end, end, flags)) { dig[0] = 5; end2 = m_digit_5->interval.end; }
-
1602 else if (m_digit_10 && m_digit_10->match(text, interval.end, end, flags)) { dig[0] = 10; end2 = m_digit_10->interval.end; }
-
1603 else if (m_digit_50 && m_digit_50->match(text, interval.end, end, flags)) { dig[0] = 50; end2 = m_digit_50->interval.end; }
-
1604 else if (m_digit_100 && m_digit_100->match(text, interval.end, end, flags)) { dig[0] = 100; end2 = m_digit_100->interval.end; }
-
1605 else if (m_digit_500 && m_digit_500->match(text, interval.end, end, flags)) { dig[0] = 500; end2 = m_digit_500->interval.end; }
-
1606 else if (m_digit_1000 && m_digit_1000->match(text, interval.end, end, flags)) { dig[0] = 1000; end2 = m_digit_1000->interval.end; }
-
1607 else if (m_digit_5000 && m_digit_5000->match(text, interval.end, end, flags)) { dig[0] = 5000; end2 = m_digit_5000->interval.end; }
-
1608 else if (m_digit_10000 && m_digit_10000->match(text, interval.end, end, flags)) { dig[0] = 10000; end2 = m_digit_10000->interval.end; }
-
1609 else break;
-
1610
-
1611 // Store first digit.
-
1612 if (dig[4] == (size_t)-1) dig[4] = dig[0];
-
1613
-
1614 if (dig[3] == dig[2] && dig[2] == dig[1] && dig[1] == dig[0] && dig[0] != dig[4]) {
-
1615 // Same digit repeated four times. No-go, unless first digit. E.g. XIIII vs. XIV. MMMMMCD allowed, IIII also...
-
1616 break;
-
1617 }
-
1618 if (dig[0] <= dig[1]) {
-
1619 // Digit is less or equal previous one: add.
-
1620 value += dig[0];
-
1621 }
-
1622 else if (
-
1623 dig[1] == 1 && (dig[0] == 5 || dig[0] == 10) ||
-
1624 dig[1] == 10 && (dig[0] == 50 || dig[0] == 100) ||
-
1625 dig[1] == 100 && (dig[0] == 500 || dig[0] == 1000) ||
-
1626 dig[1] == 1000 && (dig[0] == 5000 || dig[0] == 10000))
-
1627 {
-
1628 // Digit is up to two orders bigger than previous one: subtract. But...
-
1629 if (dig[2] < dig[0]) {
-
1630 // Digit is also bigger than pre-previous one. E.g. VIX (V < X => invalid)
-
1631 break;
-
1632 }
-
1633 value -= dig[1]; // Cancel addition in the previous step.
-
1634 dig[0] -= dig[1]; // Combine last two digits.
-
1635 dig[1] = dig[2]; // The true previous digit is now pre-previous one. :)
-
1636 dig[2] = dig[3]; // The true pre-previous digit is now pre-pre-previous one. :)
-
1637 value += dig[0]; // Add combined value.
-
1638 }
-
1639 else {
-
1640 // New digit is too big than the previous one. E.g. VX (V < X => invalid)
-
1641 break;
-
1642 }
-
1643 }
-
1644 if (value) {
-
1645 interval.start = start;
-
1646 return true;
-
1647 }
-
1648 interval.start = (interval.end = start) + 1;
-
1649 return false;
-
1650 }
-
1651
-
1652 protected:
-
1653 std::shared_ptr<basic_parser<T>>
-
1654 m_digit_1,
-
1655 m_digit_5,
-
1656 m_digit_10,
-
1657 m_digit_50,
-
1658 m_digit_100,
-
1659 m_digit_500,
-
1660 m_digit_1000,
-
1661 m_digit_5000,
-
1662 m_digit_10000;
-
1663 };
-
1664
-
1665 using roman_numeral = basic_roman_numeral<char>;
-
1666 using wroman_numeral = basic_roman_numeral<wchar_t>;
-
1667#ifdef _UNICODE
-
1668 using troman_numeral = wroman_numeral;
-
1669#else
-
1670 using troman_numeral = roman_numeral;
-
1671#endif
-
1672 using sgml_roman_numeral = basic_roman_numeral<char>;
-
1673
-
1677 template <class T>
-
1678 class basic_fraction : public basic_parser<T>
-
1679 {
-
1680 public:
-
1681 basic_fraction(
-
1682 _In_ const std::shared_ptr<basic_parser<T>>& _numerator,
-
1683 _In_ const std::shared_ptr<basic_parser<T>>& _fraction_line,
-
1684 _In_ const std::shared_ptr<basic_parser<T>>& _denominator,
-
1685 _In_ const std::locale& locale = std::locale()) :
-
1686 basic_parser<T>(locale),
-
1687 numerator(_numerator),
-
1688 fraction_line(_fraction_line),
-
1689 denominator(_denominator)
-
1690 {}
-
1691
-
1692 virtual bool match(
-
1693 _In_reads_or_z_(end) const T* text,
-
1694 _In_ size_t start = 0,
-
1695 _In_ size_t end = (size_t)-1,
-
1696 _In_ int flags = match_default)
-
1697 {
-
1698 assert(text || start >= end);
-
1699 if (numerator->match(text, start, end, flags) &&
-
1700 fraction_line->match(text, numerator->interval.end, end, flags) &&
-
1701 denominator->match(text, fraction_line->interval.end, end, flags))
-
1702 {
-
1703 interval.start = start;
-
1704 interval.end = denominator->interval.end;
-
1705 return true;
-
1706 }
-
1707 numerator->invalidate();
-
1708 fraction_line->invalidate();
-
1709 denominator->invalidate();
-
1710 interval.start = (interval.end = start) + 1;
-
1711 return false;
-
1712 }
-
1713
-
1714 virtual void invalidate()
-
1715 {
-
1716 numerator->invalidate();
-
1717 fraction_line->invalidate();
-
1718 denominator->invalidate();
-
1719 basic_parser<T>::invalidate();
-
1720 }
-
1721
-
1722 public:
-
1723 std::shared_ptr<basic_parser<T>> numerator;
-
1724 std::shared_ptr<basic_parser<T>> fraction_line;
-
1725 std::shared_ptr<basic_parser<T>> denominator;
-
1726 };
-
1727
-
1728 using fraction = basic_fraction<char>;
-
1729 using wfraction = basic_fraction<wchar_t>;
-
1730#ifdef _UNICODE
-
1731 using tfraction = wfraction;
-
1732#else
-
1733 using tfraction = fraction;
-
1734#endif
-
1735 using sgml_fraction = basic_fraction<char>;
-
1736
-
1740 template <class T>
-
1741 class basic_score : public basic_parser<T>
-
1742 {
-
1743 public:
-
1744 basic_score(
-
1745 _In_ const std::shared_ptr<basic_parser<T>>& _home,
-
1746 _In_ const std::shared_ptr<basic_parser<T>>& _separator,
-
1747 _In_ const std::shared_ptr<basic_parser<T>>& _guest,
-
1748 _In_ const std::shared_ptr<basic_parser<T>>& space,
-
1749 _In_ const std::locale& locale = std::locale()) :
-
1750 basic_parser<T>(locale),
-
1751 home(_home),
-
1752 separator(_separator),
-
1753 guest(_guest),
-
1754 m_space(space)
-
1755 {}
-
1756
-
1757 virtual bool match(
-
1758 _In_reads_or_z_(end) const T* text,
-
1759 _In_ size_t start = 0,
-
1760 _In_ size_t end = (size_t)-1,
-
1761 _In_ int flags = match_default)
-
1762 {
-
1763 assert(text || start >= end);
-
1764 interval.end = start;
-
1765
-
1766 if (home->match(text, interval.end, end, flags))
-
1767 interval.end = home->interval.end;
-
1768 else
-
1769 goto end;
-
1770
-
1771 const int space_match_flags = flags & ~match_multiline; // Spaces in score must never be broken in new line.
-
1772 for (; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
1773
-
1774 if (separator->match(text, interval.end, end, flags))
-
1775 interval.end = separator->interval.end;
-
1776 else
-
1777 goto end;
-
1778
-
1779 for (; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
16#ifdef _WIN32
+
17#include <winsock2.h>
+
18#include <ws2ipdef.h>
+
19#else
+
20#include <inaddr.h>
+
21#include <in6addr.h>
+
22#endif
+
23#include <limits>
+
24#include <list>
+
25#include <locale>
+
26#include <memory>
+
27#include <set>
+
28#include <string>
+
29
+
30#ifdef _MSC_VER
+
31#pragma warning(push)
+
32#pragma warning(disable: 4100)
+
33#endif
+
34
+
35#define ENUM_FLAG_OPERATOR(T,X) \
+
36inline T operator X (const T lhs, const T rhs) { return static_cast<T>(static_cast<std::underlying_type_t<T>>(lhs) X static_cast<std::underlying_type_t<T>>(rhs)); } \
+
37inline T operator X (const T lhs, const std::underlying_type_t<T> rhs) { return static_cast<T>(static_cast<std::underlying_type_t<T>>(lhs) X rhs); } \
+
38inline T operator X (const std::underlying_type_t<T> lhs, const T rhs) { return static_cast<T>(lhs X static_cast<std::underlying_type_t<T>>(rhs)); } \
+
39inline T& operator X= (T& lhs, const T rhs) { return lhs = lhs X rhs; } \
+
40inline T& operator X= (T& lhs, const std::underlying_type_t<T> rhs) { return lhs = lhs X rhs; }
+
41#define ENUM_FLAGS(T, type) \
+
42enum class T : type; \
+
43inline T operator ~ (T t) { return (T) (~static_cast<std::underlying_type_t <T>>(t)); } \
+
44ENUM_FLAG_OPERATOR(T,|) \
+
45ENUM_FLAG_OPERATOR(T,^) \
+
46ENUM_FLAG_OPERATOR(T,&) \
+
47enum class T : type
+
48
+
49namespace stdex
+
50{
+
51 namespace parser
+
52 {
+
56 constexpr int match_default = 0;
+
57 constexpr int match_case_insensitive = 0x1;
+
58 constexpr int match_multiline = 0x2;
+
59
+
63 template <class T>
+
64 class basic_parser
+
65 {
+
66 public:
+
67 basic_parser(_In_ const std::locale& locale = std::locale()) : m_locale(locale) {}
+
68 virtual ~basic_parser() {}
+
69
+
70 bool search(
+
71 _In_reads_or_z_(end) const T* text,
+
72 _In_ size_t start = 0,
+
73 _In_ size_t end = (size_t)-1,
+
74 _In_ int flags = match_default)
+
75 {
+
76 for (size_t i = start; i < end && text[i]; i++)
+
77 if (match(text, i, end, flags))
+
78 return true;
+
79 return false;
+
80 }
+
81
+
82 virtual bool match(
+
83 _In_reads_or_z_(end) const T* text,
+
84 _In_ size_t start = 0,
+
85 _In_ size_t end = (size_t)-1,
+
86 _In_ int flags = match_default) = 0;
+
87
+
88 template<class _Traits, class _Ax>
+
89 inline bool match(
+
90 const std::basic_string<T, _Traits, _Ax>& text,
+
91 _In_ size_t start = 0,
+
92 _In_ size_t end = (size_t)-1,
+
93 _In_ int flags = match_default)
+
94 {
+
95 return match(text.c_str(), start, std::min<size_t>(end, text.size()), flags);
+
96 }
+
97
+
98 virtual void invalidate()
+
99 {
+
100 interval.start = 1;
+
101 interval.end = 0;
+
102 }
+
103
+
104 protected:
+
106 const wchar_t* next_sgml_cp(_In_ const char* text, _In_ size_t start, _In_ size_t end, _Out_ size_t& chr_end, _Out_ wchar_t(&buf)[3])
+
107 {
+
108 if (text[start] == '&') {
+
109 // Potential entity start
+
110 const auto& ctype = std::use_facet<std::ctype<T>>(m_locale);
+
111 for (chr_end = start + 1;; chr_end++) {
+
112 if (chr_end >= end || text[chr_end] == 0) {
+
113 // Unterminated entity
+
114 break;
+
115 }
+
116 if (text[chr_end] == ';') {
+
117 // Entity end
+
118 size_t n = chr_end - start - 1;
+
119 if (n >= 2 && text[start + 1] == '#') {
+
120 // Numerical entity
+
121 char32_t unicode;
+
122 if (text[start + 2] == 'x' || text[start + 2] == 'X')
+
123 unicode = strtou32(text + start + 3, n - 2, nullptr, 16);
+
124 else
+
125 unicode = strtou32(text + start + 2, n - 1, nullptr, 10);
+
126#ifdef _WIN32
+
127 if (unicode < 0x10000) {
+
128 buf[0] = (wchar_t)unicode;
+
129 buf[1] = 0;
+
130 }
+
131 else {
+
132 ucs4_to_surrogate_pair(buf, unicode);
+
133 buf[2] = 0;
+
134 }
+
135#else
+
136 buf[0] = (wchar_t)unicode;
+
137 buf[1] = 0;
+
138#endif
+
139 chr_end++;
+
140 return buf;
+
141 }
+
142 const wchar_t* entity_w = sgml2uni(text + start + 1, n);
+
143 if (entity_w) {
+
144 chr_end++;
+
145 return entity_w;
+
146 }
+
147 // Unknown entity.
+
148 break;
+
149 }
+
150 else if (text[chr_end] == '&' || ctype.is(ctype.space, text[chr_end])) {
+
151 // This char cannot possibly be a part of entity.
+
152 break;
+
153 }
+
154 }
+
155 }
+
156 buf[0] = text[start];
+
157 buf[1] = 0;
+
158 chr_end = start + 1;
+
159 return buf;
+
160 }
+
162
+
163 public:
+
164 interval<size_t> interval;
+
165
+
166 protected:
+
167 std::locale m_locale;
+
168 };
+
169
+
170 using parser = basic_parser<char>;
+
171 using wparser = basic_parser<wchar_t>;
+
172#ifdef _UNICODE
+
173 using tparser = wparser;
+
174#else
+
175 using tparser = parser;
+
176#endif
+
177 using sgml_parser = basic_parser<char>;
+
178
+
182 template <class T>
+
183 class basic_noop : public basic_parser<T>
+
184 {
+
185 public:
+
186 virtual bool match(
+
187 _In_reads_or_z_(end) const T* text,
+
188 _In_ size_t start = 0,
+
189 _In_ size_t end = (size_t)-1,
+
190 _In_ int flags = match_default)
+
191 {
+
192 assert(text || start >= end);
+
193 if (start < end && text[start]) {
+
194 interval.start = interval.end = start;
+
195 return true;
+
196 }
+
197 interval.start = (interval.end = start) + 1;
+
198 return false;
+
199 }
+
200 };
+
201
+
202 using noop = basic_noop<char>;
+
203 using wnoop = basic_noop<wchar_t>;
+
204#ifdef _UNICODE
+
205 using tnoop = wnoop;
+
206#else
+
207 using tnoop = noop;
+
208#endif
+
209 using sgml_noop = basic_noop<char>;
+
210
+
214 template <class T>
+
215 class basic_any_cu : public basic_parser<T>
+
216 {
+
217 public:
+
218 basic_any_cu(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
+
219
+
220 virtual bool match(
+
221 _In_reads_or_z_(end) const T* text,
+
222 _In_ size_t start = 0,
+
223 _In_ size_t end = (size_t)-1,
+
224 _In_ int flags = match_default)
+
225 {
+
226 assert(text || start >= end);
+
227 if (start < end && text[start]) {
+
228 interval.end = (interval.start = start) + 1;
+
229 return true;
+
230 }
+
231 interval.start = (interval.end = start) + 1;
+
232 return false;
+
233 }
+
234 };
+
235
+
236 using any_cu = basic_any_cu<char>;
+
237 using wany_cu = basic_any_cu<wchar_t>;
+
238#ifdef _UNICODE
+
239 using tany_cu = wany_cu;
+
240#else
+
241 using tany_cu = any_cu;
+
242#endif
+
243
+
247 class sgml_any_cp : public basic_any_cu<char>
+
248 {
+
249 public:
+
250 sgml_any_cp(_In_ const std::locale& locale = std::locale()) : basic_any_cu<char>(locale) {}
+
251
+
252 virtual bool match(
+
253 _In_reads_or_z_(end) const char* text,
+
254 _In_ size_t start = 0,
+
255 _In_ size_t end = (size_t)-1,
+
256 _In_ int flags = match_default)
+
257 {
+
258 assert(text || start >= end);
+
259 if (start < end && text[start]) {
+
260 if (text[start] == '&') {
+
261 // SGML entity
+
262 const auto& ctype = std::use_facet<std::ctype<char>>(m_locale);
+
263 for (interval.end = start + 1; interval.end < end && text[interval.end]; interval.end++)
+
264 if (text[interval.end] == ';') {
+
265 interval.end++;
+
266 interval.start = start;
+
267 return true;
+
268 }
+
269 else if (text[interval.end] == '&' || ctype.is(ctype.space, text[interval.end]))
+
270 break;
+
271 // Unterminated entity
+
272 }
+
273 interval.end = (interval.start = start) + 1;
+
274 return true;
+
275 }
+
276 interval.start = (interval.end = start) + 1;
+
277 return false;
+
278 }
+
279 };
+
280
+
284 template <class T>
+
285 class basic_cu : public basic_parser<T>
+
286 {
+
287 public:
+
288 basic_cu(T chr, bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
289 basic_parser<T>(locale),
+
290 m_chr(chr),
+
291 m_invert(invert)
+
292 {}
+
293
+
294 virtual bool match(
+
295 _In_reads_or_z_(end) const T* text,
+
296 _In_ size_t start = 0,
+
297 _In_ size_t end = (size_t)-1,
+
298 _In_ int flags = match_default)
+
299 {
+
300 assert(text || start >= end);
+
301 if (start < end && text[start]) {
+
302 bool r;
+
303 if (flags & match_case_insensitive) {
+
304 const auto& ctype = std::use_facet<std::ctype<T>>(m_locale);
+
305 r = ctype.tolower(text[start]) == ctype.tolower(m_chr);
+
306 }
+
307 else
+
308 r = text[start] == m_chr;
+
309 if (r && !m_invert || !r && m_invert) {
+
310 interval.end = (interval.start = start) + 1;
+
311 return true;
+
312 }
+
313 }
+
314 interval.start = (interval.end = start) + 1;
+
315 return false;
+
316 }
+
317
+
318 protected:
+
319 T m_chr;
+
320 bool m_invert;
+
321 };
+
322
+
323 using cu = basic_cu<char>;
+
324 using wcu = basic_cu<wchar_t>;
+
325#ifdef _UNICODE
+
326 using tcu = wcu;
+
327#else
+
328 using tcu = cu;
+
329#endif
+
330
+
334 class sgml_cp : public sgml_parser
+
335 {
+
336 public:
+
337 sgml_cp(const char* chr, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
338 sgml_parser(locale),
+
339 m_invert(invert)
+
340 {
+
341 assert(chr || !count);
+
342 wchar_t buf[3];
+
343 size_t chr_end;
+
344 m_chr.assign(count ? next_sgml_cp(chr, 0, count, chr_end, buf) : L"");
+
345 }
+
346
+
347 virtual bool match(
+
348 _In_reads_or_z_(end) const char* text,
+
349 _In_ size_t start = 0,
+
350 _In_ size_t end = (size_t)-1,
+
351 _In_ int flags = match_default)
+
352 {
+
353 assert(text || start >= end);
+
354 if (start < end && text[start]) {
+
355 wchar_t buf[3];
+
356 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
357 bool r = ((flags & match_case_insensitive) ?
+
358 stdex::strnicmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size(), m_locale) :
+
359 stdex::strncmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size())) == 0;
+
360 if (r && !m_invert || !r && m_invert) {
+
361 interval.start = start;
+
362 return true;
+
363 }
+
364 }
+
365 interval.start = (interval.end = start) + 1;
+
366 return false;
+
367 }
+
368
+
369 protected:
+
370 std::wstring m_chr;
+
371 bool m_invert;
+
372 };
+
373
+
377 template <class T>
+
378 class basic_space_cu : public basic_parser<T>
+
379 {
+
380 public:
+
381 basic_space_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
382 basic_parser<T>(locale),
+
383 m_invert(invert)
+
384 {}
+
385
+
386 virtual bool match(
+
387 _In_reads_or_z_(end) const T* text,
+
388 _In_ size_t start = 0,
+
389 _In_ size_t end = (size_t)-1,
+
390 _In_ int flags = match_default)
+
391 {
+
392 assert(text || start >= end);
+
393 if (start < end && text[start]) {
+
394 bool r =
+
395 ((flags & match_multiline) || !islbreak(text[start])) &&
+
396 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::space, text[start]);
+
397 if (r && !m_invert || !r && m_invert) {
+
398 interval.end = (interval.start = start) + 1;
+
399 return true;
+
400 }
+
401 }
+
402 interval.start = (interval.end = start) + 1;
+
403 return false;
+
404 }
+
405
+
406 protected:
+
407 bool m_invert;
+
408 };
+
409
+
410 using space_cu = basic_space_cu<char>;
+
411 using wspace_cu = basic_space_cu<wchar_t>;
+
412#ifdef _UNICODE
+
413 using tspace_cu = wspace_cu;
+
414#else
+
415 using tspace_cu = space_cu;
+
416#endif
+
417
+
421 class sgml_space_cp : public basic_space_cu<char>
+
422 {
+
423 public:
+
424 sgml_space_cp(_In_ bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
425 basic_space_cu<char>(invert, locale)
+
426 {}
+
427
+
428 virtual bool match(
+
429 _In_reads_or_z_(end) const char* text,
+
430 _In_ size_t start = 0,
+
431 _In_ size_t end = (size_t)-1,
+
432 _In_ int flags = match_default)
+
433 {
+
434 assert(text || start >= end);
+
435 if (start < end && text[start]) {
+
436 wchar_t buf[3];
+
437 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
438 const wchar_t* chr_end = chr + stdex::strlen(chr);
+
439 bool r =
+
440 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
+
441 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space, chr, chr_end) == chr_end;
+
442 if (r && !m_invert || !r && m_invert) {
+
443 interval.start = start;
+
444 return true;
+
445 }
+
446 }
+
447
+
448 interval.start = (interval.end = start) + 1;
+
449 return false;
+
450 }
+
451 };
+
452
+
456 template <class T>
+
457 class basic_punct_cu : public basic_parser<T>
+
458 {
+
459 public:
+
460 basic_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
461 basic_parser<T>(locale),
+
462 m_invert(invert)
+
463 {}
+
464
+
465 virtual bool match(
+
466 _In_reads_or_z_(end) const T* text,
+
467 _In_ size_t start = 0,
+
468 _In_ size_t end = (size_t)-1,
+
469 _In_ int flags = match_default)
+
470 {
+
471 assert(text || start >= end);
+
472 if (start < end && text[start]) {
+
473 bool r = std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::punct, text[start]);
+
474 if (r && !m_invert || !r && m_invert) {
+
475 interval.end = (interval.start = start) + 1;
+
476 return true;
+
477 }
+
478 }
+
479 interval.start = (interval.end = start) + 1;
+
480 return false;
+
481 }
+
482
+
483 protected:
+
484 bool m_invert;
+
485 };
+
486
+
487 using punct_cu = basic_punct_cu<char>;
+
488 using wpunct_cu = basic_punct_cu<wchar_t>;
+
489#ifdef _UNICODE
+
490 using tpunct_cu = wpunct_cu;
+
491#else
+
492 using tpunct_cu = punct_cu;
+
493#endif
+
494
+
498 class sgml_punct_cp : public basic_punct_cu<char>
+
499 {
+
500 public:
+
501 sgml_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
502 basic_punct_cu<char>(invert, locale)
+
503 {}
+
504
+
505 virtual bool match(
+
506 _In_reads_or_z_(end) const char* text,
+
507 _In_ size_t start = 0,
+
508 _In_ size_t end = (size_t)-1,
+
509 _In_ int flags = match_default)
+
510 {
+
511 assert(text || start >= end);
+
512 if (start < end && text[start]) {
+
513 wchar_t buf[3];
+
514 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
515 const wchar_t* chr_end = chr + stdex::strlen(chr);
+
516 bool r = std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::punct, chr, chr_end) == chr_end;
+
517 if (r && !m_invert || !r && m_invert) {
+
518 interval.start = start;
+
519 return true;
+
520 }
+
521 }
+
522 interval.start = (interval.end = start) + 1;
+
523 return false;
+
524 }
+
525 };
+
526
+
530 template <class T>
+
531 class basic_space_or_punct_cu : public basic_parser<T>
+
532 {
+
533 public:
+
534 basic_space_or_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
535 basic_parser<T>(locale),
+
536 m_invert(invert)
+
537 {}
+
538
+
539 virtual bool match(
+
540 _In_reads_or_z_(end) const T* text,
+
541 _In_ size_t start = 0,
+
542 _In_ size_t end = (size_t)-1,
+
543 _In_ int flags = match_default)
+
544 {
+
545 assert(text || start >= end);
+
546 if (start < end && text[start]) {
+
547 bool r =
+
548 ((flags & match_multiline) || !islbreak(text[start])) &&
+
549 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::space | std::ctype_base::punct, text[start]);
+
550 if (r && !m_invert || !r && m_invert) {
+
551 interval.end = (interval.start = start) + 1;
+
552 return true;
+
553 }
+
554 }
+
555 interval.start = (interval.end = start) + 1;
+
556 return false;
+
557 }
+
558
+
559 protected:
+
560 bool m_invert;
+
561 };
+
562
+
563 using space_or_punct_cu = basic_space_or_punct_cu<char>;
+
564 using wspace_or_punct_cu = basic_space_or_punct_cu<wchar_t>;
+
565#ifdef _UNICODE
+
566 using tspace_or_punct_cu = wspace_or_punct_cu;
+
567#else
+
568 using tspace_or_punct_cu = space_or_punct_cu;
+
569#endif
+
570
+
574 class sgml_space_or_punct_cp : public basic_space_or_punct_cu<char>
+
575 {
+
576 public:
+
577 sgml_space_or_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
578 basic_space_or_punct_cu<char>(invert, locale)
+
579 {}
+
580
+
581 virtual bool match(
+
582 _In_reads_or_z_(end) const char* text,
+
583 _In_ size_t start = 0,
+
584 _In_ size_t end = (size_t)-1,
+
585 _In_ int flags = match_default)
+
586 {
+
587 assert(text || start >= end);
+
588 if (start < end && text[start]) {
+
589 wchar_t buf[3];
+
590 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
591 const wchar_t* chr_end = chr + stdex::strlen(chr);
+
592 bool r =
+
593 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
+
594 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space | std::ctype_base::punct, chr, chr_end) == chr_end;
+
595 if (r && !m_invert || !r && m_invert) {
+
596 interval.start = start;
+
597 return true;
+
598 }
+
599 }
+
600 interval.start = (interval.end = start) + 1;
+
601 return false;
+
602 }
+
603 };
+
604
+
608 template <class T>
+
609 class basic_bol : public basic_parser<T>
+
610 {
+
611 public:
+
612 basic_bol(bool invert = false) : m_invert(invert) {}
+
613
+
614 virtual bool match(
+
615 _In_reads_or_z_(end) const T* text,
+
616 _In_ size_t start = 0,
+
617 _In_ size_t end = (size_t)-1,
+
618 _In_ int flags = match_default)
+
619 {
+
620 assert(text || start >= end);
+
621 bool r = start == 0 || start <= end && islbreak(text[start - 1]);
+
622 if (r && !m_invert || !r && m_invert) {
+
623 interval.end = interval.start = start;
+
624 return true;
+
625 }
+
626 interval.start = (interval.end = start) + 1;
+
627 return false;
+
628 }
+
629
+
630 protected:
+
631 bool m_invert;
+
632 };
+
633
+
634 using bol = basic_bol<char>;
+
635 using wbol = basic_bol<wchar_t>;
+
636#ifdef _UNICODE
+
637 using tbol = wbol;
+
638#else
+
639 using tbol = bol;
+
640#endif
+
641 using sgml_bol = basic_bol<char>;
+
642
+
646 template <class T>
+
647 class basic_eol : public basic_parser<T>
+
648 {
+
649 public:
+
650 basic_eol(bool invert = false) : m_invert(invert) {}
+
651
+
652 virtual bool match(
+
653 _In_reads_or_z_(end) const T* text,
+
654 _In_ size_t start = 0,
+
655 _In_ size_t end = (size_t)-1,
+
656 _In_ int flags = match_default)
+
657 {
+
658 assert(text || start >= end);
+
659 bool r = islbreak(text[start]);
+
660 if (r && !m_invert || !r && m_invert) {
+
661 interval.end = interval.start = start;
+
662 return true;
+
663 }
+
664 interval.start = (interval.end = start) + 1;
+
665 return false;
+
666 }
+
667
+
668 protected:
+
669 bool m_invert;
+
670 };
+
671
+
672 using eol = basic_eol<char>;
+
673 using weol = basic_eol<wchar_t>;
+
674#ifdef _UNICODE
+
675 using teol = weol;
+
676#else
+
677 using teol = eol;
+
678#endif
+
679 using sgml_eol = basic_eol<char>;
+
680
+
681 template <class T>
+
682 class basic_set : public basic_parser<T>
+
683 {
+
684 public:
+
685 basic_set(bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
686 basic_parser<T>(locale),
+
687 hit_offset((size_t)-1),
+
688 m_invert(invert)
+
689 {}
+
690
+
691 virtual bool match(
+
692 _In_reads_or_z_(end) const T* text,
+
693 _In_ size_t start = 0,
+
694 _In_ size_t end = (size_t)-1,
+
695 _In_ int flags = match_default) = 0;
+
696
+
697 virtual void invalidate()
+
698 {
+
699 hit_offset = (size_t)-1;
+
700 basic_parser<T>::invalidate();
+
701 }
+
702
+
703 public:
+
704 size_t hit_offset;
+
705
+
706 protected:
+
707 bool m_invert;
+
708 };
+
709
+
713 template <class T>
+
714 class basic_cu_set : public basic_set<T>
+
715 {
+
716 public:
+
717 basic_cu_set(
+
718 _In_reads_or_z_(count) const T* set,
+
719 _In_ size_t count = (size_t)-1,
+
720 _In_ bool invert = false,
+
721 _In_ const std::locale& locale = std::locale()) :
+
722 basic_set<T>(invert, locale)
+
723 {
+
724 if (set)
+
725 m_set.assign(set, set + stdex::strnlen(set, count));
+
726 }
+
727
+
728 virtual bool match(
+
729 _In_reads_or_z_(end) const T* text,
+
730 _In_ size_t start = 0,
+
731 _In_ size_t end = (size_t)-1,
+
732 _In_ int flags = match_default)
+
733 {
+
734 assert(text || start >= end);
+
735 if (start < end && text[start]) {
+
736 const T* set = m_set.c_str();
+
737 size_t r = (flags & match_case_insensitive) ?
+
738 stdex::strnichr(set, m_set.size(), text[start], m_locale) :
+
739 stdex::strnchr(set, m_set.size(), text[start]);
+
740 if (r != stdex::npos && !m_invert || r == stdex::npos && m_invert) {
+
741 hit_offset = r;
+
742 interval.end = (interval.start = start) + 1;
+
743 return true;
+
744 }
+
745 }
+
746 hit_offset = (size_t)-1;
+
747 interval.start = (interval.end = start) + 1;
+
748 return false;
+
749 }
+
750
+
751 protected:
+
752 std::basic_string<T> m_set;
+
753 };
+
754
+
755 using cu_set = basic_cu_set<char>;
+
756 using wcu_set = basic_cu_set<wchar_t>;
+
757#ifdef _UNICODE
+
758 using tcu_set = wcu_set;
+
759#else
+
760 using tcu_set = cu_set;
+
761#endif
+
762
+
766 class sgml_cp_set : public basic_set<char>
+
767 {
+
768 public:
+
769 sgml_cp_set(const char* set, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
+
770 basic_set<char>(invert, locale)
+
771 {
+
772 if (set)
+
773 m_set = sgml2wstr(set, count);
+
774 }
+
775
+
776 virtual bool match(
+
777 _In_reads_or_z_(end) const char* text,
+
778 _In_ size_t start = 0,
+
779 _In_ size_t end = (size_t)-1,
+
780 _In_ int flags = match_default)
+
781 {
+
782 assert(text || start >= end);
+
783 if (start < end && text[start]) {
+
784 wchar_t buf[3];
+
785 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
786 const wchar_t* set = m_set.c_str();
+
787 size_t r = (flags & match_case_insensitive) ?
+
788 stdex::strnistr(set, m_set.size(), chr, m_locale) :
+
789 stdex::strnstr(set, m_set.size(), chr);
+
790 if (r != stdex::npos && !m_invert || r == stdex::npos && m_invert) {
+
791 hit_offset = r;
+
792 interval.start = start;
+
793 return true;
+
794 }
+
795 }
+
796 hit_offset = (size_t)-1;
+
797 interval.start = (interval.end = start) + 1;
+
798 return false;
+
799 }
+
800
+
801 protected:
+
802 std::wstring m_set;
+
803 };
+
804
+
808 template <class T>
+
809 class basic_string : public basic_parser<T>
+
810 {
+
811 public:
+
812 basic_string(
+
813 _In_reads_or_z_(count) const T* str,
+
814 _In_ size_t count = (size_t)-1,
+
815 _In_ const std::locale& locale = std::locale()) :
+
816 basic_parser<T>(locale),
+
817 m_str(str, str + stdex::strnlen(str, count))
+
818 {}
+
819
+
820 virtual bool match(
+
821 _In_reads_or_z_(end) const T* text,
+
822 _In_ size_t start = 0,
+
823 _In_ size_t end = (size_t)-1,
+
824 _In_ int flags = match_default)
+
825 {
+
826 assert(text || start >= end);
+
827 size_t
+
828 m = m_str.size(),
+
829 n = std::min<size_t>(end - start, m);
+
830 bool r = ((flags & match_case_insensitive) ?
+
831 stdex::strnicmp(text + start, n, m_str.c_str(), m, m_locale) :
+
832 stdex::strncmp(text + start, n, m_str.c_str(), m)) == 0;
+
833 if (r) {
+
834 interval.end = (interval.start = start) + n;
+
835 return true;
+
836 }
+
837 interval.start = (interval.end = start) + 1;
+
838 return false;
+
839 }
+
840
+
841 protected:
+
842 std::basic_string<T> m_str;
+
843 };
+
844
+
845 using string = basic_string<char>;
+
846 using wstring = basic_string<wchar_t>;
+
847#ifdef _UNICODE
+
848 using tstring = wstring;
+
849#else
+
850 using tstring = string;
+
851#endif
+
852
+
856 class sgml_string : public sgml_parser
+
857 {
+
858 public:
+
859 sgml_string(const char* str, size_t count = (size_t)-1, _In_ const std::locale& locale = std::locale()) :
+
860 sgml_parser(locale),
+
861 m_str(sgml2wstr(str, count))
+
862 {}
+
863
+
864 virtual bool match(
+
865 _In_reads_or_z_(end) const char* text,
+
866 _In_ size_t start = 0,
+
867 _In_ size_t end = (size_t)-1,
+
868 _In_ int flags = match_default)
+
869 {
+
870 assert(text || start >= end);
+
871 const wchar_t* str = m_str.c_str();
+
872 const bool case_insensitive = flags & match_case_insensitive ? true : false;
+
873 const auto& ctype = std::use_facet<std::ctype<wchar_t>>(m_locale);
+
874 for (interval.end = start;;) {
+
875 if (!*str) {
+
876 interval.start = start;
+
877 return true;
+
878 }
+
879 if (interval.end >= end || !text[interval.end]) {
+
880 interval.start = (interval.end = start) + 1;
+
881 return false;
+
882 }
+
883 wchar_t buf[3];
+
884 const wchar_t* chr = next_sgml_cp(text, interval.end, end, interval.end, buf);
+
885 for (; *chr; ++str, ++chr) {
+
886 if (!*str ||
+
887 (case_insensitive ? ctype.tolower(*str) != ctype.tolower(*chr) : *str != *chr))
+
888 {
+
889 interval.start = (interval.end = start) + 1;
+
890 return false;
+
891 }
+
892 }
+
893 }
+
894 }
+
895
+
896 protected:
+
897 std::wstring m_str;
+
898 };
+
899
+
903 template <class T>
+
904 class basic_iterations : public basic_parser<T>
+
905 {
+
906 public:
+
907 basic_iterations(const std::shared_ptr<basic_parser<T>>& el, size_t min_iterations = 0, size_t max_iterations = (size_t)-1, bool greedy = true) :
+
908 m_el(el),
+
909 m_min_iterations(min_iterations),
+
910 m_max_iterations(max_iterations),
+
911 m_greedy(greedy)
+
912 {}
+
913
+
914 virtual bool match(
+
915 _In_reads_or_z_(end) const T* text,
+
916 _In_ size_t start = 0,
+
917 _In_ size_t end = (size_t)-1,
+
918 _In_ int flags = match_default)
+
919 {
+
920 assert(text || start >= end);
+
921 interval.start = interval.end = start;
+
922 for (size_t i = 0; ; i++) {
+
923 if (!m_greedy && i >= m_min_iterations || i >= m_max_iterations)
+
924 return true;
+
925 if (!m_el->match(text, interval.end, end, flags)) {
+
926 if (i >= m_min_iterations)
+
927 return true;
+
928 break;
+
929 }
+
930 if (m_el->interval.end == interval.end) {
+
931 // Element did match, but the matching interval was empty. Quit instead of spinning.
+
932 return true;
+
933 }
+
934 interval.end = m_el->interval.end;
+
935 }
+
936 interval.start = (interval.end = start) + 1;
+
937 return false;
+
938 }
+
939
+
940 protected:
+
941 std::shared_ptr<basic_parser<T>> m_el;
+
942 size_t m_min_iterations;
+
943 size_t m_max_iterations;
+
944 bool m_greedy;
+
945 };
+
946
+
947 using iterations = basic_iterations<char>;
+
948 using witerations = basic_iterations<wchar_t>;
+
949#ifdef _UNICODE
+
950 using titerations = witerations;
+
951#else
+
952 using titerations = iterations;
+
953#endif
+
954 using sgml_iterations = basic_iterations<char>;
+
955
+
959 template <class T>
+
960 class parser_collection : public basic_parser<T>
+
961 {
+
962 protected:
+
963 parser_collection(_In_ const std::locale& locale) : basic_parser<T>(locale) {}
+
964
+
965 public:
+
966 parser_collection(
+
967 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el,
+
968 _In_ size_t count,
+
969 _In_ const std::locale& locale = std::locale()) :
+
970 basic_parser<T>(locale)
+
971 {
+
972 assert(el || !count);
+
973 m_collection.reserve(count);
+
974 for (size_t i = 0; i < count; i++)
+
975 m_collection.push_back(el[i]);
+
976 }
+
977
+
978 parser_collection(
+
979 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
+
980 _In_ const std::locale& locale = std::locale()) :
+
981 basic_parser<T>(locale),
+
982 m_collection(std::move(collection))
+
983 {}
+
984
+
985 virtual void invalidate()
+
986 {
+
987 for (auto& el: m_collection)
+
988 el->invalidate();
+
989 basic_parser<T>::invalidate();
+
990 }
+
991
+
992 protected:
+
993 std::vector<std::shared_ptr<basic_parser<T>>> m_collection;
+
994 };
+
995
+
999 template <class T>
+
1000 class basic_sequence : public parser_collection<T>
+
1001 {
+
1002 public:
+
1003 basic_sequence(
+
1004 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
+
1005 _In_ size_t count = 0,
+
1006 _In_ const std::locale& locale = std::locale()) :
+
1007 parser_collection<T>(el, count, locale)
+
1008 {}
+
1009
+
1010 basic_sequence(
+
1011 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
+
1012 _In_ const std::locale& locale = std::locale()) :
+
1013 parser_collection<T>(std::move(collection), locale)
+
1014 {}
+
1015
+
1016 virtual bool match(
+
1017 _In_reads_or_z_(end) const T* text,
+
1018 _In_ size_t start = 0,
+
1019 _In_ size_t end = (size_t)-1,
+
1020 _In_ int flags = match_default)
+
1021 {
+
1022 assert(text || start >= end);
+
1023 interval.end = start;
+
1024 for (auto i = m_collection.begin(); i != m_collection.end(); ++i) {
+
1025 if (!(*i)->match(text, interval.end, end, flags)) {
+
1026 for (++i; i != m_collection.end(); ++i)
+
1027 (*i)->invalidate();
+
1028 interval.start = (interval.end = start) + 1;
+
1029 return false;
+
1030 }
+
1031 interval.end = (*i)->interval.end;
+
1032 }
+
1033 interval.start = start;
+
1034 return true;
+
1035 }
+
1036 };
+
1037
+
1038 using sequence = basic_sequence<char>;
+
1039 using wsequence = basic_sequence<wchar_t>;
+
1040#ifdef _UNICODE
+
1041 using tsequence = wsequence;
+
1042#else
+
1043 using tsequence = sequence;
+
1044#endif
+
1045 using sgml_sequence = basic_sequence<char>;
+
1046
+
1050 template <class T>
+
1051 class basic_branch : public parser_collection<T>
+
1052 {
+
1053 protected:
+
1054 basic_branch(_In_ const std::locale& locale) :
+
1055 parser_collection<T>(locale),
+
1056 hit_offset((size_t)-1)
+
1057 {}
+
1058
+
1059 public:
+
1060 basic_branch(
+
1061 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
+
1062 _In_ size_t count = 0,
+
1063 _In_ const std::locale& locale = std::locale()) :
+
1064 parser_collection<T>(el, count, locale),
+
1065 hit_offset((size_t)-1)
+
1066 {}
+
1067
+
1068 basic_branch(
+
1069 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
+
1070 _In_ const std::locale& locale = std::locale()) :
+
1071 parser_collection<T>(std::move(collection), locale),
+
1072 hit_offset((size_t)-1)
+
1073 {}
+
1074
+
1075 virtual bool match(
+
1076 _In_reads_or_z_(end) const T* text,
+
1077 _In_ size_t start = 0,
+
1078 _In_ size_t end = (size_t)-1,
+
1079 _In_ int flags = match_default)
+
1080 {
+
1081 assert(text || start >= end);
+
1082 hit_offset = 0;
+
1083 for (auto i = m_collection.begin(); i != m_collection.end(); ++i, ++hit_offset) {
+
1084 if ((*i)->match(text, start, end, flags)) {
+
1085 interval = (*i)->interval;
+
1086 for (++i; i != m_collection.end(); ++i)
+
1087 (*i)->invalidate();
+
1088 return true;
+
1089 }
+
1090 }
+
1091 hit_offset = (size_t)-1;
+
1092 interval.start = (interval.end = start) + 1;
+
1093 return false;
+
1094 }
+
1095
+
1096 virtual void invalidate()
+
1097 {
+
1098 hit_offset = (size_t)-1;
+
1099 parser_collection<T>::invalidate();
+
1100 }
+
1101
+
1102 public:
+
1103 size_t hit_offset;
+
1104 };
+
1105
+
1106 using branch = basic_branch<char>;
+
1107 using wbranch = basic_branch<wchar_t>;
+
1108#ifdef _UNICODE
+
1109 using tbranch = wbranch;
+
1110#else
+
1111 using tbranch = branch;
+
1112#endif
+
1113 using sgml_branch = basic_branch<char>;
+
1114
+
1118 template <class T, class T_parser = basic_string<T>>
+
1119 class basic_string_branch : public basic_branch<T>
+
1120 {
+
1121 public:
+
1122 inline basic_string_branch(
+
1123 _In_reads_(count) const T* str_z = nullptr,
+
1124 _In_ size_t count = 0,
+
1125 _In_ const std::locale& locale = std::locale()) :
+
1126 basic_branch<T>(locale)
+
1127 {
+
1128 build(str_z, count);
+
1129 }
+
1130
+
1131 inline basic_string_branch(_In_z_ const T* str, ...) :
+
1132 basic_branch<T>(std::locale())
+
1133 {
+
1134 va_list params;
+
1135 va_start(params, str);
+
1136 build(str, params);
+
1137 va_end(params);
+
1138 }
+
1139
+
1140 inline basic_string_branch(_In_ const std::locale& locale, _In_z_ const T* str, ...) :
+
1141 basic_branch<T>(locale)
+
1142 {
+
1143 va_list params;
+
1144 va_start(params, str);
+
1145 build(str, params);
+
1146 va_end(params);
+
1147 }
+
1148
+
1149 protected:
+
1150 void build(_In_reads_(count) const T* str_z, _In_ size_t count)
+
1151 {
+
1152 assert(str_z || !count);
+
1153 if (count) {
+
1154 size_t offset, n;
+
1155 for (
+
1156 offset = n = 0;
+
1157 offset < count && str_z[offset];
+
1158 offset += stdex::strnlen(str_z + offset, count - offset) + 1, ++n);
+
1159 m_collection.reserve(n);
+
1160 for (
+
1161 offset = 0;
+
1162 offset < count && str_z[offset];
+
1163 offset += stdex::strnlen(str_z + offset, count - offset) + 1)
+
1164 m_collection.push_back(std::move(std::make_shared<T_parser>(str_z + offset, count - offset, m_locale)));
+
1165 }
+
1166 }
+
1167
+
1168 void build(_In_z_ const T* str, _In_ va_list params)
+
1169 {
+
1170 const T* p;
+
1171 for (
+
1172 m_collection.push_back(std::move(std::make_shared<T_parser>(str, (size_t)-1, m_locale)));
+
1173 (p = va_arg(params, const T*)) != nullptr;
+
1174 m_collection.push_back(std::move(std::make_shared<T_parser>(p, (size_t)-1, m_locale))));
+
1175 }
+
1176 };
+
1177
+
1178 using string_branch = basic_string_branch<char>;
+
1179 using wstring_branch = basic_string_branch<wchar_t>;
+
1180#ifdef _UNICODE
+
1181 using tstring_branch = wstring_branch;
+
1182#else
+
1183 using tstring_branch = string_branch;
+
1184#endif
+
1185 using sgml_string_branch = basic_string_branch<char, sgml_string>;
+
1186
+
1190 template <class T>
+
1191 class basic_permutation : public parser_collection<T>
+
1192 {
+
1193 public:
+
1194 basic_permutation(
+
1195 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
+
1196 _In_ size_t count = 0,
+
1197 _In_ const std::locale& locale = std::locale()) :
+
1198 parser_collection<T>(el, count, locale)
+
1199 {}
+
1200
+
1201 basic_permutation(
+
1202 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
+
1203 _In_ const std::locale& locale = std::locale()) :
+
1204 parser_collection<T>(std::move(collection), locale)
+
1205 {}
+
1206
+
1207 virtual bool match(
+
1208 _In_reads_or_z_(end) const T* text,
+
1209 _In_ size_t start = 0,
+
1210 _In_ size_t end = (size_t)-1,
+
1211 _In_ int flags = match_default)
+
1212 {
+
1213 assert(text || start >= end);
+
1214 for (auto& el: m_collection)
+
1215 el->invalidate();
+
1216 if (match_recursively(text, start, end, flags)) {
+
1217 interval.start = start;
+
1218 return true;
+
1219 }
+
1220 interval.start = (interval.end = start) + 1;
+
1221 return false;
+
1222 }
+
1223
+
1224 protected:
+
1225 bool match_recursively(
+
1226 _In_reads_or_z_(end) const T* text,
+
1227 _In_ size_t start = 0,
+
1228 _In_ size_t end = (size_t)-1,
+
1229 _In_ int flags = match_default)
+
1230 {
+
1231 bool all_matched = true;
+
1232 for (auto& el: m_collection) {
+
1233 if (!el->interval) {
+
1234 // Element was not matched in permutatuion yet.
+
1235 all_matched = false;
+
1236 if (el->match(text, start, end, flags)) {
+
1237 // Element matched for the first time.
+
1238 if (match_recursively(text, el->interval.end, end, flags)) {
+
1239 // Rest of the elements matched too.
+
1240 return true;
+
1241 }
+
1242 el->invalidate();
+
1243 }
+
1244 }
+
1245 }
+
1246 if (all_matched) {
+
1247 interval.end = start;
+
1248 return true;
+
1249 }
+
1250 return false;
+
1251 }
+
1252 };
+
1253
+
1254 using permutation = basic_permutation<char>;
+
1255 using wpermutation = basic_permutation<wchar_t>;
+
1256#ifdef _UNICODE
+
1257 using tpermutation = wpermutation;
+
1258#else
+
1259 using tpermutation = permutation;
+
1260#endif
+
1261 using sgml_permutation = basic_permutation<char>;
+
1262
+
1266 template <class T>
+
1267 class basic_integer : public basic_parser<T>
+
1268 {
+
1269 public:
+
1270 basic_integer(_In_ const std::locale& locale = std::locale()) :
+
1271 basic_parser<T>(locale),
+
1272 value(0)
+
1273 {}
+
1274
+
1275 virtual void invalidate()
+
1276 {
+
1277 value = 0;
+
1278 basic_parser<T>::invalidate();
+
1279 }
+
1280
+
1281 public:
+
1282 size_t value;
+
1283 };
+
1284
+
1288 template <class T>
+
1289 class basic_integer10 : public basic_integer<T>
+
1290 {
+
1291 public:
+
1292 basic_integer10(
+
1293 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
+
1294 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
+
1295 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
+
1296 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
+
1297 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
+
1298 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
+
1299 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
+
1300 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
+
1301 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
+
1302 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
+
1303 _In_ const std::locale& locale = std::locale()) :
+
1304 basic_integer<T>(locale),
+
1305 m_digit_0(digit_0),
+
1306 m_digit_1(digit_1),
+
1307 m_digit_2(digit_2),
+
1308 m_digit_3(digit_3),
+
1309 m_digit_4(digit_4),
+
1310 m_digit_5(digit_5),
+
1311 m_digit_6(digit_6),
+
1312 m_digit_7(digit_7),
+
1313 m_digit_8(digit_8),
+
1314 m_digit_9(digit_9)
+
1315 {}
+
1316
+
1317 virtual bool match(
+
1318 _In_reads_or_z_(end) const T* text,
+
1319 _In_ size_t start = 0,
+
1320 _In_ size_t end = (size_t)-1,
+
1321 _In_ int flags = match_default)
+
1322 {
+
1323 assert(text || start >= end);
+
1324 for (interval.end = start, value = 0; interval.end < end && text[interval.end];) {
+
1325 size_t dig;
+
1326 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; interval.end = m_digit_0->interval.end; }
+
1327 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; interval.end = m_digit_1->interval.end; }
+
1328 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; interval.end = m_digit_2->interval.end; }
+
1329 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; interval.end = m_digit_3->interval.end; }
+
1330 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; interval.end = m_digit_4->interval.end; }
+
1331 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; interval.end = m_digit_5->interval.end; }
+
1332 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; interval.end = m_digit_6->interval.end; }
+
1333 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; interval.end = m_digit_7->interval.end; }
+
1334 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; interval.end = m_digit_8->interval.end; }
+
1335 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; interval.end = m_digit_9->interval.end; }
+
1336 else break;
+
1337 value = value * 10 + dig;
+
1338 }
+
1339 if (start < interval.end) {
+
1340 interval.start = start;
+
1341 return true;
+
1342 }
+
1343 interval.start = (interval.end = start) + 1;
+
1344 return false;
+
1345 }
+
1346
+
1347 protected:
+
1348 std::shared_ptr<basic_parser<T>>
+
1349 m_digit_0,
+
1350 m_digit_1,
+
1351 m_digit_2,
+
1352 m_digit_3,
+
1353 m_digit_4,
+
1354 m_digit_5,
+
1355 m_digit_6,
+
1356 m_digit_7,
+
1357 m_digit_8,
+
1358 m_digit_9;
+
1359 };
+
1360
+
1361 using integer10 = basic_integer10<char>;
+
1362 using winteger10 = basic_integer10<wchar_t>;
+
1363#ifdef _UNICODE
+
1364 using tinteger10 = winteger10;
+
1365#else
+
1366 using tinteger10 = integer10;
+
1367#endif
+
1368 using sgml_integer10 = basic_integer10<char>;
+
1369
+
1373 template <class T>
+
1374 class basic_integer10ts : public basic_integer<T>
+
1375 {
+
1376 public:
+
1377 basic_integer10ts(
+
1378 _In_ const std::shared_ptr<basic_integer10<T>>& digits,
+
1379 _In_ const std::shared_ptr<basic_set<T>>& separator,
+
1380 _In_ const std::locale& locale = std::locale()) :
+
1381 basic_integer<T>(locale),
+
1382 digit_count(0),
+
1383 has_separators(false),
+
1384 m_digits(digits),
+
1385 m_separator(separator)
+
1386 {}
+
1387
+
1388 virtual bool match(
+
1389 _In_reads_or_z_(end) const T* text,
+
1390 _In_ size_t start = 0,
+
1391 _In_ size_t end = (size_t)-1,
+
1392 _In_ int flags = match_default)
+
1393 {
+
1394 assert(text || start >= end);
+
1395 if (m_digits->match(text, start, end, flags)) {
+
1396 // Leading part match.
+
1397 value = m_digits->value;
+
1398 digit_count = m_digits->interval.size();
+
1399 has_separators = false;
+
1400 interval.start = start;
+
1401 interval.end = m_digits->interval.end;
+
1402 if (m_digits->interval.size() <= 3) {
+
1403 // Maybe separated with thousand separators?
+
1404 size_t hit_offset = (size_t)-1;
+
1405 while (m_separator->match(text, interval.end, end, flags) &&
+
1406 (hit_offset == (size_t)-1 || hit_offset == m_separator->hit_offset) && // All separators must be the same, no mixing.
+
1407 m_digits->match(text, m_separator->interval.end, end, flags) &&
+
1408 m_digits->interval.size() == 3)
+
1409 {
+
1410 // Thousand separator and three-digit integer followed.
+
1411 value = value * 1000 + m_digits->value;
+
1412 digit_count += 3;
+
1413 has_separators = true;
+
1414 interval.end = m_digits->interval.end;
+
1415 hit_offset = m_separator->hit_offset;
+
1416 }
+
1417 }
+
1418
+
1419 return true;
+
1420 }
+
1421 value = 0;
+
1422 interval.start = (interval.end = start) + 1;
+
1423 return false;
+
1424 }
+
1425
+
1426 virtual void invalidate()
+
1427 {
+
1428 digit_count = 0;
+
1429 has_separators = false;
+
1430 basic_integer<T>::invalidate();
+
1431 }
+
1432
+
1433 public:
+
1434 size_t digit_count;
+
1435 bool has_separators;
+
1436
+
1437 protected:
+
1438 std::shared_ptr<basic_integer10<T>> m_digits;
+
1439 std::shared_ptr<basic_set<T>> m_separator;
+
1440 };
+
1441
+
1442 using integer10ts = basic_integer10ts<char>;
+
1443 using winteger10ts = basic_integer10ts<wchar_t>;
+
1444#ifdef _UNICODE
+
1445 using tinteger10ts = winteger10ts;
+
1446#else
+
1447 using tinteger10ts = integer10ts;
+
1448#endif
+
1449 using sgml_integer10ts = basic_integer10ts<char>;
+
1450
+
1454 template <class T>
+
1455 class basic_integer16 : public basic_integer<T>
+
1456 {
+
1457 public:
+
1458 basic_integer16(
+
1459 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
+
1460 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
+
1461 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
+
1462 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
+
1463 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
+
1464 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
+
1465 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
+
1466 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
+
1467 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
+
1468 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
+
1469 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
+
1470 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
+
1471 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
+
1472 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
+
1473 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
+
1474 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
+
1475 _In_ const std::locale& locale = std::locale()) :
+
1476 basic_integer<T>(locale),
+
1477 m_digit_0(digit_0),
+
1478 m_digit_1(digit_1),
+
1479 m_digit_2(digit_2),
+
1480 m_digit_3(digit_3),
+
1481 m_digit_4(digit_4),
+
1482 m_digit_5(digit_5),
+
1483 m_digit_6(digit_6),
+
1484 m_digit_7(digit_7),
+
1485 m_digit_8(digit_8),
+
1486 m_digit_9(digit_9),
+
1487 m_digit_10(digit_10),
+
1488 m_digit_11(digit_11),
+
1489 m_digit_12(digit_12),
+
1490 m_digit_13(digit_13),
+
1491 m_digit_14(digit_14),
+
1492 m_digit_15(digit_15)
+
1493 {}
+
1494
+
1495 virtual bool match(
+
1496 _In_reads_or_z_(end) const T* text,
+
1497 _In_ size_t start = 0,
+
1498 _In_ size_t end = (size_t)-1,
+
1499 _In_ int flags = match_default)
+
1500 {
+
1501 assert(text || start >= end);
+
1502 for (interval.end = start, value = 0; interval.end < end && text[interval.end];) {
+
1503 size_t dig;
+
1504 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; interval.end = m_digit_0->interval.end; }
+
1505 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; interval.end = m_digit_1->interval.end; }
+
1506 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; interval.end = m_digit_2->interval.end; }
+
1507 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; interval.end = m_digit_3->interval.end; }
+
1508 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; interval.end = m_digit_4->interval.end; }
+
1509 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; interval.end = m_digit_5->interval.end; }
+
1510 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; interval.end = m_digit_6->interval.end; }
+
1511 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; interval.end = m_digit_7->interval.end; }
+
1512 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; interval.end = m_digit_8->interval.end; }
+
1513 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; interval.end = m_digit_9->interval.end; }
+
1514 else if (m_digit_10->match(text, interval.end, end, flags)) { dig = 10; interval.end = m_digit_10->interval.end; }
+
1515 else if (m_digit_11->match(text, interval.end, end, flags)) { dig = 11; interval.end = m_digit_11->interval.end; }
+
1516 else if (m_digit_12->match(text, interval.end, end, flags)) { dig = 12; interval.end = m_digit_12->interval.end; }
+
1517 else if (m_digit_13->match(text, interval.end, end, flags)) { dig = 13; interval.end = m_digit_13->interval.end; }
+
1518 else if (m_digit_14->match(text, interval.end, end, flags)) { dig = 14; interval.end = m_digit_14->interval.end; }
+
1519 else if (m_digit_15->match(text, interval.end, end, flags)) { dig = 15; interval.end = m_digit_15->interval.end; }
+
1520 else break;
+
1521 value = value * 16 + dig;
+
1522 }
+
1523 if (start < interval.end) {
+
1524 interval.start = start;
+
1525 return true;
+
1526 }
+
1527 interval.start = (interval.end = start) + 1;
+
1528 return false;
+
1529 }
+
1530
+
1531 protected:
+
1532 std::shared_ptr<basic_parser<T>>
+
1533 m_digit_0,
+
1534 m_digit_1,
+
1535 m_digit_2,
+
1536 m_digit_3,
+
1537 m_digit_4,
+
1538 m_digit_5,
+
1539 m_digit_6,
+
1540 m_digit_7,
+
1541 m_digit_8,
+
1542 m_digit_9,
+
1543 m_digit_10,
+
1544 m_digit_11,
+
1545 m_digit_12,
+
1546 m_digit_13,
+
1547 m_digit_14,
+
1548 m_digit_15;
+
1549 };
+
1550
+
1551 using integer16 = basic_integer16<char>;
+
1552 using winteger16 = basic_integer16<wchar_t>;
+
1553#ifdef _UNICODE
+
1554 using tinteger16 = winteger16;
+
1555#else
+
1556 using tinteger16 = integer16;
+
1557#endif
+
1558 using sgml_integer16 = basic_integer16<char>;
+
1559
+
1563 template <class T>
+
1564 class basic_roman_numeral : public basic_integer<T>
+
1565 {
+
1566 public:
+
1567 basic_roman_numeral(
+
1568 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
+
1569 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
+
1570 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
+
1571 _In_ const std::shared_ptr<basic_parser<T>>& digit_50,
+
1572 _In_ const std::shared_ptr<basic_parser<T>>& digit_100,
+
1573 _In_ const std::shared_ptr<basic_parser<T>>& digit_500,
+
1574 _In_ const std::shared_ptr<basic_parser<T>>& digit_1000,
+
1575 _In_ const std::shared_ptr<basic_parser<T>>& digit_5000,
+
1576 _In_ const std::shared_ptr<basic_parser<T>>& digit_10000,
+
1577 _In_ const std::locale& locale = std::locale()) :
+
1578 basic_integer<T>(locale),
+
1579 m_digit_1(digit_1),
+
1580 m_digit_5(digit_5),
+
1581 m_digit_10(digit_10),
+
1582 m_digit_50(digit_50),
+
1583 m_digit_100(digit_100),
+
1584 m_digit_500(digit_500),
+
1585 m_digit_1000(digit_1000),
+
1586 m_digit_5000(digit_5000),
+
1587 m_digit_10000(digit_10000)
+
1588 {}
+
1589
+
1590 virtual bool match(
+
1591 _In_reads_or_z_(end) const T* text,
+
1592 _In_ size_t start = 0,
+
1593 _In_ size_t end = (size_t)-1,
+
1594 _In_ int flags = match_default)
+
1595 {
+
1596 assert(text || start >= end);
+
1597 size_t
+
1598 dig[5] = { (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1 },
+
1599 end2;
+
1600
+
1601 for (interval.end = start, value = 0; interval.end < end && text[interval.end]; dig[3] = dig[2], dig[2] = dig[1], dig[1] = dig[0], interval.end = end2) {
+
1602 if (m_digit_1 && m_digit_1->match(text, interval.end, end, flags)) { dig[0] = 1; end2 = m_digit_1->interval.end; }
+
1603 else if (m_digit_5 && m_digit_5->match(text, interval.end, end, flags)) { dig[0] = 5; end2 = m_digit_5->interval.end; }
+
1604 else if (m_digit_10 && m_digit_10->match(text, interval.end, end, flags)) { dig[0] = 10; end2 = m_digit_10->interval.end; }
+
1605 else if (m_digit_50 && m_digit_50->match(text, interval.end, end, flags)) { dig[0] = 50; end2 = m_digit_50->interval.end; }
+
1606 else if (m_digit_100 && m_digit_100->match(text, interval.end, end, flags)) { dig[0] = 100; end2 = m_digit_100->interval.end; }
+
1607 else if (m_digit_500 && m_digit_500->match(text, interval.end, end, flags)) { dig[0] = 500; end2 = m_digit_500->interval.end; }
+
1608 else if (m_digit_1000 && m_digit_1000->match(text, interval.end, end, flags)) { dig[0] = 1000; end2 = m_digit_1000->interval.end; }
+
1609 else if (m_digit_5000 && m_digit_5000->match(text, interval.end, end, flags)) { dig[0] = 5000; end2 = m_digit_5000->interval.end; }
+
1610 else if (m_digit_10000 && m_digit_10000->match(text, interval.end, end, flags)) { dig[0] = 10000; end2 = m_digit_10000->interval.end; }
+
1611 else break;
+
1612
+
1613 // Store first digit.
+
1614 if (dig[4] == (size_t)-1) dig[4] = dig[0];
+
1615
+
1616 if (dig[3] == dig[2] && dig[2] == dig[1] && dig[1] == dig[0] && dig[0] != dig[4]) {
+
1617 // Same digit repeated four times. No-go, unless first digit. E.g. XIIII vs. XIV. MMMMMCD allowed, IIII also...
+
1618 break;
+
1619 }
+
1620 if (dig[0] <= dig[1]) {
+
1621 // Digit is less or equal previous one: add.
+
1622 value += dig[0];
+
1623 }
+
1624 else if (
+
1625 dig[1] == 1 && (dig[0] == 5 || dig[0] == 10) ||
+
1626 dig[1] == 10 && (dig[0] == 50 || dig[0] == 100) ||
+
1627 dig[1] == 100 && (dig[0] == 500 || dig[0] == 1000) ||
+
1628 dig[1] == 1000 && (dig[0] == 5000 || dig[0] == 10000))
+
1629 {
+
1630 // Digit is up to two orders bigger than previous one: subtract. But...
+
1631 if (dig[2] < dig[0]) {
+
1632 // Digit is also bigger than pre-previous one. E.g. VIX (V < X => invalid)
+
1633 break;
+
1634 }
+
1635 value -= dig[1]; // Cancel addition in the previous step.
+
1636 dig[0] -= dig[1]; // Combine last two digits.
+
1637 dig[1] = dig[2]; // The true previous digit is now pre-previous one. :)
+
1638 dig[2] = dig[3]; // The true pre-previous digit is now pre-pre-previous one. :)
+
1639 value += dig[0]; // Add combined value.
+
1640 }
+
1641 else {
+
1642 // New digit is too big than the previous one. E.g. VX (V < X => invalid)
+
1643 break;
+
1644 }
+
1645 }
+
1646 if (value) {
+
1647 interval.start = start;
+
1648 return true;
+
1649 }
+
1650 interval.start = (interval.end = start) + 1;
+
1651 return false;
+
1652 }
+
1653
+
1654 protected:
+
1655 std::shared_ptr<basic_parser<T>>
+
1656 m_digit_1,
+
1657 m_digit_5,
+
1658 m_digit_10,
+
1659 m_digit_50,
+
1660 m_digit_100,
+
1661 m_digit_500,
+
1662 m_digit_1000,
+
1663 m_digit_5000,
+
1664 m_digit_10000;
+
1665 };
+
1666
+
1667 using roman_numeral = basic_roman_numeral<char>;
+
1668 using wroman_numeral = basic_roman_numeral<wchar_t>;
+
1669#ifdef _UNICODE
+
1670 using troman_numeral = wroman_numeral;
+
1671#else
+
1672 using troman_numeral = roman_numeral;
+
1673#endif
+
1674 using sgml_roman_numeral = basic_roman_numeral<char>;
+
1675
+
1679 template <class T>
+
1680 class basic_fraction : public basic_parser<T>
+
1681 {
+
1682 public:
+
1683 basic_fraction(
+
1684 _In_ const std::shared_ptr<basic_parser<T>>& _numerator,
+
1685 _In_ const std::shared_ptr<basic_parser<T>>& _fraction_line,
+
1686 _In_ const std::shared_ptr<basic_parser<T>>& _denominator,
+
1687 _In_ const std::locale& locale = std::locale()) :
+
1688 basic_parser<T>(locale),
+
1689 numerator(_numerator),
+
1690 fraction_line(_fraction_line),
+
1691 denominator(_denominator)
+
1692 {}
+
1693
+
1694 virtual bool match(
+
1695 _In_reads_or_z_(end) const T* text,
+
1696 _In_ size_t start = 0,
+
1697 _In_ size_t end = (size_t)-1,
+
1698 _In_ int flags = match_default)
+
1699 {
+
1700 assert(text || start >= end);
+
1701 if (numerator->match(text, start, end, flags) &&
+
1702 fraction_line->match(text, numerator->interval.end, end, flags) &&
+
1703 denominator->match(text, fraction_line->interval.end, end, flags))
+
1704 {
+
1705 interval.start = start;
+
1706 interval.end = denominator->interval.end;
+
1707 return true;
+
1708 }
+
1709 numerator->invalidate();
+
1710 fraction_line->invalidate();
+
1711 denominator->invalidate();
+
1712 interval.start = (interval.end = start) + 1;
+
1713 return false;
+
1714 }
+
1715
+
1716 virtual void invalidate()
+
1717 {
+
1718 numerator->invalidate();
+
1719 fraction_line->invalidate();
+
1720 denominator->invalidate();
+
1721 basic_parser<T>::invalidate();
+
1722 }
+
1723
+
1724 public:
+
1725 std::shared_ptr<basic_parser<T>> numerator;
+
1726 std::shared_ptr<basic_parser<T>> fraction_line;
+
1727 std::shared_ptr<basic_parser<T>> denominator;
+
1728 };
+
1729
+
1730 using fraction = basic_fraction<char>;
+
1731 using wfraction = basic_fraction<wchar_t>;
+
1732#ifdef _UNICODE
+
1733 using tfraction = wfraction;
+
1734#else
+
1735 using tfraction = fraction;
+
1736#endif
+
1737 using sgml_fraction = basic_fraction<char>;
+
1738
+
1742 template <class T>
+
1743 class basic_score : public basic_parser<T>
+
1744 {
+
1745 public:
+
1746 basic_score(
+
1747 _In_ const std::shared_ptr<basic_parser<T>>& _home,
+
1748 _In_ const std::shared_ptr<basic_parser<T>>& _separator,
+
1749 _In_ const std::shared_ptr<basic_parser<T>>& _guest,
+
1750 _In_ const std::shared_ptr<basic_parser<T>>& space,
+
1751 _In_ const std::locale& locale = std::locale()) :
+
1752 basic_parser<T>(locale),
+
1753 home(_home),
+
1754 separator(_separator),
+
1755 guest(_guest),
+
1756 m_space(space)
+
1757 {}
+
1758
+
1759 virtual bool match(
+
1760 _In_reads_or_z_(end) const T* text,
+
1761 _In_ size_t start = 0,
+
1762 _In_ size_t end = (size_t)-1,
+
1763 _In_ int flags = match_default)
+
1764 {
+
1765 assert(text || start >= end);
+
1766 interval.end = start;
+
1767
+
1768 if (home->match(text, interval.end, end, flags))
+
1769 interval.end = home->interval.end;
+
1770 else
+
1771 goto end;
+
1772
+
1773 const int space_match_flags = flags & ~match_multiline; // Spaces in score must never be broken in new line.
+
1774 for (; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
1775
+
1776 if (separator->match(text, interval.end, end, flags))
+
1777 interval.end = separator->interval.end;
+
1778 else
+
1779 goto end;
1780
-
1781 if (guest->match(text, interval.end, end, flags))
-
1782 interval.end = guest->interval.end;
-
1783 else
-
1784 goto end;
-
1785
-
1786 interval.start = start;
-
1787 return true;
-
1788
-
1789 end:
-
1790 home->invalidate();
-
1791 separator->invalidate();
-
1792 guest->invalidate();
-
1793 interval.start = (interval.end = start) + 1;
-
1794 return false;
-
1795 }
-
1796
-
1797 virtual void invalidate()
-
1798 {
-
1799 home->invalidate();
-
1800 separator->invalidate();
-
1801 guest->invalidate();
-
1802 basic_parser<T>::invalidate();
-
1803 }
-
1804
-
1805 public:
-
1806 std::shared_ptr<basic_parser<T>> home;
-
1807 std::shared_ptr<basic_parser<T>> separator;
-
1808 std::shared_ptr<basic_parser<T>> guest;
-
1809
-
1810 protected:
-
1811 std::shared_ptr<basic_parser<T>> m_space;
-
1812 };
-
1813
-
1814 using score = basic_score<char>;
-
1815 using wscore = basic_score<wchar_t>;
-
1816#ifdef _UNICODE
-
1817 using tscore = wscore;
-
1818#else
-
1819 using tscore = score;
-
1820#endif
-
1821 using sgml_score = basic_score<char>;
-
1822
-
1826 template <class T>
-
1827 class basic_signed_numeral : public basic_parser<T>
-
1828 {
-
1829 public:
-
1830 basic_signed_numeral(
-
1831 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
-
1832 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
-
1833 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
-
1834 _In_ const std::shared_ptr<basic_parser<T>>& _number,
-
1835 _In_ const std::locale& locale = std::locale()) :
-
1836 basic_parser<T>(locale),
-
1837 positive_sign(_positive_sign),
-
1838 negative_sign(_negative_sign),
-
1839 special_sign(_special_sign),
-
1840 number(_number)
-
1841 {}
-
1842
-
1843 virtual bool match(
-
1844 _In_reads_or_z_(end) const T* text,
-
1845 _In_ size_t start = 0,
-
1846 _In_ size_t end = (size_t)-1,
-
1847 _In_ int flags = match_default)
-
1848 {
-
1849 assert(text || start >= end);
-
1850 interval.end = start;
-
1851 if (positive_sign && positive_sign->match(text, interval.end, end, flags)) {
-
1852 interval.end = positive_sign->interval.end;
-
1853 if (negative_sign) negative_sign->invalidate();
-
1854 if (special_sign) special_sign->invalidate();
-
1855 }
-
1856 else if (negative_sign && negative_sign->match(text, interval.end, end, flags)) {
-
1857 interval.end = negative_sign->interval.end;
-
1858 if (positive_sign) positive_sign->invalidate();
-
1859 if (special_sign) special_sign->invalidate();
-
1860 }
-
1861 else if (special_sign && special_sign->match(text, interval.end, end, flags)) {
-
1862 interval.end = special_sign->interval.end;
-
1863 if (positive_sign) positive_sign->invalidate();
-
1864 if (negative_sign) negative_sign->invalidate();
-
1865 }
-
1866 else {
-
1867 if (positive_sign) positive_sign->invalidate();
-
1868 if (negative_sign) negative_sign->invalidate();
-
1869 if (special_sign) special_sign->invalidate();
-
1870 }
-
1871 if (number->match(text, interval.end, end, flags)) {
-
1872 interval.start = start;
-
1873 interval.end = number->interval.end;
-
1874 return true;
-
1875 }
-
1876 if (positive_sign) positive_sign->invalidate();
-
1877 if (negative_sign) negative_sign->invalidate();
-
1878 if (special_sign) special_sign->invalidate();
-
1879 number->invalidate();
-
1880 interval.start = (interval.end = start) + 1;
-
1881 return false;
-
1882 }
-
1883
-
1884 virtual void invalidate()
-
1885 {
-
1886 if (positive_sign) positive_sign->invalidate();
-
1887 if (negative_sign) negative_sign->invalidate();
-
1888 if (special_sign) special_sign->invalidate();
-
1889 number->invalidate();
-
1890 basic_parser<T>::invalidate();
-
1891 }
-
1892
-
1893 public:
-
1894 std::shared_ptr<basic_parser<T>> positive_sign;
-
1895 std::shared_ptr<basic_parser<T>> negative_sign;
-
1896 std::shared_ptr<basic_parser<T>> special_sign;
-
1897 std::shared_ptr<basic_parser<T>> number;
-
1898 };
-
1899
-
1900 using signed_numeral = basic_signed_numeral<char>;
-
1901 using wsigned_numeral = basic_signed_numeral<wchar_t>;
-
1902#ifdef _UNICODE
-
1903 using tsigned_numeral = wsigned_numeral;
-
1904#else
-
1905 using tsigned_numeral = signed_numeral;
-
1906#endif
-
1907 using sgml_signed_numeral = basic_signed_numeral<char>;
-
1908
-
1912 template <class T>
-
1913 class basic_mixed_numeral : public basic_parser<T>
-
1914 {
-
1915 public:
-
1916 basic_mixed_numeral(
-
1917 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
-
1918 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
-
1919 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
-
1920 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
-
1921 _In_ const std::shared_ptr<basic_parser<T>>& space,
-
1922 _In_ const std::shared_ptr<basic_parser<T>>& _fraction,
-
1923 _In_ const std::locale& locale = std::locale()) :
-
1924 basic_parser<T>(locale),
-
1925 positive_sign(_positive_sign),
-
1926 negative_sign(_negative_sign),
-
1927 special_sign(_special_sign),
-
1928 integer(_integer),
-
1929 fraction(_fraction),
-
1930 m_space(space)
-
1931 {}
-
1932
-
1933 virtual bool match(
-
1934 _In_reads_or_z_(end) const T* text,
-
1935 _In_ size_t start = 0,
-
1936 _In_ size_t end = (size_t)-1,
-
1937 _In_ int flags = match_default)
-
1938 {
-
1939 assert(text || start >= end);
-
1940 interval.end = start;
-
1941
-
1942 if (positive_sign && positive_sign->match(text, interval.end, end, flags)) {
-
1943 interval.end = positive_sign->interval.end;
-
1944 if (negative_sign) negative_sign->invalidate();
-
1945 if (special_sign) special_sign->invalidate();
-
1946 }
-
1947 else if (negative_sign && negative_sign->match(text, interval.end, end, flags)) {
-
1948 interval.end = negative_sign->interval.end;
-
1949 if (positive_sign) positive_sign->invalidate();
-
1950 if (special_sign) special_sign->invalidate();
-
1951 }
-
1952 else if (special_sign && special_sign->match(text, interval.end, end, flags)) {
-
1953 interval.end = special_sign->interval.end;
-
1954 if (positive_sign) positive_sign->invalidate();
-
1955 if (negative_sign) negative_sign->invalidate();
-
1956 }
-
1957 else {
-
1958 if (positive_sign) positive_sign->invalidate();
-
1959 if (negative_sign) negative_sign->invalidate();
-
1960 if (special_sign) special_sign->invalidate();
-
1961 }
-
1962
-
1963 // Check for <integer> <fraction>
-
1964 const int space_match_flags = flags & ~match_multiline; // Spaces in fractions must never be broken in new line.
-
1965 if (integer->match(text, interval.end, end, flags) &&
-
1966 m_space->match(text, integer->interval.end, end, space_match_flags))
-
1967 {
-
1968 for (interval.end = m_space->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
1969 if (fraction->match(text, interval.end, end, flags)) {
-
1970 interval.start = start;
-
1971 interval.end = fraction->interval.end;
-
1972 return true;
-
1973 }
-
1974 fraction->invalidate();
-
1975 interval.start = start;
-
1976 interval.end = integer->interval.end;
-
1977 return true;
-
1978 }
-
1979
-
1980 // Check for <fraction>
-
1981 if (fraction->match(text, interval.end, end, flags)) {
-
1982 integer->invalidate();
-
1983 interval.start = start;
-
1984 interval.end = fraction->interval.end;
-
1985 return true;
-
1986 }
-
1987
-
1988 // Check for <integer>
-
1989 if (integer->match(text, interval.end, end, flags)) {
-
1990 fraction->invalidate();
-
1991 interval.start = start;
-
1992 interval.end = integer->interval.end;
-
1993 return true;
-
1994 }
-
1995
-
1996 if (positive_sign) positive_sign->invalidate();
-
1997 if (negative_sign) negative_sign->invalidate();
-
1998 if (special_sign) special_sign->invalidate();
-
1999 integer->invalidate();
-
2000 fraction->invalidate();
-
2001 interval.start = (interval.end = start) + 1;
-
2002 return false;
-
2003 }
-
2004
-
2005 virtual void invalidate()
-
2006 {
-
2007 if (positive_sign) positive_sign->invalidate();
-
2008 if (negative_sign) negative_sign->invalidate();
-
2009 if (special_sign) special_sign->invalidate();
-
2010 integer->invalidate();
-
2011 fraction->invalidate();
-
2012 basic_parser<T>::invalidate();
-
2013 }
-
2014
-
2015 public:
-
2016 std::shared_ptr<basic_parser<T>> positive_sign;
-
2017 std::shared_ptr<basic_parser<T>> negative_sign;
-
2018 std::shared_ptr<basic_parser<T>> special_sign;
-
2019 std::shared_ptr<basic_parser<T>> integer;
-
2020 std::shared_ptr<basic_parser<T>> fraction;
-
2021
-
2022 protected:
-
2023 std::shared_ptr<basic_parser<T>> m_space;
-
2024 };
-
2025
-
2026 using mixed_numeral = basic_mixed_numeral<char>;
-
2027 using wmixed_numeral = basic_mixed_numeral<wchar_t>;
-
2028#ifdef _UNICODE
-
2029 using tmixed_numeral = wmixed_numeral;
-
2030#else
-
2031 using tmixed_numeral = mixed_numeral;
-
2032#endif
-
2033 using sgml_mixed_numeral = basic_mixed_numeral<char>;
-
2034
-
2038 template <class T>
-
2039 class basic_scientific_numeral : public basic_parser<T>
-
2040 {
-
2041 public:
-
2042 basic_scientific_numeral(
-
2043 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
-
2044 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
-
2045 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
-
2046 _In_ const std::shared_ptr<basic_integer<T>>& _integer,
-
2047 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
-
2048 _In_ const std::shared_ptr<basic_integer<T>>& _decimal,
-
2049 _In_ const std::shared_ptr<basic_parser<T>>& _exponent_symbol,
-
2050 _In_ const std::shared_ptr<basic_parser<T>>& _positive_exp_sign,
-
2051 _In_ const std::shared_ptr<basic_parser<T>>& _negative_exp_sign,
-
2052 _In_ const std::shared_ptr<basic_integer<T>>& _exponent,
-
2053 _In_ const std::locale& locale = std::locale()) :
-
2054 basic_parser<T>(locale),
-
2055 positive_sign(_positive_sign),
-
2056 negative_sign(_negative_sign),
-
2057 special_sign(_special_sign),
-
2058 integer(_integer),
-
2059 decimal_separator(_decimal_separator),
-
2060 decimal(_decimal),
-
2061 exponent_symbol(_exponent_symbol),
-
2062 positive_exp_sign(_positive_exp_sign),
-
2063 negative_exp_sign(_negative_exp_sign),
-
2064 exponent(_exponent),
-
2065 value(std::numeric_limits<double>::quiet_NaN())
-
2066 {}
-
2067
-
2068 virtual bool match(
-
2069 _In_reads_or_z_(end) const T* text,
-
2070 _In_ size_t start = 0,
-
2071 _In_ size_t end = (size_t)-1,
-
2072 _In_ int flags = match_default)
-
2073 {
-
2074 assert(text || start >= end);
-
2075 interval.end = start;
-
2076
-
2077 if (positive_sign && positive_sign->match(text, interval.end, end, flags)) {
-
2078 interval.end = positive_sign->interval.end;
-
2079 if (negative_sign) negative_sign->invalidate();
-
2080 if (special_sign) special_sign->invalidate();
-
2081 }
-
2082 else if (negative_sign && negative_sign->match(text, interval.end, end, flags)) {
-
2083 interval.end = negative_sign->interval.end;
-
2084 if (positive_sign) positive_sign->invalidate();
-
2085 if (special_sign) special_sign->invalidate();
-
2086 }
-
2087 else if (special_sign && special_sign->match(text, interval.end, end, flags)) {
-
2088 interval.end = special_sign->interval.end;
-
2089 if (positive_sign) positive_sign->invalidate();
-
2090 if (negative_sign) negative_sign->invalidate();
-
2091 }
-
2092 else {
-
2093 if (positive_sign) positive_sign->invalidate();
-
2094 if (negative_sign) negative_sign->invalidate();
-
2095 if (special_sign) special_sign->invalidate();
-
2096 }
-
2097
-
2098 if (integer->match(text, interval.end, end, flags))
-
2099 interval.end = integer->interval.end;
-
2100
-
2101 if (decimal_separator->match(text, interval.end, end, flags) &&
-
2102 decimal->match(text, decimal_separator->interval.end, end, flags))
-
2103 interval.end = decimal->interval.end;
-
2104 else {
-
2105 decimal_separator->invalidate();
-
2106 decimal->invalidate();
-
2107 }
-
2108
-
2109 if (!integer->interval.empty() &&
-
2110 decimal->interval.empty())
-
2111 {
-
2112 // No integer part, no decimal part.
-
2113 if (positive_sign) positive_sign->invalidate();
-
2114 if (negative_sign) negative_sign->invalidate();
-
2115 if (special_sign) special_sign->invalidate();
-
2116 integer->invalidate();
-
2117 decimal_separator->invalidate();
-
2118 decimal->invalidate();
-
2119 if (exponent_symbol) exponent_symbol->invalidate();
-
2120 if (positive_exp_sign) positive_exp_sign->invalidate();
-
2121 if (negative_exp_sign) negative_exp_sign->invalidate();
-
2122 if (exponent) exponent->invalidate();
-
2123 interval.start = (interval.end = start) + 1;
-
2124 return false;
-
2125 }
-
2126
-
2127 if (exponent_symbol && exponent_symbol->match(text, interval.end, end, flags) &&
-
2128 (positive_exp_sign && positive_exp_sign->match(text, exponent_symbol->interval.end, end, flags) &&
-
2129 exponent && exponent->match(text, positive_exp_sign->interval.end, end, flags) ||
-
2130 exponent && exponent->match(text, exponent_symbol->interval.end, end, flags)))
-
2131 {
-
2132 interval.end = exponent->interval.end;
-
2133 if (negative_exp_sign) negative_exp_sign->invalidate();
-
2134 }
-
2135 else if (exponent_symbol && exponent_symbol->match(text, interval.end, end, flags) &&
-
2136 negative_exp_sign && negative_exp_sign->match(text, exponent_symbol->interval.end, end, flags) &&
-
2137 exponent && exponent->match(text, negative_exp_sign->interval.end, end, flags))
-
2138 {
-
2139 interval.end = exponent->interval.end;
-
2140 if (positive_exp_sign) positive_exp_sign->invalidate();
-
2141 }
-
2142 else {
-
2143 if (exponent_symbol) exponent_symbol->invalidate();
-
2144 if (positive_exp_sign) positive_exp_sign->invalidate();
-
2145 if (negative_exp_sign) negative_exp_sign->invalidate();
-
2146 if (exponent) exponent->invalidate();
-
2147 }
-
2148
-
2149 value = (double)integer->value;
-
2150 if (decimal->interval)
-
2151 value += (double)decimal->value * pow(10.0, -(double)decimal->interval.size());
-
2152 if (negative_sign && negative_sign->interval)
-
2153 value = -value;
-
2154 if (exponent && exponent->interval) {
-
2155 double e = (double)exponent->value;
-
2156 if (negative_exp_sign && negative_exp_sign->interval)
-
2157 e = -e;
-
2158 value *= pow(10.0, e);
-
2159 }
-
2160
-
2161 interval.start = start;
-
2162 return true;
-
2163 }
-
2164
-
2165 virtual void invalidate()
-
2166 {
-
2167 if (positive_sign) positive_sign->invalidate();
-
2168 if (negative_sign) negative_sign->invalidate();
-
2169 if (special_sign) special_sign->invalidate();
-
2170 integer->invalidate();
-
2171 decimal_separator->invalidate();
-
2172 decimal->invalidate();
-
2173 if (exponent_symbol) exponent_symbol->invalidate();
-
2174 if (positive_exp_sign) positive_exp_sign->invalidate();
-
2175 if (negative_exp_sign) negative_exp_sign->invalidate();
-
2176 if (exponent) exponent->invalidate();
-
2177 value = std::numeric_limits<double>::quiet_NaN();
-
2178 basic_parser<T>::invalidate();
-
2179 }
-
2180
-
2181 public:
-
2182 std::shared_ptr<basic_parser<T>> positive_sign;
-
2183 std::shared_ptr<basic_parser<T>> negative_sign;
-
2184 std::shared_ptr<basic_parser<T>> special_sign;
-
2185 std::shared_ptr<basic_integer<T>> integer;
-
2186 std::shared_ptr<basic_parser<T>> decimal_separator;
-
2187 std::shared_ptr<basic_integer<T>> decimal;
-
2188 std::shared_ptr<basic_parser<T>> exponent_symbol;
-
2189 std::shared_ptr<basic_parser<T>> positive_exp_sign;
-
2190 std::shared_ptr<basic_parser<T>> negative_exp_sign;
-
2191 std::shared_ptr<basic_integer<T>> exponent;
-
2192 double value;
-
2193 };
-
2194
-
2195 using scientific_numeral = basic_scientific_numeral<char>;
-
2196 using wscientific_numeral = basic_scientific_numeral<wchar_t>;
-
2197#ifdef _UNICODE
-
2198 using tscientific_numeral = wscientific_numeral;
-
2199#else
-
2200 using tscientific_numeral = scientific_numeral;
-
2201#endif
-
2202 using sgml_scientific_numeral = basic_scientific_numeral<char>;
-
2203
-
2207 template <class T>
-
2208 class basic_monetary_numeral : public basic_parser<T>
-
2209 {
-
2210 public:
-
2211 basic_monetary_numeral(
-
2212 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
-
2213 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
-
2214 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
-
2215 _In_ const std::shared_ptr<basic_parser<T>>& _currency,
-
2216 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
-
2217 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
-
2218 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
-
2219 _In_ const std::locale& locale = std::locale()) :
-
2220 basic_parser<T>(locale),
-
2221 positive_sign(_positive_sign),
-
2222 negative_sign(_negative_sign),
-
2223 special_sign(_special_sign),
-
2224 currency(_currency),
-
2225 integer(_integer),
-
2226 decimal_separator(_decimal_separator),
-
2227 decimal(_decimal)
-
2228 {}
-
2229
-
2230 virtual bool match(
-
2231 _In_reads_or_z_(end) const T* text,
-
2232 _In_ size_t start = 0,
-
2233 _In_ size_t end = (size_t)-1,
-
2234 _In_ int flags = match_default)
-
2235 {
-
2236 assert(text || start >= end);
-
2237 interval.end = start;
-
2238
-
2239 if (positive_sign->match(text, interval.end, end, flags)) {
-
2240 interval.end = positive_sign->interval.end;
-
2241 if (negative_sign) negative_sign->invalidate();
-
2242 if (special_sign) special_sign->invalidate();
-
2243 }
-
2244 else if (negative_sign->match(text, interval.end, end, flags)) {
-
2245 interval.end = negative_sign->interval.end;
-
2246 if (positive_sign) positive_sign->invalidate();
-
2247 if (special_sign) special_sign->invalidate();
-
2248 }
-
2249 else if (special_sign->match(text, interval.end, end, flags)) {
-
2250 interval.end = special_sign->interval.end;
-
2251 if (positive_sign) positive_sign->invalidate();
-
2252 if (negative_sign) negative_sign->invalidate();
-
2253 }
-
2254 else {
-
2255 if (positive_sign) positive_sign->invalidate();
-
2256 if (negative_sign) negative_sign->invalidate();
-
2257 if (special_sign) special_sign->invalidate();
-
2258 }
-
2259
-
2260 if (currency->match(text, interval.end, end, flags))
-
2261 interval.end = currency->interval.end;
-
2262 else {
-
2263 if (positive_sign) positive_sign->invalidate();
-
2264 if (negative_sign) negative_sign->invalidate();
-
2265 if (special_sign) special_sign->invalidate();
-
2266 integer->invalidate();
-
2267 decimal_separator->invalidate();
-
2268 decimal->invalidate();
-
2269 interval.start = (interval.end = start) + 1;
-
2270 return false;
-
2271 }
-
2272
-
2273 if (integer->match(text, interval.end, end, flags))
-
2274 interval.end = integer->interval.end;
-
2275 if (decimal_separator->match(text, interval.end, end, flags) &&
-
2276 decimal->match(text, decimal_separator->interval.end, end, flags))
-
2277 interval.end = decimal->interval.end;
-
2278 else {
-
2279 decimal_separator->invalidate();
-
2280 decimal->invalidate();
-
2281 }
-
2282
-
2283 if (integer->interval.empty() &&
-
2284 decimal->interval.empty())
-
2285 {
-
2286 // No integer part, no decimal part.
-
2287 if (positive_sign) positive_sign->invalidate();
-
2288 if (negative_sign) negative_sign->invalidate();
-
2289 if (special_sign) special_sign->invalidate();
-
2290 currency->invalidate();
-
2291 integer->invalidate();
-
2292 decimal_separator->invalidate();
-
2293 decimal->invalidate();
-
2294 interval.start = (interval.end = start) + 1;
-
2295 return false;
-
2296 }
-
2297
-
2298 interval.start = start;
-
2299 return true;
-
2300 }
-
2301
-
2302 virtual void invalidate()
-
2303 {
-
2304 if (positive_sign) positive_sign->invalidate();
-
2305 if (negative_sign) negative_sign->invalidate();
-
2306 if (special_sign) special_sign->invalidate();
-
2307 currency->invalidate();
-
2308 integer->invalidate();
-
2309 decimal_separator->invalidate();
-
2310 decimal->invalidate();
-
2311 basic_parser<T>::invalidate();
-
2312 }
-
2313
-
2314 public:
-
2315 std::shared_ptr<basic_parser<T>> positive_sign;
-
2316 std::shared_ptr<basic_parser<T>> negative_sign;
-
2317 std::shared_ptr<basic_parser<T>> special_sign;
-
2318 std::shared_ptr<basic_parser<T>> currency;
-
2319 std::shared_ptr<basic_parser<T>> integer;
-
2320 std::shared_ptr<basic_parser<T>> decimal_separator;
-
2321 std::shared_ptr<basic_parser<T>> decimal;
-
2322 };
-
2323
-
2324 using monetary_numeral = basic_monetary_numeral<char>;
-
2325 using wmonetary_numeral = basic_monetary_numeral<wchar_t>;
-
2326#ifdef _UNICODE
-
2327 using tmonetary_numeral = wmonetary_numeral;
-
2328#else
-
2329 using tmonetary_numeral = monetary_numeral;
-
2330#endif
-
2331 using sgml_monetary_numeral = basic_monetary_numeral<char>;
-
2332
-
2336 template <class T>
-
2337 class basic_ipv4_address : public basic_parser<T>
-
2338 {
-
2339 public:
-
2340 basic_ipv4_address(
-
2341 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
-
2342 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
-
2343 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
-
2344 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
-
2345 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
-
2346 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
-
2347 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
-
2348 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
-
2349 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
-
2350 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
-
2351 _In_ const std::shared_ptr<basic_parser<T>>& separator,
-
2352 _In_ const std::locale& locale = std::locale()) :
-
2353 basic_parser<T>(locale),
-
2354 m_digit_0(digit_0),
-
2355 m_digit_1(digit_1),
-
2356 m_digit_2(digit_2),
-
2357 m_digit_3(digit_3),
-
2358 m_digit_4(digit_4),
-
2359 m_digit_5(digit_5),
-
2360 m_digit_6(digit_6),
-
2361 m_digit_7(digit_7),
-
2362 m_digit_8(digit_8),
-
2363 m_digit_9(digit_9),
-
2364 m_separator(separator)
-
2365 {
-
2366 value.s_addr = 0;
-
2367 }
-
2368
-
2369 virtual bool match(
-
2370 _In_reads_or_z_(end) const T* text,
-
2371 _In_ size_t start = 0,
-
2372 _In_ size_t end = (size_t)-1,
-
2373 _In_ int flags = match_default)
-
2374 {
-
2375 assert(text || start >= end);
-
2376 interval.end = start;
-
2377 value.s_addr = 0;
-
2378
-
2379 size_t i;
-
2380 for (i = 0; i < 4; i++) {
-
2381 if (i) {
-
2382 if (m_separator->match(text, interval.end, end, flags))
-
2383 interval.end = m_separator->interval.end;
-
2384 else
-
2385 goto error;
-
2386 }
-
2387
-
2388 components[i].start = interval.end;
-
2389 bool is_empty = true;
-
2390 size_t x;
-
2391 for (x = 0; interval.end < end && text[interval.end];) {
-
2392 size_t dig, digit_end;
-
2393 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
-
2394 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
-
2395 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
-
2396 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
-
2397 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
-
2398 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
-
2399 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
-
2400 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
-
2401 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
-
2402 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
-
2403 else break;
-
2404 size_t x_n = x * 10 + dig;
-
2405 if (x_n <= 255) {
-
2406 x = x_n;
-
2407 interval.end = digit_end;
-
2408 is_empty = false;
-
2409 }
-
2410 else
-
2411 break;
-
2412 }
-
2413 if (is_empty)
-
2414 goto error;
-
2415 components[i].end = interval.end;
-
2416 value.s_addr = (value.s_addr << 8) | (uint8_t)x;
-
2417 }
-
2418 if (i < 4)
-
2419 goto error;
-
2420
-
2421 interval.start = start;
-
2422 return true;
-
2423
-
2424 error:
-
2425 components[0].start = 1;
-
2426 components[0].end = 0;
-
2427 components[1].start = 1;
-
2428 components[1].end = 0;
-
2429 components[2].start = 1;
-
2430 components[2].end = 0;
-
2431 components[3].start = 1;
-
2432 components[3].end = 0;
-
2433 value.s_addr = 0;
-
2434 interval.start = (interval.end = start) + 1;
-
2435 return false;
-
2436 }
-
2437
-
2438 virtual void invalidate()
-
2439 {
-
2440 components[0].start = 1;
-
2441 components[0].end = 0;
-
2442 components[1].start = 1;
-
2443 components[1].end = 0;
-
2444 components[2].start = 1;
-
2445 components[2].end = 0;
-
2446 components[3].start = 1;
-
2447 components[3].end = 0;
-
2448 value.s_addr = 0;
-
2449 basic_parser<T>::invalidate();
-
2450 }
-
2451
-
2452 public:
-
2453 stdex::interval<size_t> components[4];
-
2454 struct in_addr value;
-
2455
-
2456 protected:
-
2457 std::shared_ptr<basic_parser<T>>
-
2458 m_digit_0,
-
2459 m_digit_1,
-
2460 m_digit_2,
-
2461 m_digit_3,
-
2462 m_digit_4,
-
2463 m_digit_5,
-
2464 m_digit_6,
-
2465 m_digit_7,
-
2466 m_digit_8,
-
2467 m_digit_9;
-
2468 std::shared_ptr<basic_parser<T>> m_separator;
-
2469 };
-
2470
-
2471 using ipv4_address = basic_ipv4_address<char>;
-
2472 using wipv4_address = basic_ipv4_address<wchar_t>;
-
2473#ifdef _UNICODE
-
2474 using tipv4_address = wipv4_address;
-
2475#else
-
2476 using tipv4_address = ipv4_address;
-
2477#endif
-
2478 using sgml_ipv4_address = basic_ipv4_address<char>;
-
2479
-
2483 template <class T>
-
2484 class basic_ipv6_scope_id_char : public basic_parser<T>
-
2485 {
-
2486 public:
-
2487 basic_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
-
2488
-
2489 virtual bool match(
-
2490 _In_reads_or_z_(end) const T* text,
-
2491 _In_ size_t start = 0,
-
2492 _In_ size_t end = (size_t)-1,
-
2493 _In_ int flags = match_default)
-
2494 {
-
2495 assert(text || start >= end);
-
2496 if (start < end && text[start]) {
-
2497 if (text[start] == '-' ||
-
2498 text[start] == '_' ||
-
2499 text[start] == ':' ||
-
2500 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
-
2501 {
-
2502 interval.end = (interval.start = start) + 1;
-
2503 return true;
-
2504 }
-
2505 }
-
2506 interval.start = (interval.end = start) + 1;
-
2507 return false;
-
2508 }
-
2509 };
-
2510
-
2511 using ipv6_scope_id_char = basic_ipv6_scope_id_char<char>;
-
2512 using wipv6_scope_id_char = basic_ipv6_scope_id_char<wchar_t>;
-
2513#ifdef _UNICODE
-
2514 using tipv6_scope_id_char = wipv6_scope_id_char;
-
2515#else
-
2516 using tipv6_scope_id_char = ipv6_scope_id_char;
-
2517#endif
-
2518
-
2522 class sgml_ipv6_scope_id_char : public sgml_parser
-
2523 {
-
2524 public:
-
2525 sgml_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : sgml_parser(locale) {}
-
2526
-
2527 virtual bool match(
-
2528 _In_reads_or_z_(end) const char* text,
-
2529 _In_ size_t start = 0,
-
2530 _In_ size_t end = (size_t)-1,
-
2531 _In_ int flags = match_default)
-
2532 {
-
2533 assert(text || start >= end);
-
2534 if (start < end && text[start]) {
-
2535 wchar_t buf[3];
-
2536 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
2537 const wchar_t* chr_end = chr + stdex::strlen(chr);
-
2538 if ((chr[0] == L'-' ||
-
2539 chr[0] == L'_' ||
-
2540 chr[0] == L':') && chr[1] == 0 ||
-
2541 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
-
2542 {
-
2543 interval.start = start;
-
2544 return true;
-
2545 }
-
2546 }
-
2547 interval.start = (interval.end = start) + 1;
-
2548 return false;
-
2549 }
-
2550 };
-
2551
-
2555 template <class T>
-
2556 class basic_ipv6_address : public basic_parser<T>
-
2557 {
-
2558 public:
-
2559 basic_ipv6_address(
-
2560 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
-
2561 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
-
2562 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
-
2563 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
-
2564 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
-
2565 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
-
2566 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
-
2567 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
-
2568 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
-
2569 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
-
2570 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
-
2571 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
-
2572 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
-
2573 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
-
2574 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
-
2575 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
-
2576 _In_ const std::shared_ptr<basic_parser<T>>& separator,
-
2577 _In_ const std::shared_ptr<basic_parser<T>>& scope_id_separator = nullptr,
-
2578 _In_ const std::shared_ptr<basic_parser<T>>& _scope_id = nullptr,
-
2579 _In_ const std::locale& locale = std::locale()) :
-
2580 basic_parser<T>(locale),
-
2581 m_digit_0(digit_0),
-
2582 m_digit_1(digit_1),
-
2583 m_digit_2(digit_2),
-
2584 m_digit_3(digit_3),
-
2585 m_digit_4(digit_4),
-
2586 m_digit_5(digit_5),
-
2587 m_digit_6(digit_6),
-
2588 m_digit_7(digit_7),
-
2589 m_digit_8(digit_8),
-
2590 m_digit_9(digit_9),
-
2591 m_digit_10(digit_10),
-
2592 m_digit_11(digit_11),
-
2593 m_digit_12(digit_12),
-
2594 m_digit_13(digit_13),
-
2595 m_digit_14(digit_14),
-
2596 m_digit_15(digit_15),
-
2597 m_separator(separator),
-
2598 m_scope_id_separator(scope_id_separator),
-
2599 scope_id(_scope_id)
-
2600 {
-
2601 memset(&value, 0, sizeof(value));
-
2602 }
-
2603
-
2604 virtual bool match(
-
2605 _In_reads_or_z_(end) const T* text,
-
2606 _In_ size_t start = 0,
-
2607 _In_ size_t end = (size_t)-1,
-
2608 _In_ int flags = match_default)
-
2609 {
-
2610 assert(text || start >= end);
-
2611 interval.end = start;
-
2612 memset(&value, 0, sizeof(value));
-
2613
-
2614 size_t i, compaction_i = (size_t)-1, compaction_start = start;
-
2615 for (i = 0; i < 8; i++) {
-
2616 bool is_empty = true;
-
2617
-
2618 if (m_separator->match(text, interval.end, end, flags)) {
-
2619 if (m_separator->match(text, m_separator->interval.end, end, flags)) {
-
2620 // :: found
-
2621 if (compaction_i == (size_t)-1) {
-
2622 // Zero compaction start
-
2623 compaction_i = i;
-
2624 compaction_start = m_separator->interval.start;
-
2625 interval.end = m_separator->interval.end;
-
2626 }
-
2627 else {
-
2628 // More than one zero compaction
-
2629 break;
-
2630 }
-
2631 }
-
2632 else if (i) {
-
2633 // Inner : found
-
2634 interval.end = m_separator->interval.end;
-
2635 }
-
2636 else {
-
2637 // Leading : found
-
2638 goto error;
-
2639 }
-
2640 }
-
2641 else if (i) {
-
2642 // : missing
-
2643 break;
-
2644 }
-
2645
-
2646 components[i].start = interval.end;
-
2647 size_t x;
-
2648 for (x = 0; interval.end < end && text[interval.end];) {
-
2649 size_t dig, digit_end;
-
2650 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
-
2651 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
-
2652 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
-
2653 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
-
2654 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
-
2655 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
-
2656 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
-
2657 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
-
2658 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
-
2659 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
-
2660 else if (m_digit_10->match(text, interval.end, end, flags)) { dig = 10; digit_end = m_digit_10->interval.end; }
-
2661 else if (m_digit_11->match(text, interval.end, end, flags)) { dig = 11; digit_end = m_digit_11->interval.end; }
-
2662 else if (m_digit_12->match(text, interval.end, end, flags)) { dig = 12; digit_end = m_digit_12->interval.end; }
-
2663 else if (m_digit_13->match(text, interval.end, end, flags)) { dig = 13; digit_end = m_digit_13->interval.end; }
-
2664 else if (m_digit_14->match(text, interval.end, end, flags)) { dig = 14; digit_end = m_digit_14->interval.end; }
-
2665 else if (m_digit_15->match(text, interval.end, end, flags)) { dig = 15; digit_end = m_digit_15->interval.end; }
-
2666 else break;
-
2667 size_t x_n = x * 16 + dig;
-
2668 if (x_n <= 0xffff) {
-
2669 x = x_n;
-
2670 interval.end = digit_end;
-
2671 is_empty = false;
-
2672 }
-
2673 else
-
2674 break;
-
2675 }
-
2676 if (is_empty) {
-
2677 if (compaction_i != (size_t)-1) {
-
2678 // Zero compaction active: no sweat.
-
2679 break;
-
2680 }
-
2681 goto error;
-
2682 }
-
2683 components[i].end = interval.end;
-
2684 value.s6_words[i] = (uint16_t)x;
-
2685 }
-
2686
-
2687 if (compaction_i != (size_t)-1) {
-
2688 // Align components right due to zero compaction.
-
2689 size_t j, k;
-
2690 for (j = 8, k = i; k > compaction_i;) {
-
2691 value.s6_words[--j] = value.s6_words[--k];
-
2692 components[j] = components[k];
-
2693 }
-
2694 for (; j > compaction_i;) {
-
2695 value.s6_words[--j] = 0;
-
2696 components[j].start =
-
2697 components[j].end = compaction_start;
-
2698 }
-
2699 }
-
2700 else if (i < 8)
-
2701 goto error;
-
2702
-
2703 if (m_scope_id_separator && m_scope_id_separator->match(text, interval.end, end, flags) &&
-
2704 scope_id && scope_id->match(text, m_scope_id_separator->interval.end, end, flags))
-
2705 interval.end = scope_id->interval.end;
-
2706 else if (scope_id)
-
2707 scope_id->invalidate();
-
2708
-
2709 interval.start = start;
-
2710 return true;
-
2711
-
2712 error:
-
2713 components[0].start = 1;
-
2714 components[0].end = 0;
-
2715 components[1].start = 1;
-
2716 components[1].end = 0;
-
2717 components[2].start = 1;
-
2718 components[2].end = 0;
-
2719 components[3].start = 1;
-
2720 components[3].end = 0;
-
2721 components[4].start = 1;
-
2722 components[4].end = 0;
-
2723 components[5].start = 1;
-
2724 components[5].end = 0;
-
2725 components[6].start = 1;
-
2726 components[6].end = 0;
-
2727 components[7].start = 1;
-
2728 components[7].end = 0;
-
2729 memset(&value, 0, sizeof(value));
-
2730 if (scope_id) scope_id->invalidate();
-
2731 interval.start = (interval.end = start) + 1;
-
2732 return false;
-
2733 }
-
2734
-
2735 virtual void invalidate()
-
2736 {
-
2737 components[0].start = 1;
-
2738 components[0].end = 0;
-
2739 components[1].start = 1;
-
2740 components[1].end = 0;
-
2741 components[2].start = 1;
-
2742 components[2].end = 0;
-
2743 components[3].start = 1;
-
2744 components[3].end = 0;
-
2745 components[4].start = 1;
-
2746 components[4].end = 0;
-
2747 components[5].start = 1;
-
2748 components[5].end = 0;
-
2749 components[6].start = 1;
-
2750 components[6].end = 0;
-
2751 components[7].start = 1;
-
2752 components[7].end = 0;
-
2753 memset(&value, 0, sizeof(value));
-
2754 if (scope_id) scope_id->invalidate();
-
2755 basic_parser<T>::invalidate();
-
2756 }
-
2757
-
2758 public:
-
2759 stdex::interval<size_t> components[8];
-
2760 struct in6_addr value;
-
2761 std::shared_ptr<basic_parser<T>> scope_id;
-
2762
-
2763 protected:
-
2764 std::shared_ptr<basic_parser<T>>
-
2765 m_digit_0,
-
2766 m_digit_1,
-
2767 m_digit_2,
-
2768 m_digit_3,
-
2769 m_digit_4,
-
2770 m_digit_5,
-
2771 m_digit_6,
-
2772 m_digit_7,
-
2773 m_digit_8,
-
2774 m_digit_9,
-
2775 m_digit_10,
-
2776 m_digit_11,
-
2777 m_digit_12,
-
2778 m_digit_13,
-
2779 m_digit_14,
-
2780 m_digit_15;
-
2781 std::shared_ptr<basic_parser<T>> m_separator, m_scope_id_separator;
-
2782 };
-
2783
-
2784 using ipv6_address = basic_ipv6_address<char>;
-
2785 using wipv6_address = basic_ipv6_address<wchar_t>;
-
2786#ifdef _UNICODE
-
2787 using tipv6_address = wipv6_address;
-
2788#else
-
2789 using tipv6_address = ipv6_address;
-
2790#endif
-
2791 using sgml_ipv6_address = basic_ipv6_address<char>;
-
2792
-
2796 template <class T>
-
2797 class basic_dns_domain_char : public basic_parser<T>
-
2798 {
-
2799 public:
-
2800 basic_dns_domain_char(
-
2801 _In_ bool allow_idn,
-
2802 _In_ const std::locale& locale = std::locale()) :
-
2803 basic_parser<T>(locale),
-
2804 m_allow_idn(allow_idn),
-
2805 allow_on_edge(true)
-
2806 {}
-
2807
-
2808 virtual bool match(
-
2809 _In_reads_or_z_(end) const T* text,
-
2810 _In_ size_t start = 0,
-
2811 _In_ size_t end = (size_t)-1,
-
2812 _In_ int flags = match_default)
-
2813 {
-
2814 assert(text || start >= end);
-
2815 if (start < end && text[start]) {
-
2816 if (('A' <= text[start] && text[start] <= 'Z') ||
-
2817 ('a' <= text[start] && text[start] <= 'z') ||
-
2818 ('0' <= text[start] && text[start] <= '9'))
-
2819 allow_on_edge = true;
-
2820 else if (text[start] == '-')
-
2821 allow_on_edge = false;
-
2822 else if (m_allow_idn && std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
-
2823 allow_on_edge = true;
-
2824 else {
-
2825 interval.start = (interval.end = start) + 1;
-
2826 return false;
-
2827 }
-
2828 interval.end = (interval.start = start) + 1;
-
2829 return true;
-
2830 }
-
2831 interval.start = (interval.end = start) + 1;
-
2832 return false;
-
2833 }
-
2834
-
2835 public:
-
2836 bool allow_on_edge;
-
2837
-
2838 protected:
-
2839 bool m_allow_idn;
-
2840 };
-
2841
-
2842 using dns_domain_char = basic_dns_domain_char<char>;
-
2843 using wdns_domain_char = basic_dns_domain_char<wchar_t>;
-
2844#ifdef _UNICODE
-
2845 using tdns_domain_char = wdns_domain_char;
-
2846#else
-
2847 using tdns_domain_char = dns_domain_char;
-
2848#endif
-
2849
-
2853 class sgml_dns_domain_char : public basic_dns_domain_char<char>
-
2854 {
-
2855 public:
-
2856 sgml_dns_domain_char(
-
2857 _In_ bool allow_idn,
-
2858 _In_ const std::locale& locale = std::locale()) :
-
2859 basic_dns_domain_char<char>(allow_idn, locale)
-
2860 {}
-
2861
-
2862 virtual bool match(
-
2863 _In_reads_or_z_(end) const char* text,
-
2864 _In_ size_t start = 0,
-
2865 _In_ size_t end = (size_t)-1,
-
2866 _In_ int flags = match_default)
-
2867 {
-
2868 assert(text || start >= end);
-
2869 if (start < end && text[start]) {
-
2870 wchar_t buf[3];
-
2871 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
2872 const wchar_t* chr_end = chr + stdex::strlen(chr);
-
2873 if ((('A' <= chr[0] && chr[0] <= 'Z') ||
-
2874 ('a' <= chr[0] && chr[0] <= 'z') ||
-
2875 ('0' <= chr[0] && chr[0] <= '9')) && chr[1] == 0)
-
2876 allow_on_edge = true;
-
2877 else if (chr[0] == '-' && chr[1] == 0)
-
2878 allow_on_edge = false;
-
2879 else if (m_allow_idn && std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
-
2880 allow_on_edge = true;
-
2881 else {
-
2882 interval.start = (interval.end = start) + 1;
-
2883 return false;
-
2884 }
-
2885 interval.start = start;
-
2886 return true;
-
2887 }
-
2888 interval.start = (interval.end = start) + 1;
-
2889 return false;
-
2890 }
-
2891 };
-
2892
-
2896 template <class T>
-
2897 class basic_dns_name : public basic_parser<T>
-
2898 {
-
2899 public:
-
2900 basic_dns_name(
-
2901 _In_ bool allow_absolute,
-
2902 _In_ const std::shared_ptr<basic_dns_domain_char<T>>& domain_char,
-
2903 _In_ const std::shared_ptr<basic_parser<T>>& separator,
-
2904 _In_ const std::locale& locale = std::locale()) :
-
2905 basic_parser<T>(locale),
-
2906 m_allow_absolute(allow_absolute),
-
2907 m_domain_char(domain_char),
-
2908 m_separator(separator)
-
2909 {}
-
2910
-
2911 virtual bool match(
-
2912 _In_reads_or_z_(end) const T* text,
-
2913 _In_ size_t start = 0,
-
2914 _In_ size_t end = (size_t)-1,
-
2915 _In_ int flags = match_default)
-
2916 {
-
2917 assert(text || start >= end);
-
2918 size_t i = start, count;
-
2919 for (count = 0; i < end && text[i] && count < 127; count++) {
-
2920 if (m_domain_char->match(text, i, end, flags) &&
-
2921 m_domain_char->allow_on_edge)
-
2922 {
-
2923 // Domain start
-
2924 interval.end = i = m_domain_char->interval.end;
-
2925 while (i < end && text[i]) {
-
2926 if (m_domain_char->allow_on_edge &&
-
2927 m_separator->match(text, i, end, flags))
-
2928 {
-
2929 // Domain end
-
2930 if (m_allow_absolute)
-
2931 interval.end = i = m_separator->interval.end;
-
2932 else {
-
2933 interval.end = i;
-
2934 i = m_separator->interval.end;
-
2935 }
-
2936 break;
-
2937 }
-
2938 if (m_domain_char->match(text, i, end, flags)) {
-
2939 if (m_domain_char->allow_on_edge)
-
2940 interval.end = i = m_domain_char->interval.end;
-
2941 else
-
2942 i = m_domain_char->interval.end;
-
2943 }
-
2944 else {
-
2945 interval.start = start;
-
2946 return true;
-
2947 }
-
2948 }
-
2949 }
-
2950 else
-
2951 break;
-
2952 }
-
2953 if (count) {
-
2954 interval.start = start;
-
2955 return true;
-
2956 }
-
2957 interval.start = (interval.end = start) + 1;
-
2958 return false;
-
2959 }
-
2960
-
2961 protected:
-
2962 bool m_allow_absolute;
-
2963 std::shared_ptr<basic_dns_domain_char<T>> m_domain_char;
-
2964 std::shared_ptr<basic_parser<T>> m_separator;
-
2965 };
-
2966
-
2967 using dns_name = basic_dns_name<char>;
-
2968 using wdns_name = basic_dns_name<wchar_t>;
-
2969#ifdef _UNICODE
-
2970 using tdns_name = wdns_name;
-
2971#else
-
2972 using tdns_name = dns_name;
-
2973#endif
-
2974 using sgml_dns_name = basic_dns_name<char>;
-
2975
-
2979 template <class T>
-
2980 class basic_url_username_char : public basic_parser<T>
-
2981 {
-
2982 public:
-
2983 basic_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
-
2984
-
2985 virtual bool match(
-
2986 _In_reads_or_z_(end) const T* text,
-
2987 _In_ size_t start = 0,
-
2988 _In_ size_t end = (size_t)-1,
-
2989 _In_ int flags = match_default)
-
2990 {
-
2991 assert(text || start >= end);
-
2992 if (start < end && text[start]) {
-
2993 if (text[start] == '-' ||
-
2994 text[start] == '.' ||
-
2995 text[start] == '_' ||
-
2996 text[start] == '~' ||
-
2997 text[start] == '%' ||
-
2998 text[start] == '!' ||
-
2999 text[start] == '$' ||
-
3000 text[start] == '&' ||
-
3001 text[start] == '\'' ||
-
3002 //text[start] == '(' ||
-
3003 //text[start] == ')' ||
-
3004 text[start] == '*' ||
-
3005 text[start] == '+' ||
-
3006 text[start] == ',' ||
-
3007 text[start] == ';' ||
-
3008 text[start] == '=' ||
-
3009 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
-
3010 {
-
3011 interval.end = (interval.start = start) + 1;
-
3012 return true;
-
3013 }
-
3014 }
-
3015 interval.start = (interval.end = start) + 1;
-
3016 return false;
-
3017 }
-
3018 };
-
3019
-
3020 using url_username_char = basic_url_username_char<char>;
-
3021 using wurl_username_char = basic_url_username_char<wchar_t>;
-
3022#ifdef _UNICODE
-
3023 using turl_username_char = wurl_username_char;
-
3024#else
-
3025 using turl_username_char = url_username_char;
-
3026#endif
-
3027
-
3031 class sgml_url_username_char : public basic_url_username_char<char>
-
3032 {
-
3033 public:
-
3034 sgml_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_url_username_char<char>(locale) {}
-
3035
-
3036 virtual bool match(
-
3037 _In_reads_or_z_(end) const char* text,
-
3038 _In_ size_t start = 0,
-
3039 _In_ size_t end = (size_t)-1,
-
3040 _In_ int flags = match_default)
-
3041 {
-
3042 assert(text || start >= end);
-
3043 if (start < end && text[start]) {
-
3044 wchar_t buf[3];
-
3045 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
3046 const wchar_t* chr_end = chr + stdex::strlen(chr);
-
3047 if ((chr[0] == L'-' ||
-
3048 chr[0] == L'.' ||
-
3049 chr[0] == L'_' ||
-
3050 chr[0] == L'~' ||
-
3051 chr[0] == L'%' ||
-
3052 chr[0] == L'!' ||
-
3053 chr[0] == L'$' ||
-
3054 chr[0] == L'&' ||
-
3055 chr[0] == L'\'' ||
-
3056 //chr[0] == L'(' ||
-
3057 //chr[0] == L')' ||
-
3058 chr[0] == L'*' ||
-
3059 chr[0] == L'+' ||
-
3060 chr[0] == L',' ||
-
3061 chr[0] == L';' ||
-
3062 chr[0] == L'=') && chr[1] == 0 ||
-
3063 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
-
3064 {
-
3065 interval.start = start;
-
3066 return true;
-
3067 }
-
3068 }
-
3069
-
3070 interval.start = (interval.end = start) + 1;
-
3071 return false;
-
3072 }
-
3073 };
-
3074
-
3078 template <class T>
-
3079 class basic_url_password_char : public basic_parser<T>
-
3080 {
-
3081 public:
-
3082 basic_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
-
3083
-
3084 virtual bool match(
-
3085 _In_reads_or_z_(end) const T* text,
-
3086 _In_ size_t start = 0,
-
3087 _In_ size_t end = (size_t)-1,
-
3088 _In_ int flags = match_default)
-
3089 {
-
3090 assert(text || start >= end);
-
3091 if (start < end && text[start]) {
-
3092 if (text[start] == '-' ||
-
3093 text[start] == '.' ||
-
3094 text[start] == '_' ||
-
3095 text[start] == '~' ||
-
3096 text[start] == '%' ||
-
3097 text[start] == '!' ||
-
3098 text[start] == '$' ||
-
3099 text[start] == '&' ||
-
3100 text[start] == '\'' ||
-
3101 text[start] == '(' ||
-
3102 text[start] == ')' ||
-
3103 text[start] == '*' ||
-
3104 text[start] == '+' ||
-
3105 text[start] == ',' ||
-
3106 text[start] == ';' ||
-
3107 text[start] == '=' ||
-
3108 text[start] == ':' ||
-
3109 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
-
3110 {
-
3111 interval.end = (interval.start = start) + 1;
-
3112 return true;
-
3113 }
-
3114 }
-
3115 interval.start = (interval.end = start) + 1;
-
3116 return false;
-
3117 }
-
3118 };
-
3119
-
3120 using url_password_char = basic_url_password_char<char>;
-
3121 using wurl_password_char = basic_url_password_char<wchar_t>;
-
3122#ifdef _UNICODE
-
3123 using turl_password_char = wurl_password_char;
-
3124#else
-
3125 using turl_password_char = url_password_char;
-
3126#endif
-
3127
-
3131 class sgml_url_password_char : public basic_url_password_char<char>
-
3132 {
-
3133 public:
-
3134 sgml_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_url_password_char<char>(locale) {}
-
3135
-
3136 virtual bool match(
-
3137 _In_reads_or_z_(end) const char* text,
-
3138 _In_ size_t start = 0,
-
3139 _In_ size_t end = (size_t)-1,
-
3140 _In_ int flags = match_default)
-
3141 {
-
3142 assert(text || start >= end);
-
3143 if (start < end && text[start]) {
-
3144 wchar_t buf[3];
-
3145 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
3146 const wchar_t* chr_end = chr + stdex::strlen(chr);
-
3147 if ((chr[0] == L'-' ||
-
3148 chr[0] == L'.' ||
-
3149 chr[0] == L'_' ||
-
3150 chr[0] == L'~' ||
-
3151 chr[0] == L'%' ||
-
3152 chr[0] == L'!' ||
-
3153 chr[0] == L'$' ||
-
3154 chr[0] == L'&' ||
-
3155 chr[0] == L'\'' ||
-
3156 chr[0] == L'(' ||
-
3157 chr[0] == L')' ||
-
3158 chr[0] == L'*' ||
-
3159 chr[0] == L'+' ||
-
3160 chr[0] == L',' ||
-
3161 chr[0] == L';' ||
-
3162 chr[0] == L'=' ||
-
3163 chr[0] == L':') && chr[1] == 0 ||
-
3164 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
-
3165 {
-
3166 interval.start = start;
-
3167 return true;
-
3168 }
-
3169 }
-
3170 interval.start = (interval.end = start) + 1;
-
3171 return false;
-
3172 }
-
3173 };
-
3174
-
3178 template <class T>
-
3179 class basic_url_path_char : public basic_parser<T>
-
3180 {
-
3181 public:
-
3182 basic_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
-
3183
-
3184 virtual bool match(
-
3185 _In_reads_or_z_(end) const T* text,
-
3186 _In_ size_t start = 0,
-
3187 _In_ size_t end = (size_t)-1,
-
3188 _In_ int flags = match_default)
-
3189 {
-
3190 assert(text || start >= end);
-
3191 if (start < end && text[start]) {
-
3192 if (text[start] == '/' ||
-
3193 text[start] == '-' ||
-
3194 text[start] == '.' ||
-
3195 text[start] == '_' ||
-
3196 text[start] == '~' ||
-
3197 text[start] == '%' ||
-
3198 text[start] == '!' ||
-
3199 text[start] == '$' ||
-
3200 text[start] == '&' ||
-
3201 text[start] == '\'' ||
-
3202 text[start] == '(' ||
-
3203 text[start] == ')' ||
-
3204 text[start] == '*' ||
-
3205 text[start] == '+' ||
-
3206 text[start] == ',' ||
-
3207 text[start] == ';' ||
-
3208 text[start] == '=' ||
-
3209 text[start] == ':' ||
-
3210 text[start] == '@' ||
-
3211 text[start] == '?' ||
-
3212 text[start] == '#' ||
-
3213 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
-
3214 {
-
3215 interval.end = (interval.start = start) + 1;
-
3216 return true;
-
3217 }
-
3218 }
-
3219 interval.start = (interval.end = start) + 1;
-
3220 return false;
-
3221 }
-
3222 };
-
3223
-
3224 using url_path_char = basic_url_path_char<char>;
-
3225 using wurl_path_char = basic_url_path_char<wchar_t>;
-
3226#ifdef _UNICODE
-
3227 using turl_path_char = wurl_path_char;
-
3228#else
-
3229 using turl_path_char = url_path_char;
-
3230#endif
-
3231
-
3235 class sgml_url_path_char : public basic_url_path_char<char>
-
3236 {
-
3237 public:
-
3238 sgml_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_url_path_char<char>(locale) {}
-
3239
-
3240 virtual bool match(
-
3241 _In_reads_or_z_(end) const char* text,
-
3242 _In_ size_t start = 0,
-
3243 _In_ size_t end = (size_t)-1,
-
3244 _In_ int flags = match_default)
-
3245 {
-
3246 assert(text || start >= end);
-
3247 if (start < end && text[start]) {
-
3248 wchar_t buf[3];
-
3249 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
-
3250 const wchar_t* chr_end = chr + stdex::strlen(chr);
-
3251 if ((chr[0] == L'/' ||
-
3252 chr[0] == L'-' ||
-
3253 chr[0] == L'.' ||
-
3254 chr[0] == L'_' ||
-
3255 chr[0] == L'~' ||
-
3256 chr[0] == L'%' ||
-
3257 chr[0] == L'!' ||
-
3258 chr[0] == L'$' ||
-
3259 chr[0] == L'&' ||
-
3260 chr[0] == L'\'' ||
-
3261 chr[0] == L'(' ||
-
3262 chr[0] == L')' ||
-
3263 chr[0] == L'*' ||
-
3264 chr[0] == L'+' ||
-
3265 chr[0] == L',' ||
-
3266 chr[0] == L';' ||
-
3267 chr[0] == L'=' ||
-
3268 chr[0] == L':' ||
-
3269 chr[0] == L'@' ||
-
3270 chr[0] == L'?' ||
-
3271 chr[0] == L'#') && chr[1] == 0 ||
-
3272 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
-
3273 {
-
3274 interval.start = start;
-
3275 return true;
-
3276 }
-
3277 }
-
3278 interval.start = (interval.end = start) + 1;
-
3279 return false;
-
3280 }
-
3281 };
-
3282
-
3286 template <class T>
-
3287 class basic_url_path : public basic_parser<T>
-
3288 {
-
3289 public:
-
3290 basic_url_path(
-
3291 _In_ const std::shared_ptr<basic_parser<T>>& path_char,
-
3292 _In_ const std::shared_ptr<basic_parser<T>>& query_start,
-
3293 _In_ const std::shared_ptr<basic_parser<T>>& bookmark_start,
-
3294 _In_ const std::locale& locale = std::locale()) :
-
3295 basic_parser<T>(locale),
-
3296 m_path_char(path_char),
-
3297 m_query_start(query_start),
-
3298 m_bookmark_start(bookmark_start)
-
3299 {}
-
3300
-
3301 virtual bool match(
-
3302 _In_reads_or_z_(end) const T* text,
-
3303 _In_ size_t start = 0,
-
3304 _In_ size_t end = (size_t)-1,
-
3305 _In_ int flags = match_default)
-
3306 {
-
3307 assert(text || start >= end);
-
3308
-
3309 interval.end = start;
-
3310 path.start = start;
-
3311 query.start = 1;
-
3312 query.end = 0;
-
3313 bookmark.start = 1;
-
3314 bookmark.end = 0;
-
3315
-
3316 for (;;) {
-
3317 if (interval.end >= end || !text[interval.end])
-
3318 break;
-
3319 if (m_query_start->match(text, interval.end, end, flags)) {
-
3320 path.end = interval.end;
-
3321 query.start = interval.end = m_query_start->interval.end;
-
3322 for (;;) {
-
3323 if (interval.end >= end || !text[interval.end]) {
-
3324 query.end = interval.end;
-
3325 break;
-
3326 }
-
3327 if (m_bookmark_start->match(text, interval.end, end, flags)) {
-
3328 query.end = interval.end;
-
3329 bookmark.start = interval.end = m_bookmark_start->interval.end;
-
3330 for (;;) {
-
3331 if (interval.end >= end || !text[interval.end]) {
-
3332 bookmark.end = interval.end;
-
3333 break;
-
3334 }
-
3335 if (m_path_char->match(text, interval.end, end, flags))
-
3336 interval.end = m_path_char->interval.end;
-
3337 else {
-
3338 bookmark.end = interval.end;
-
3339 break;
-
3340 }
-
3341 }
-
3342 interval.start = start;
-
3343 return true;
-
3344 }
-
3345 if (m_path_char->match(text, interval.end, end, flags))
-
3346 interval.end = m_path_char->interval.end;
-
3347 else {
-
3348 query.end = interval.end;
-
3349 break;
-
3350 }
-
3351 }
-
3352 interval.start = start;
-
3353 return true;
-
3354 }
-
3355 if (m_bookmark_start->match(text, interval.end, end, flags)) {
-
3356 path.end = interval.end;
-
3357 bookmark.start = interval.end = m_bookmark_start->interval.end;
-
3358 for (;;) {
-
3359 if (interval.end >= end || !text[interval.end]) {
-
3360 bookmark.end = interval.end;
-
3361 break;
-
3362 }
-
3363 if (m_path_char->match(text, interval.end, end, flags))
-
3364 interval.end = m_path_char->interval.end;
-
3365 else {
-
3366 bookmark.end = interval.end;
-
3367 break;
-
3368 }
-
3369 }
-
3370 interval.start = start;
-
3371 return true;
-
3372 }
-
3373 if (m_path_char->match(text, interval.end, end, flags))
-
3374 interval.end = m_path_char->interval.end;
-
3375 else
-
3376 break;
-
3377 }
-
3378
-
3379 if (start < interval.end) {
-
3380 path.end = interval.end;
-
3381 interval.start = start;
-
3382 return true;
-
3383 }
-
3384
-
3385 path.start = 1;
-
3386 path.end = 0;
-
3387 bookmark.start = 1;
-
3388 bookmark.end = 0;
-
3389 interval.start = (interval.end = start) + 1;
-
3390 return false;
-
3391 }
-
3392
-
3393 virtual void invalidate()
-
3394 {
-
3395 path.start = 1;
-
3396 path.end = 0;
-
3397 query.start = 1;
-
3398 query.end = 0;
-
3399 bookmark.start = 1;
-
3400 bookmark.end = 0;
-
3401 basic_parser<T>::invalidate();
-
3402 }
-
3403
-
3404 public:
-
3405 stdex::interval<size_t> path;
-
3406 stdex::interval<size_t> query;
-
3407 stdex::interval<size_t> bookmark;
-
3408
-
3409 protected:
-
3410 std::shared_ptr<basic_parser<T>> m_path_char;
-
3411 std::shared_ptr<basic_parser<T>> m_query_start;
-
3412 std::shared_ptr<basic_parser<T>> m_bookmark_start;
-
3413 };
-
3414
-
3415 using url_path = basic_url_path<char>;
-
3416 using wurl_path = basic_url_path<wchar_t>;
-
3417#ifdef _UNICODE
-
3418 using turl_path = wurl_path;
-
3419#else
-
3420 using turl_path = url_path;
-
3421#endif
-
3422 using sgml_url_path = basic_url_path<char>;
-
3423
-
3427 template <class T>
-
3428 class basic_url : public basic_parser<T>
-
3429 {
-
3430 public:
-
3431 basic_url(
-
3432 _In_ const std::shared_ptr<basic_parser<T>>& _http_scheme,
-
3433 _In_ const std::shared_ptr<basic_parser<T>>& _ftp_scheme,
-
3434 _In_ const std::shared_ptr<basic_parser<T>>& _mailto_scheme,
-
3435 _In_ const std::shared_ptr<basic_parser<T>>& _file_scheme,
-
3436 _In_ const std::shared_ptr<basic_parser<T>>& colon,
-
3437 _In_ const std::shared_ptr<basic_parser<T>>& slash,
-
3438 _In_ const std::shared_ptr<basic_parser<T>>& _username,
-
3439 _In_ const std::shared_ptr<basic_parser<T>>& _password,
-
3440 _In_ const std::shared_ptr<basic_parser<T>>& at,
-
3441 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
-
3442 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
-
3443 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
-
3444 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
-
3445 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
-
3446 _In_ const std::shared_ptr<basic_parser<T>>& _port,
-
3447 _In_ const std::shared_ptr<basic_parser<T>>& _path,
-
3448 _In_ const std::locale& locale = std::locale()) :
-
3449 basic_parser<T>(locale),
-
3450 http_scheme(_http_scheme),
-
3451 ftp_scheme(_ftp_scheme),
-
3452 mailto_scheme(_mailto_scheme),
-
3453 file_scheme(_file_scheme),
-
3454 m_colon(colon),
-
3455 m_slash(slash),
-
3456 username(_username),
-
3457 password(_password),
-
3458 m_at(at),
-
3459 m_ip_lbracket(ip_lbracket),
-
3460 m_ip_rbracket(ip_rbracket),
-
3461 ipv4_host(_ipv4_host),
-
3462 ipv6_host(_ipv6_host),
-
3463 dns_host(_dns_host),
-
3464 port(_port),
-
3465 path(_path)
-
3466 {}
-
3467
-
3468 virtual bool match(
-
3469 _In_reads_or_z_(end) const T* text,
-
3470 _In_ size_t start = 0,
-
3471 _In_ size_t end = (size_t)-1,
-
3472 _In_ int flags = match_default)
-
3473 {
-
3474 assert(text || start >= end);
-
3475
-
3476 interval.end = start;
+
1781 for (; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
1782
+
1783 if (guest->match(text, interval.end, end, flags))
+
1784 interval.end = guest->interval.end;
+
1785 else
+
1786 goto end;
+
1787
+
1788 interval.start = start;
+
1789 return true;
+
1790
+
1791 end:
+
1792 home->invalidate();
+
1793 separator->invalidate();
+
1794 guest->invalidate();
+
1795 interval.start = (interval.end = start) + 1;
+
1796 return false;
+
1797 }
+
1798
+
1799 virtual void invalidate()
+
1800 {
+
1801 home->invalidate();
+
1802 separator->invalidate();
+
1803 guest->invalidate();
+
1804 basic_parser<T>::invalidate();
+
1805 }
+
1806
+
1807 public:
+
1808 std::shared_ptr<basic_parser<T>> home;
+
1809 std::shared_ptr<basic_parser<T>> separator;
+
1810 std::shared_ptr<basic_parser<T>> guest;
+
1811
+
1812 protected:
+
1813 std::shared_ptr<basic_parser<T>> m_space;
+
1814 };
+
1815
+
1816 using score = basic_score<char>;
+
1817 using wscore = basic_score<wchar_t>;
+
1818#ifdef _UNICODE
+
1819 using tscore = wscore;
+
1820#else
+
1821 using tscore = score;
+
1822#endif
+
1823 using sgml_score = basic_score<char>;
+
1824
+
1828 template <class T>
+
1829 class basic_signed_numeral : public basic_parser<T>
+
1830 {
+
1831 public:
+
1832 basic_signed_numeral(
+
1833 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
+
1834 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
+
1835 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
+
1836 _In_ const std::shared_ptr<basic_parser<T>>& _number,
+
1837 _In_ const std::locale& locale = std::locale()) :
+
1838 basic_parser<T>(locale),
+
1839 positive_sign(_positive_sign),
+
1840 negative_sign(_negative_sign),
+
1841 special_sign(_special_sign),
+
1842 number(_number)
+
1843 {}
+
1844
+
1845 virtual bool match(
+
1846 _In_reads_or_z_(end) const T* text,
+
1847 _In_ size_t start = 0,
+
1848 _In_ size_t end = (size_t)-1,
+
1849 _In_ int flags = match_default)
+
1850 {
+
1851 assert(text || start >= end);
+
1852 interval.end = start;
+
1853 if (positive_sign && positive_sign->match(text, interval.end, end, flags)) {
+
1854 interval.end = positive_sign->interval.end;
+
1855 if (negative_sign) negative_sign->invalidate();
+
1856 if (special_sign) special_sign->invalidate();
+
1857 }
+
1858 else if (negative_sign && negative_sign->match(text, interval.end, end, flags)) {
+
1859 interval.end = negative_sign->interval.end;
+
1860 if (positive_sign) positive_sign->invalidate();
+
1861 if (special_sign) special_sign->invalidate();
+
1862 }
+
1863 else if (special_sign && special_sign->match(text, interval.end, end, flags)) {
+
1864 interval.end = special_sign->interval.end;
+
1865 if (positive_sign) positive_sign->invalidate();
+
1866 if (negative_sign) negative_sign->invalidate();
+
1867 }
+
1868 else {
+
1869 if (positive_sign) positive_sign->invalidate();
+
1870 if (negative_sign) negative_sign->invalidate();
+
1871 if (special_sign) special_sign->invalidate();
+
1872 }
+
1873 if (number->match(text, interval.end, end, flags)) {
+
1874 interval.start = start;
+
1875 interval.end = number->interval.end;
+
1876 return true;
+
1877 }
+
1878 if (positive_sign) positive_sign->invalidate();
+
1879 if (negative_sign) negative_sign->invalidate();
+
1880 if (special_sign) special_sign->invalidate();
+
1881 number->invalidate();
+
1882 interval.start = (interval.end = start) + 1;
+
1883 return false;
+
1884 }
+
1885
+
1886 virtual void invalidate()
+
1887 {
+
1888 if (positive_sign) positive_sign->invalidate();
+
1889 if (negative_sign) negative_sign->invalidate();
+
1890 if (special_sign) special_sign->invalidate();
+
1891 number->invalidate();
+
1892 basic_parser<T>::invalidate();
+
1893 }
+
1894
+
1895 public:
+
1896 std::shared_ptr<basic_parser<T>> positive_sign;
+
1897 std::shared_ptr<basic_parser<T>> negative_sign;
+
1898 std::shared_ptr<basic_parser<T>> special_sign;
+
1899 std::shared_ptr<basic_parser<T>> number;
+
1900 };
+
1901
+
1902 using signed_numeral = basic_signed_numeral<char>;
+
1903 using wsigned_numeral = basic_signed_numeral<wchar_t>;
+
1904#ifdef _UNICODE
+
1905 using tsigned_numeral = wsigned_numeral;
+
1906#else
+
1907 using tsigned_numeral = signed_numeral;
+
1908#endif
+
1909 using sgml_signed_numeral = basic_signed_numeral<char>;
+
1910
+
1914 template <class T>
+
1915 class basic_mixed_numeral : public basic_parser<T>
+
1916 {
+
1917 public:
+
1918 basic_mixed_numeral(
+
1919 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
+
1920 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
+
1921 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
+
1922 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
+
1923 _In_ const std::shared_ptr<basic_parser<T>>& space,
+
1924 _In_ const std::shared_ptr<basic_parser<T>>& _fraction,
+
1925 _In_ const std::locale& locale = std::locale()) :
+
1926 basic_parser<T>(locale),
+
1927 positive_sign(_positive_sign),
+
1928 negative_sign(_negative_sign),
+
1929 special_sign(_special_sign),
+
1930 integer(_integer),
+
1931 fraction(_fraction),
+
1932 m_space(space)
+
1933 {}
+
1934
+
1935 virtual bool match(
+
1936 _In_reads_or_z_(end) const T* text,
+
1937 _In_ size_t start = 0,
+
1938 _In_ size_t end = (size_t)-1,
+
1939 _In_ int flags = match_default)
+
1940 {
+
1941 assert(text || start >= end);
+
1942 interval.end = start;
+
1943
+
1944 if (positive_sign && positive_sign->match(text, interval.end, end, flags)) {
+
1945 interval.end = positive_sign->interval.end;
+
1946 if (negative_sign) negative_sign->invalidate();
+
1947 if (special_sign) special_sign->invalidate();
+
1948 }
+
1949 else if (negative_sign && negative_sign->match(text, interval.end, end, flags)) {
+
1950 interval.end = negative_sign->interval.end;
+
1951 if (positive_sign) positive_sign->invalidate();
+
1952 if (special_sign) special_sign->invalidate();
+
1953 }
+
1954 else if (special_sign && special_sign->match(text, interval.end, end, flags)) {
+
1955 interval.end = special_sign->interval.end;
+
1956 if (positive_sign) positive_sign->invalidate();
+
1957 if (negative_sign) negative_sign->invalidate();
+
1958 }
+
1959 else {
+
1960 if (positive_sign) positive_sign->invalidate();
+
1961 if (negative_sign) negative_sign->invalidate();
+
1962 if (special_sign) special_sign->invalidate();
+
1963 }
+
1964
+
1965 // Check for <integer> <fraction>
+
1966 const int space_match_flags = flags & ~match_multiline; // Spaces in fractions must never be broken in new line.
+
1967 if (integer->match(text, interval.end, end, flags) &&
+
1968 m_space->match(text, integer->interval.end, end, space_match_flags))
+
1969 {
+
1970 for (interval.end = m_space->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
1971 if (fraction->match(text, interval.end, end, flags)) {
+
1972 interval.start = start;
+
1973 interval.end = fraction->interval.end;
+
1974 return true;
+
1975 }
+
1976 fraction->invalidate();
+
1977 interval.start = start;
+
1978 interval.end = integer->interval.end;
+
1979 return true;
+
1980 }
+
1981
+
1982 // Check for <fraction>
+
1983 if (fraction->match(text, interval.end, end, flags)) {
+
1984 integer->invalidate();
+
1985 interval.start = start;
+
1986 interval.end = fraction->interval.end;
+
1987 return true;
+
1988 }
+
1989
+
1990 // Check for <integer>
+
1991 if (integer->match(text, interval.end, end, flags)) {
+
1992 fraction->invalidate();
+
1993 interval.start = start;
+
1994 interval.end = integer->interval.end;
+
1995 return true;
+
1996 }
+
1997
+
1998 if (positive_sign) positive_sign->invalidate();
+
1999 if (negative_sign) negative_sign->invalidate();
+
2000 if (special_sign) special_sign->invalidate();
+
2001 integer->invalidate();
+
2002 fraction->invalidate();
+
2003 interval.start = (interval.end = start) + 1;
+
2004 return false;
+
2005 }
+
2006
+
2007 virtual void invalidate()
+
2008 {
+
2009 if (positive_sign) positive_sign->invalidate();
+
2010 if (negative_sign) negative_sign->invalidate();
+
2011 if (special_sign) special_sign->invalidate();
+
2012 integer->invalidate();
+
2013 fraction->invalidate();
+
2014 basic_parser<T>::invalidate();
+
2015 }
+
2016
+
2017 public:
+
2018 std::shared_ptr<basic_parser<T>> positive_sign;
+
2019 std::shared_ptr<basic_parser<T>> negative_sign;
+
2020 std::shared_ptr<basic_parser<T>> special_sign;
+
2021 std::shared_ptr<basic_parser<T>> integer;
+
2022 std::shared_ptr<basic_parser<T>> fraction;
+
2023
+
2024 protected:
+
2025 std::shared_ptr<basic_parser<T>> m_space;
+
2026 };
+
2027
+
2028 using mixed_numeral = basic_mixed_numeral<char>;
+
2029 using wmixed_numeral = basic_mixed_numeral<wchar_t>;
+
2030#ifdef _UNICODE
+
2031 using tmixed_numeral = wmixed_numeral;
+
2032#else
+
2033 using tmixed_numeral = mixed_numeral;
+
2034#endif
+
2035 using sgml_mixed_numeral = basic_mixed_numeral<char>;
+
2036
+
2040 template <class T>
+
2041 class basic_scientific_numeral : public basic_parser<T>
+
2042 {
+
2043 public:
+
2044 basic_scientific_numeral(
+
2045 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
+
2046 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
+
2047 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
+
2048 _In_ const std::shared_ptr<basic_integer<T>>& _integer,
+
2049 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
+
2050 _In_ const std::shared_ptr<basic_integer<T>>& _decimal,
+
2051 _In_ const std::shared_ptr<basic_parser<T>>& _exponent_symbol,
+
2052 _In_ const std::shared_ptr<basic_parser<T>>& _positive_exp_sign,
+
2053 _In_ const std::shared_ptr<basic_parser<T>>& _negative_exp_sign,
+
2054 _In_ const std::shared_ptr<basic_integer<T>>& _exponent,
+
2055 _In_ const std::locale& locale = std::locale()) :
+
2056 basic_parser<T>(locale),
+
2057 positive_sign(_positive_sign),
+
2058 negative_sign(_negative_sign),
+
2059 special_sign(_special_sign),
+
2060 integer(_integer),
+
2061 decimal_separator(_decimal_separator),
+
2062 decimal(_decimal),
+
2063 exponent_symbol(_exponent_symbol),
+
2064 positive_exp_sign(_positive_exp_sign),
+
2065 negative_exp_sign(_negative_exp_sign),
+
2066 exponent(_exponent),
+
2067 value(std::numeric_limits<double>::quiet_NaN())
+
2068 {}
+
2069
+
2070 virtual bool match(
+
2071 _In_reads_or_z_(end) const T* text,
+
2072 _In_ size_t start = 0,
+
2073 _In_ size_t end = (size_t)-1,
+
2074 _In_ int flags = match_default)
+
2075 {
+
2076 assert(text || start >= end);
+
2077 interval.end = start;
+
2078
+
2079 if (positive_sign && positive_sign->match(text, interval.end, end, flags)) {
+
2080 interval.end = positive_sign->interval.end;
+
2081 if (negative_sign) negative_sign->invalidate();
+
2082 if (special_sign) special_sign->invalidate();
+
2083 }
+
2084 else if (negative_sign && negative_sign->match(text, interval.end, end, flags)) {
+
2085 interval.end = negative_sign->interval.end;
+
2086 if (positive_sign) positive_sign->invalidate();
+
2087 if (special_sign) special_sign->invalidate();
+
2088 }
+
2089 else if (special_sign && special_sign->match(text, interval.end, end, flags)) {
+
2090 interval.end = special_sign->interval.end;
+
2091 if (positive_sign) positive_sign->invalidate();
+
2092 if (negative_sign) negative_sign->invalidate();
+
2093 }
+
2094 else {
+
2095 if (positive_sign) positive_sign->invalidate();
+
2096 if (negative_sign) negative_sign->invalidate();
+
2097 if (special_sign) special_sign->invalidate();
+
2098 }
+
2099
+
2100 if (integer->match(text, interval.end, end, flags))
+
2101 interval.end = integer->interval.end;
+
2102
+
2103 if (decimal_separator->match(text, interval.end, end, flags) &&
+
2104 decimal->match(text, decimal_separator->interval.end, end, flags))
+
2105 interval.end = decimal->interval.end;
+
2106 else {
+
2107 decimal_separator->invalidate();
+
2108 decimal->invalidate();
+
2109 }
+
2110
+
2111 if (!integer->interval.empty() &&
+
2112 decimal->interval.empty())
+
2113 {
+
2114 // No integer part, no decimal part.
+
2115 if (positive_sign) positive_sign->invalidate();
+
2116 if (negative_sign) negative_sign->invalidate();
+
2117 if (special_sign) special_sign->invalidate();
+
2118 integer->invalidate();
+
2119 decimal_separator->invalidate();
+
2120 decimal->invalidate();
+
2121 if (exponent_symbol) exponent_symbol->invalidate();
+
2122 if (positive_exp_sign) positive_exp_sign->invalidate();
+
2123 if (negative_exp_sign) negative_exp_sign->invalidate();
+
2124 if (exponent) exponent->invalidate();
+
2125 interval.start = (interval.end = start) + 1;
+
2126 return false;
+
2127 }
+
2128
+
2129 if (exponent_symbol && exponent_symbol->match(text, interval.end, end, flags) &&
+
2130 (positive_exp_sign && positive_exp_sign->match(text, exponent_symbol->interval.end, end, flags) &&
+
2131 exponent && exponent->match(text, positive_exp_sign->interval.end, end, flags) ||
+
2132 exponent && exponent->match(text, exponent_symbol->interval.end, end, flags)))
+
2133 {
+
2134 interval.end = exponent->interval.end;
+
2135 if (negative_exp_sign) negative_exp_sign->invalidate();
+
2136 }
+
2137 else if (exponent_symbol && exponent_symbol->match(text, interval.end, end, flags) &&
+
2138 negative_exp_sign && negative_exp_sign->match(text, exponent_symbol->interval.end, end, flags) &&
+
2139 exponent && exponent->match(text, negative_exp_sign->interval.end, end, flags))
+
2140 {
+
2141 interval.end = exponent->interval.end;
+
2142 if (positive_exp_sign) positive_exp_sign->invalidate();
+
2143 }
+
2144 else {
+
2145 if (exponent_symbol) exponent_symbol->invalidate();
+
2146 if (positive_exp_sign) positive_exp_sign->invalidate();
+
2147 if (negative_exp_sign) negative_exp_sign->invalidate();
+
2148 if (exponent) exponent->invalidate();
+
2149 }
+
2150
+
2151 value = (double)integer->value;
+
2152 if (decimal->interval)
+
2153 value += (double)decimal->value * pow(10.0, -(double)decimal->interval.size());
+
2154 if (negative_sign && negative_sign->interval)
+
2155 value = -value;
+
2156 if (exponent && exponent->interval) {
+
2157 double e = (double)exponent->value;
+
2158 if (negative_exp_sign && negative_exp_sign->interval)
+
2159 e = -e;
+
2160 value *= pow(10.0, e);
+
2161 }
+
2162
+
2163 interval.start = start;
+
2164 return true;
+
2165 }
+
2166
+
2167 virtual void invalidate()
+
2168 {
+
2169 if (positive_sign) positive_sign->invalidate();
+
2170 if (negative_sign) negative_sign->invalidate();
+
2171 if (special_sign) special_sign->invalidate();
+
2172 integer->invalidate();
+
2173 decimal_separator->invalidate();
+
2174 decimal->invalidate();
+
2175 if (exponent_symbol) exponent_symbol->invalidate();
+
2176 if (positive_exp_sign) positive_exp_sign->invalidate();
+
2177 if (negative_exp_sign) negative_exp_sign->invalidate();
+
2178 if (exponent) exponent->invalidate();
+
2179 value = std::numeric_limits<double>::quiet_NaN();
+
2180 basic_parser<T>::invalidate();
+
2181 }
+
2182
+
2183 public:
+
2184 std::shared_ptr<basic_parser<T>> positive_sign;
+
2185 std::shared_ptr<basic_parser<T>> negative_sign;
+
2186 std::shared_ptr<basic_parser<T>> special_sign;
+
2187 std::shared_ptr<basic_integer<T>> integer;
+
2188 std::shared_ptr<basic_parser<T>> decimal_separator;
+
2189 std::shared_ptr<basic_integer<T>> decimal;
+
2190 std::shared_ptr<basic_parser<T>> exponent_symbol;
+
2191 std::shared_ptr<basic_parser<T>> positive_exp_sign;
+
2192 std::shared_ptr<basic_parser<T>> negative_exp_sign;
+
2193 std::shared_ptr<basic_integer<T>> exponent;
+
2194 double value;
+
2195 };
+
2196
+
2197 using scientific_numeral = basic_scientific_numeral<char>;
+
2198 using wscientific_numeral = basic_scientific_numeral<wchar_t>;
+
2199#ifdef _UNICODE
+
2200 using tscientific_numeral = wscientific_numeral;
+
2201#else
+
2202 using tscientific_numeral = scientific_numeral;
+
2203#endif
+
2204 using sgml_scientific_numeral = basic_scientific_numeral<char>;
+
2205
+
2209 template <class T>
+
2210 class basic_monetary_numeral : public basic_parser<T>
+
2211 {
+
2212 public:
+
2213 basic_monetary_numeral(
+
2214 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
+
2215 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
+
2216 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
+
2217 _In_ const std::shared_ptr<basic_parser<T>>& _currency,
+
2218 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
+
2219 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
+
2220 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
+
2221 _In_ const std::locale& locale = std::locale()) :
+
2222 basic_parser<T>(locale),
+
2223 positive_sign(_positive_sign),
+
2224 negative_sign(_negative_sign),
+
2225 special_sign(_special_sign),
+
2226 currency(_currency),
+
2227 integer(_integer),
+
2228 decimal_separator(_decimal_separator),
+
2229 decimal(_decimal)
+
2230 {}
+
2231
+
2232 virtual bool match(
+
2233 _In_reads_or_z_(end) const T* text,
+
2234 _In_ size_t start = 0,
+
2235 _In_ size_t end = (size_t)-1,
+
2236 _In_ int flags = match_default)
+
2237 {
+
2238 assert(text || start >= end);
+
2239 interval.end = start;
+
2240
+
2241 if (positive_sign->match(text, interval.end, end, flags)) {
+
2242 interval.end = positive_sign->interval.end;
+
2243 if (negative_sign) negative_sign->invalidate();
+
2244 if (special_sign) special_sign->invalidate();
+
2245 }
+
2246 else if (negative_sign->match(text, interval.end, end, flags)) {
+
2247 interval.end = negative_sign->interval.end;
+
2248 if (positive_sign) positive_sign->invalidate();
+
2249 if (special_sign) special_sign->invalidate();
+
2250 }
+
2251 else if (special_sign->match(text, interval.end, end, flags)) {
+
2252 interval.end = special_sign->interval.end;
+
2253 if (positive_sign) positive_sign->invalidate();
+
2254 if (negative_sign) negative_sign->invalidate();
+
2255 }
+
2256 else {
+
2257 if (positive_sign) positive_sign->invalidate();
+
2258 if (negative_sign) negative_sign->invalidate();
+
2259 if (special_sign) special_sign->invalidate();
+
2260 }
+
2261
+
2262 if (currency->match(text, interval.end, end, flags))
+
2263 interval.end = currency->interval.end;
+
2264 else {
+
2265 if (positive_sign) positive_sign->invalidate();
+
2266 if (negative_sign) negative_sign->invalidate();
+
2267 if (special_sign) special_sign->invalidate();
+
2268 integer->invalidate();
+
2269 decimal_separator->invalidate();
+
2270 decimal->invalidate();
+
2271 interval.start = (interval.end = start) + 1;
+
2272 return false;
+
2273 }
+
2274
+
2275 if (integer->match(text, interval.end, end, flags))
+
2276 interval.end = integer->interval.end;
+
2277 if (decimal_separator->match(text, interval.end, end, flags) &&
+
2278 decimal->match(text, decimal_separator->interval.end, end, flags))
+
2279 interval.end = decimal->interval.end;
+
2280 else {
+
2281 decimal_separator->invalidate();
+
2282 decimal->invalidate();
+
2283 }
+
2284
+
2285 if (integer->interval.empty() &&
+
2286 decimal->interval.empty())
+
2287 {
+
2288 // No integer part, no decimal part.
+
2289 if (positive_sign) positive_sign->invalidate();
+
2290 if (negative_sign) negative_sign->invalidate();
+
2291 if (special_sign) special_sign->invalidate();
+
2292 currency->invalidate();
+
2293 integer->invalidate();
+
2294 decimal_separator->invalidate();
+
2295 decimal->invalidate();
+
2296 interval.start = (interval.end = start) + 1;
+
2297 return false;
+
2298 }
+
2299
+
2300 interval.start = start;
+
2301 return true;
+
2302 }
+
2303
+
2304 virtual void invalidate()
+
2305 {
+
2306 if (positive_sign) positive_sign->invalidate();
+
2307 if (negative_sign) negative_sign->invalidate();
+
2308 if (special_sign) special_sign->invalidate();
+
2309 currency->invalidate();
+
2310 integer->invalidate();
+
2311 decimal_separator->invalidate();
+
2312 decimal->invalidate();
+
2313 basic_parser<T>::invalidate();
+
2314 }
+
2315
+
2316 public:
+
2317 std::shared_ptr<basic_parser<T>> positive_sign;
+
2318 std::shared_ptr<basic_parser<T>> negative_sign;
+
2319 std::shared_ptr<basic_parser<T>> special_sign;
+
2320 std::shared_ptr<basic_parser<T>> currency;
+
2321 std::shared_ptr<basic_parser<T>> integer;
+
2322 std::shared_ptr<basic_parser<T>> decimal_separator;
+
2323 std::shared_ptr<basic_parser<T>> decimal;
+
2324 };
+
2325
+
2326 using monetary_numeral = basic_monetary_numeral<char>;
+
2327 using wmonetary_numeral = basic_monetary_numeral<wchar_t>;
+
2328#ifdef _UNICODE
+
2329 using tmonetary_numeral = wmonetary_numeral;
+
2330#else
+
2331 using tmonetary_numeral = monetary_numeral;
+
2332#endif
+
2333 using sgml_monetary_numeral = basic_monetary_numeral<char>;
+
2334
+
2338 template <class T>
+
2339 class basic_ipv4_address : public basic_parser<T>
+
2340 {
+
2341 public:
+
2342 basic_ipv4_address(
+
2343 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
+
2344 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
+
2345 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
+
2346 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
+
2347 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
+
2348 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
+
2349 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
+
2350 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
+
2351 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
+
2352 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
+
2353 _In_ const std::shared_ptr<basic_parser<T>>& separator,
+
2354 _In_ const std::locale& locale = std::locale()) :
+
2355 basic_parser<T>(locale),
+
2356 m_digit_0(digit_0),
+
2357 m_digit_1(digit_1),
+
2358 m_digit_2(digit_2),
+
2359 m_digit_3(digit_3),
+
2360 m_digit_4(digit_4),
+
2361 m_digit_5(digit_5),
+
2362 m_digit_6(digit_6),
+
2363 m_digit_7(digit_7),
+
2364 m_digit_8(digit_8),
+
2365 m_digit_9(digit_9),
+
2366 m_separator(separator)
+
2367 {
+
2368 value.s_addr = 0;
+
2369 }
+
2370
+
2371 virtual bool match(
+
2372 _In_reads_or_z_(end) const T* text,
+
2373 _In_ size_t start = 0,
+
2374 _In_ size_t end = (size_t)-1,
+
2375 _In_ int flags = match_default)
+
2376 {
+
2377 assert(text || start >= end);
+
2378 interval.end = start;
+
2379 value.s_addr = 0;
+
2380
+
2381 size_t i;
+
2382 for (i = 0; i < 4; i++) {
+
2383 if (i) {
+
2384 if (m_separator->match(text, interval.end, end, flags))
+
2385 interval.end = m_separator->interval.end;
+
2386 else
+
2387 goto error;
+
2388 }
+
2389
+
2390 components[i].start = interval.end;
+
2391 bool is_empty = true;
+
2392 size_t x;
+
2393 for (x = 0; interval.end < end && text[interval.end];) {
+
2394 size_t dig, digit_end;
+
2395 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
+
2396 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
+
2397 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
+
2398 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
+
2399 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
+
2400 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
+
2401 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
+
2402 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
+
2403 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
+
2404 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
+
2405 else break;
+
2406 size_t x_n = x * 10 + dig;
+
2407 if (x_n <= 255) {
+
2408 x = x_n;
+
2409 interval.end = digit_end;
+
2410 is_empty = false;
+
2411 }
+
2412 else
+
2413 break;
+
2414 }
+
2415 if (is_empty)
+
2416 goto error;
+
2417 components[i].end = interval.end;
+
2418 value.s_addr = (value.s_addr << 8) | (uint8_t)x;
+
2419 }
+
2420 if (i < 4)
+
2421 goto error;
+
2422
+
2423 interval.start = start;
+
2424 return true;
+
2425
+
2426 error:
+
2427 components[0].start = 1;
+
2428 components[0].end = 0;
+
2429 components[1].start = 1;
+
2430 components[1].end = 0;
+
2431 components[2].start = 1;
+
2432 components[2].end = 0;
+
2433 components[3].start = 1;
+
2434 components[3].end = 0;
+
2435 value.s_addr = 0;
+
2436 interval.start = (interval.end = start) + 1;
+
2437 return false;
+
2438 }
+
2439
+
2440 virtual void invalidate()
+
2441 {
+
2442 components[0].start = 1;
+
2443 components[0].end = 0;
+
2444 components[1].start = 1;
+
2445 components[1].end = 0;
+
2446 components[2].start = 1;
+
2447 components[2].end = 0;
+
2448 components[3].start = 1;
+
2449 components[3].end = 0;
+
2450 value.s_addr = 0;
+
2451 basic_parser<T>::invalidate();
+
2452 }
+
2453
+
2454 public:
+
2455 stdex::interval<size_t> components[4];
+
2456 struct in_addr value;
+
2457
+
2458 protected:
+
2459 std::shared_ptr<basic_parser<T>>
+
2460 m_digit_0,
+
2461 m_digit_1,
+
2462 m_digit_2,
+
2463 m_digit_3,
+
2464 m_digit_4,
+
2465 m_digit_5,
+
2466 m_digit_6,
+
2467 m_digit_7,
+
2468 m_digit_8,
+
2469 m_digit_9;
+
2470 std::shared_ptr<basic_parser<T>> m_separator;
+
2471 };
+
2472
+
2473 using ipv4_address = basic_ipv4_address<char>;
+
2474 using wipv4_address = basic_ipv4_address<wchar_t>;
+
2475#ifdef _UNICODE
+
2476 using tipv4_address = wipv4_address;
+
2477#else
+
2478 using tipv4_address = ipv4_address;
+
2479#endif
+
2480 using sgml_ipv4_address = basic_ipv4_address<char>;
+
2481
+
2485 template <class T>
+
2486 class basic_ipv6_scope_id_char : public basic_parser<T>
+
2487 {
+
2488 public:
+
2489 basic_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
+
2490
+
2491 virtual bool match(
+
2492 _In_reads_or_z_(end) const T* text,
+
2493 _In_ size_t start = 0,
+
2494 _In_ size_t end = (size_t)-1,
+
2495 _In_ int flags = match_default)
+
2496 {
+
2497 assert(text || start >= end);
+
2498 if (start < end && text[start]) {
+
2499 if (text[start] == '-' ||
+
2500 text[start] == '_' ||
+
2501 text[start] == ':' ||
+
2502 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
+
2503 {
+
2504 interval.end = (interval.start = start) + 1;
+
2505 return true;
+
2506 }
+
2507 }
+
2508 interval.start = (interval.end = start) + 1;
+
2509 return false;
+
2510 }
+
2511 };
+
2512
+
2513 using ipv6_scope_id_char = basic_ipv6_scope_id_char<char>;
+
2514 using wipv6_scope_id_char = basic_ipv6_scope_id_char<wchar_t>;
+
2515#ifdef _UNICODE
+
2516 using tipv6_scope_id_char = wipv6_scope_id_char;
+
2517#else
+
2518 using tipv6_scope_id_char = ipv6_scope_id_char;
+
2519#endif
+
2520
+
2524 class sgml_ipv6_scope_id_char : public sgml_parser
+
2525 {
+
2526 public:
+
2527 sgml_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : sgml_parser(locale) {}
+
2528
+
2529 virtual bool match(
+
2530 _In_reads_or_z_(end) const char* text,
+
2531 _In_ size_t start = 0,
+
2532 _In_ size_t end = (size_t)-1,
+
2533 _In_ int flags = match_default)
+
2534 {
+
2535 assert(text || start >= end);
+
2536 if (start < end && text[start]) {
+
2537 wchar_t buf[3];
+
2538 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
2539 const wchar_t* chr_end = chr + stdex::strlen(chr);
+
2540 if ((chr[0] == L'-' ||
+
2541 chr[0] == L'_' ||
+
2542 chr[0] == L':') && chr[1] == 0 ||
+
2543 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
+
2544 {
+
2545 interval.start = start;
+
2546 return true;
+
2547 }
+
2548 }
+
2549 interval.start = (interval.end = start) + 1;
+
2550 return false;
+
2551 }
+
2552 };
+
2553
+
2557 template <class T>
+
2558 class basic_ipv6_address : public basic_parser<T>
+
2559 {
+
2560 public:
+
2561 basic_ipv6_address(
+
2562 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
+
2563 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
+
2564 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
+
2565 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
+
2566 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
+
2567 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
+
2568 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
+
2569 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
+
2570 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
+
2571 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
+
2572 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
+
2573 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
+
2574 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
+
2575 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
+
2576 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
+
2577 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
+
2578 _In_ const std::shared_ptr<basic_parser<T>>& separator,
+
2579 _In_ const std::shared_ptr<basic_parser<T>>& scope_id_separator = nullptr,
+
2580 _In_ const std::shared_ptr<basic_parser<T>>& _scope_id = nullptr,
+
2581 _In_ const std::locale& locale = std::locale()) :
+
2582 basic_parser<T>(locale),
+
2583 m_digit_0(digit_0),
+
2584 m_digit_1(digit_1),
+
2585 m_digit_2(digit_2),
+
2586 m_digit_3(digit_3),
+
2587 m_digit_4(digit_4),
+
2588 m_digit_5(digit_5),
+
2589 m_digit_6(digit_6),
+
2590 m_digit_7(digit_7),
+
2591 m_digit_8(digit_8),
+
2592 m_digit_9(digit_9),
+
2593 m_digit_10(digit_10),
+
2594 m_digit_11(digit_11),
+
2595 m_digit_12(digit_12),
+
2596 m_digit_13(digit_13),
+
2597 m_digit_14(digit_14),
+
2598 m_digit_15(digit_15),
+
2599 m_separator(separator),
+
2600 m_scope_id_separator(scope_id_separator),
+
2601 scope_id(_scope_id)
+
2602 {
+
2603 memset(&value, 0, sizeof(value));
+
2604 }
+
2605
+
2606 virtual bool match(
+
2607 _In_reads_or_z_(end) const T* text,
+
2608 _In_ size_t start = 0,
+
2609 _In_ size_t end = (size_t)-1,
+
2610 _In_ int flags = match_default)
+
2611 {
+
2612 assert(text || start >= end);
+
2613 interval.end = start;
+
2614 memset(&value, 0, sizeof(value));
+
2615
+
2616 size_t i, compaction_i = (size_t)-1, compaction_start = start;
+
2617 for (i = 0; i < 8; i++) {
+
2618 bool is_empty = true;
+
2619
+
2620 if (m_separator->match(text, interval.end, end, flags)) {
+
2621 if (m_separator->match(text, m_separator->interval.end, end, flags)) {
+
2622 // :: found
+
2623 if (compaction_i == (size_t)-1) {
+
2624 // Zero compaction start
+
2625 compaction_i = i;
+
2626 compaction_start = m_separator->interval.start;
+
2627 interval.end = m_separator->interval.end;
+
2628 }
+
2629 else {
+
2630 // More than one zero compaction
+
2631 break;
+
2632 }
+
2633 }
+
2634 else if (i) {
+
2635 // Inner : found
+
2636 interval.end = m_separator->interval.end;
+
2637 }
+
2638 else {
+
2639 // Leading : found
+
2640 goto error;
+
2641 }
+
2642 }
+
2643 else if (i) {
+
2644 // : missing
+
2645 break;
+
2646 }
+
2647
+
2648 components[i].start = interval.end;
+
2649 size_t x;
+
2650 for (x = 0; interval.end < end && text[interval.end];) {
+
2651 size_t dig, digit_end;
+
2652 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
+
2653 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
+
2654 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
+
2655 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
+
2656 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
+
2657 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
+
2658 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
+
2659 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
+
2660 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
+
2661 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
+
2662 else if (m_digit_10->match(text, interval.end, end, flags)) { dig = 10; digit_end = m_digit_10->interval.end; }
+
2663 else if (m_digit_11->match(text, interval.end, end, flags)) { dig = 11; digit_end = m_digit_11->interval.end; }
+
2664 else if (m_digit_12->match(text, interval.end, end, flags)) { dig = 12; digit_end = m_digit_12->interval.end; }
+
2665 else if (m_digit_13->match(text, interval.end, end, flags)) { dig = 13; digit_end = m_digit_13->interval.end; }
+
2666 else if (m_digit_14->match(text, interval.end, end, flags)) { dig = 14; digit_end = m_digit_14->interval.end; }
+
2667 else if (m_digit_15->match(text, interval.end, end, flags)) { dig = 15; digit_end = m_digit_15->interval.end; }
+
2668 else break;
+
2669 size_t x_n = x * 16 + dig;
+
2670 if (x_n <= 0xffff) {
+
2671 x = x_n;
+
2672 interval.end = digit_end;
+
2673 is_empty = false;
+
2674 }
+
2675 else
+
2676 break;
+
2677 }
+
2678 if (is_empty) {
+
2679 if (compaction_i != (size_t)-1) {
+
2680 // Zero compaction active: no sweat.
+
2681 break;
+
2682 }
+
2683 goto error;
+
2684 }
+
2685 components[i].end = interval.end;
+
2686 value.s6_words[i] = (uint16_t)x;
+
2687 }
+
2688
+
2689 if (compaction_i != (size_t)-1) {
+
2690 // Align components right due to zero compaction.
+
2691 size_t j, k;
+
2692 for (j = 8, k = i; k > compaction_i;) {
+
2693 value.s6_words[--j] = value.s6_words[--k];
+
2694 components[j] = components[k];
+
2695 }
+
2696 for (; j > compaction_i;) {
+
2697 value.s6_words[--j] = 0;
+
2698 components[j].start =
+
2699 components[j].end = compaction_start;
+
2700 }
+
2701 }
+
2702 else if (i < 8)
+
2703 goto error;
+
2704
+
2705 if (m_scope_id_separator && m_scope_id_separator->match(text, interval.end, end, flags) &&
+
2706 scope_id && scope_id->match(text, m_scope_id_separator->interval.end, end, flags))
+
2707 interval.end = scope_id->interval.end;
+
2708 else if (scope_id)
+
2709 scope_id->invalidate();
+
2710
+
2711 interval.start = start;
+
2712 return true;
+
2713
+
2714 error:
+
2715 components[0].start = 1;
+
2716 components[0].end = 0;
+
2717 components[1].start = 1;
+
2718 components[1].end = 0;
+
2719 components[2].start = 1;
+
2720 components[2].end = 0;
+
2721 components[3].start = 1;
+
2722 components[3].end = 0;
+
2723 components[4].start = 1;
+
2724 components[4].end = 0;
+
2725 components[5].start = 1;
+
2726 components[5].end = 0;
+
2727 components[6].start = 1;
+
2728 components[6].end = 0;
+
2729 components[7].start = 1;
+
2730 components[7].end = 0;
+
2731 memset(&value, 0, sizeof(value));
+
2732 if (scope_id) scope_id->invalidate();
+
2733 interval.start = (interval.end = start) + 1;
+
2734 return false;
+
2735 }
+
2736
+
2737 virtual void invalidate()
+
2738 {
+
2739 components[0].start = 1;
+
2740 components[0].end = 0;
+
2741 components[1].start = 1;
+
2742 components[1].end = 0;
+
2743 components[2].start = 1;
+
2744 components[2].end = 0;
+
2745 components[3].start = 1;
+
2746 components[3].end = 0;
+
2747 components[4].start = 1;
+
2748 components[4].end = 0;
+
2749 components[5].start = 1;
+
2750 components[5].end = 0;
+
2751 components[6].start = 1;
+
2752 components[6].end = 0;
+
2753 components[7].start = 1;
+
2754 components[7].end = 0;
+
2755 memset(&value, 0, sizeof(value));
+
2756 if (scope_id) scope_id->invalidate();
+
2757 basic_parser<T>::invalidate();
+
2758 }
+
2759
+
2760 public:
+
2761 stdex::interval<size_t> components[8];
+
2762 struct in6_addr value;
+
2763 std::shared_ptr<basic_parser<T>> scope_id;
+
2764
+
2765 protected:
+
2766 std::shared_ptr<basic_parser<T>>
+
2767 m_digit_0,
+
2768 m_digit_1,
+
2769 m_digit_2,
+
2770 m_digit_3,
+
2771 m_digit_4,
+
2772 m_digit_5,
+
2773 m_digit_6,
+
2774 m_digit_7,
+
2775 m_digit_8,
+
2776 m_digit_9,
+
2777 m_digit_10,
+
2778 m_digit_11,
+
2779 m_digit_12,
+
2780 m_digit_13,
+
2781 m_digit_14,
+
2782 m_digit_15;
+
2783 std::shared_ptr<basic_parser<T>> m_separator, m_scope_id_separator;
+
2784 };
+
2785
+
2786 using ipv6_address = basic_ipv6_address<char>;
+
2787 using wipv6_address = basic_ipv6_address<wchar_t>;
+
2788#ifdef _UNICODE
+
2789 using tipv6_address = wipv6_address;
+
2790#else
+
2791 using tipv6_address = ipv6_address;
+
2792#endif
+
2793 using sgml_ipv6_address = basic_ipv6_address<char>;
+
2794
+
2798 template <class T>
+
2799 class basic_dns_domain_char : public basic_parser<T>
+
2800 {
+
2801 public:
+
2802 basic_dns_domain_char(
+
2803 _In_ bool allow_idn,
+
2804 _In_ const std::locale& locale = std::locale()) :
+
2805 basic_parser<T>(locale),
+
2806 m_allow_idn(allow_idn),
+
2807 allow_on_edge(true)
+
2808 {}
+
2809
+
2810 virtual bool match(
+
2811 _In_reads_or_z_(end) const T* text,
+
2812 _In_ size_t start = 0,
+
2813 _In_ size_t end = (size_t)-1,
+
2814 _In_ int flags = match_default)
+
2815 {
+
2816 assert(text || start >= end);
+
2817 if (start < end && text[start]) {
+
2818 if (('A' <= text[start] && text[start] <= 'Z') ||
+
2819 ('a' <= text[start] && text[start] <= 'z') ||
+
2820 ('0' <= text[start] && text[start] <= '9'))
+
2821 allow_on_edge = true;
+
2822 else if (text[start] == '-')
+
2823 allow_on_edge = false;
+
2824 else if (m_allow_idn && std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
+
2825 allow_on_edge = true;
+
2826 else {
+
2827 interval.start = (interval.end = start) + 1;
+
2828 return false;
+
2829 }
+
2830 interval.end = (interval.start = start) + 1;
+
2831 return true;
+
2832 }
+
2833 interval.start = (interval.end = start) + 1;
+
2834 return false;
+
2835 }
+
2836
+
2837 public:
+
2838 bool allow_on_edge;
+
2839
+
2840 protected:
+
2841 bool m_allow_idn;
+
2842 };
+
2843
+
2844 using dns_domain_char = basic_dns_domain_char<char>;
+
2845 using wdns_domain_char = basic_dns_domain_char<wchar_t>;
+
2846#ifdef _UNICODE
+
2847 using tdns_domain_char = wdns_domain_char;
+
2848#else
+
2849 using tdns_domain_char = dns_domain_char;
+
2850#endif
+
2851
+
2855 class sgml_dns_domain_char : public basic_dns_domain_char<char>
+
2856 {
+
2857 public:
+
2858 sgml_dns_domain_char(
+
2859 _In_ bool allow_idn,
+
2860 _In_ const std::locale& locale = std::locale()) :
+
2861 basic_dns_domain_char<char>(allow_idn, locale)
+
2862 {}
+
2863
+
2864 virtual bool match(
+
2865 _In_reads_or_z_(end) const char* text,
+
2866 _In_ size_t start = 0,
+
2867 _In_ size_t end = (size_t)-1,
+
2868 _In_ int flags = match_default)
+
2869 {
+
2870 assert(text || start >= end);
+
2871 if (start < end && text[start]) {
+
2872 wchar_t buf[3];
+
2873 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
2874 const wchar_t* chr_end = chr + stdex::strlen(chr);
+
2875 if ((('A' <= chr[0] && chr[0] <= 'Z') ||
+
2876 ('a' <= chr[0] && chr[0] <= 'z') ||
+
2877 ('0' <= chr[0] && chr[0] <= '9')) && chr[1] == 0)
+
2878 allow_on_edge = true;
+
2879 else if (chr[0] == '-' && chr[1] == 0)
+
2880 allow_on_edge = false;
+
2881 else if (m_allow_idn && std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
+
2882 allow_on_edge = true;
+
2883 else {
+
2884 interval.start = (interval.end = start) + 1;
+
2885 return false;
+
2886 }
+
2887 interval.start = start;
+
2888 return true;
+
2889 }
+
2890 interval.start = (interval.end = start) + 1;
+
2891 return false;
+
2892 }
+
2893 };
+
2894
+
2898 template <class T>
+
2899 class basic_dns_name : public basic_parser<T>
+
2900 {
+
2901 public:
+
2902 basic_dns_name(
+
2903 _In_ bool allow_absolute,
+
2904 _In_ const std::shared_ptr<basic_dns_domain_char<T>>& domain_char,
+
2905 _In_ const std::shared_ptr<basic_parser<T>>& separator,
+
2906 _In_ const std::locale& locale = std::locale()) :
+
2907 basic_parser<T>(locale),
+
2908 m_allow_absolute(allow_absolute),
+
2909 m_domain_char(domain_char),
+
2910 m_separator(separator)
+
2911 {}
+
2912
+
2913 virtual bool match(
+
2914 _In_reads_or_z_(end) const T* text,
+
2915 _In_ size_t start = 0,
+
2916 _In_ size_t end = (size_t)-1,
+
2917 _In_ int flags = match_default)
+
2918 {
+
2919 assert(text || start >= end);
+
2920 size_t i = start, count;
+
2921 for (count = 0; i < end && text[i] && count < 127; count++) {
+
2922 if (m_domain_char->match(text, i, end, flags) &&
+
2923 m_domain_char->allow_on_edge)
+
2924 {
+
2925 // Domain start
+
2926 interval.end = i = m_domain_char->interval.end;
+
2927 while (i < end && text[i]) {
+
2928 if (m_domain_char->allow_on_edge &&
+
2929 m_separator->match(text, i, end, flags))
+
2930 {
+
2931 // Domain end
+
2932 if (m_allow_absolute)
+
2933 interval.end = i = m_separator->interval.end;
+
2934 else {
+
2935 interval.end = i;
+
2936 i = m_separator->interval.end;
+
2937 }
+
2938 break;
+
2939 }
+
2940 if (m_domain_char->match(text, i, end, flags)) {
+
2941 if (m_domain_char->allow_on_edge)
+
2942 interval.end = i = m_domain_char->interval.end;
+
2943 else
+
2944 i = m_domain_char->interval.end;
+
2945 }
+
2946 else {
+
2947 interval.start = start;
+
2948 return true;
+
2949 }
+
2950 }
+
2951 }
+
2952 else
+
2953 break;
+
2954 }
+
2955 if (count) {
+
2956 interval.start = start;
+
2957 return true;
+
2958 }
+
2959 interval.start = (interval.end = start) + 1;
+
2960 return false;
+
2961 }
+
2962
+
2963 protected:
+
2964 bool m_allow_absolute;
+
2965 std::shared_ptr<basic_dns_domain_char<T>> m_domain_char;
+
2966 std::shared_ptr<basic_parser<T>> m_separator;
+
2967 };
+
2968
+
2969 using dns_name = basic_dns_name<char>;
+
2970 using wdns_name = basic_dns_name<wchar_t>;
+
2971#ifdef _UNICODE
+
2972 using tdns_name = wdns_name;
+
2973#else
+
2974 using tdns_name = dns_name;
+
2975#endif
+
2976 using sgml_dns_name = basic_dns_name<char>;
+
2977
+
2981 template <class T>
+
2982 class basic_url_username_char : public basic_parser<T>
+
2983 {
+
2984 public:
+
2985 basic_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
+
2986
+
2987 virtual bool match(
+
2988 _In_reads_or_z_(end) const T* text,
+
2989 _In_ size_t start = 0,
+
2990 _In_ size_t end = (size_t)-1,
+
2991 _In_ int flags = match_default)
+
2992 {
+
2993 assert(text || start >= end);
+
2994 if (start < end && text[start]) {
+
2995 if (text[start] == '-' ||
+
2996 text[start] == '.' ||
+
2997 text[start] == '_' ||
+
2998 text[start] == '~' ||
+
2999 text[start] == '%' ||
+
3000 text[start] == '!' ||
+
3001 text[start] == '$' ||
+
3002 text[start] == '&' ||
+
3003 text[start] == '\'' ||
+
3004 //text[start] == '(' ||
+
3005 //text[start] == ')' ||
+
3006 text[start] == '*' ||
+
3007 text[start] == '+' ||
+
3008 text[start] == ',' ||
+
3009 text[start] == ';' ||
+
3010 text[start] == '=' ||
+
3011 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
+
3012 {
+
3013 interval.end = (interval.start = start) + 1;
+
3014 return true;
+
3015 }
+
3016 }
+
3017 interval.start = (interval.end = start) + 1;
+
3018 return false;
+
3019 }
+
3020 };
+
3021
+
3022 using url_username_char = basic_url_username_char<char>;
+
3023 using wurl_username_char = basic_url_username_char<wchar_t>;
+
3024#ifdef _UNICODE
+
3025 using turl_username_char = wurl_username_char;
+
3026#else
+
3027 using turl_username_char = url_username_char;
+
3028#endif
+
3029
+
3033 class sgml_url_username_char : public basic_url_username_char<char>
+
3034 {
+
3035 public:
+
3036 sgml_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_url_username_char<char>(locale) {}
+
3037
+
3038 virtual bool match(
+
3039 _In_reads_or_z_(end) const char* text,
+
3040 _In_ size_t start = 0,
+
3041 _In_ size_t end = (size_t)-1,
+
3042 _In_ int flags = match_default)
+
3043 {
+
3044 assert(text || start >= end);
+
3045 if (start < end && text[start]) {
+
3046 wchar_t buf[3];
+
3047 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
3048 const wchar_t* chr_end = chr + stdex::strlen(chr);
+
3049 if ((chr[0] == L'-' ||
+
3050 chr[0] == L'.' ||
+
3051 chr[0] == L'_' ||
+
3052 chr[0] == L'~' ||
+
3053 chr[0] == L'%' ||
+
3054 chr[0] == L'!' ||
+
3055 chr[0] == L'$' ||
+
3056 chr[0] == L'&' ||
+
3057 chr[0] == L'\'' ||
+
3058 //chr[0] == L'(' ||
+
3059 //chr[0] == L')' ||
+
3060 chr[0] == L'*' ||
+
3061 chr[0] == L'+' ||
+
3062 chr[0] == L',' ||
+
3063 chr[0] == L';' ||
+
3064 chr[0] == L'=') && chr[1] == 0 ||
+
3065 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
+
3066 {
+
3067 interval.start = start;
+
3068 return true;
+
3069 }
+
3070 }
+
3071
+
3072 interval.start = (interval.end = start) + 1;
+
3073 return false;
+
3074 }
+
3075 };
+
3076
+
3080 template <class T>
+
3081 class basic_url_password_char : public basic_parser<T>
+
3082 {
+
3083 public:
+
3084 basic_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
+
3085
+
3086 virtual bool match(
+
3087 _In_reads_or_z_(end) const T* text,
+
3088 _In_ size_t start = 0,
+
3089 _In_ size_t end = (size_t)-1,
+
3090 _In_ int flags = match_default)
+
3091 {
+
3092 assert(text || start >= end);
+
3093 if (start < end && text[start]) {
+
3094 if (text[start] == '-' ||
+
3095 text[start] == '.' ||
+
3096 text[start] == '_' ||
+
3097 text[start] == '~' ||
+
3098 text[start] == '%' ||
+
3099 text[start] == '!' ||
+
3100 text[start] == '$' ||
+
3101 text[start] == '&' ||
+
3102 text[start] == '\'' ||
+
3103 text[start] == '(' ||
+
3104 text[start] == ')' ||
+
3105 text[start] == '*' ||
+
3106 text[start] == '+' ||
+
3107 text[start] == ',' ||
+
3108 text[start] == ';' ||
+
3109 text[start] == '=' ||
+
3110 text[start] == ':' ||
+
3111 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
+
3112 {
+
3113 interval.end = (interval.start = start) + 1;
+
3114 return true;
+
3115 }
+
3116 }
+
3117 interval.start = (interval.end = start) + 1;
+
3118 return false;
+
3119 }
+
3120 };
+
3121
+
3122 using url_password_char = basic_url_password_char<char>;
+
3123 using wurl_password_char = basic_url_password_char<wchar_t>;
+
3124#ifdef _UNICODE
+
3125 using turl_password_char = wurl_password_char;
+
3126#else
+
3127 using turl_password_char = url_password_char;
+
3128#endif
+
3129
+
3133 class sgml_url_password_char : public basic_url_password_char<char>
+
3134 {
+
3135 public:
+
3136 sgml_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_url_password_char<char>(locale) {}
+
3137
+
3138 virtual bool match(
+
3139 _In_reads_or_z_(end) const char* text,
+
3140 _In_ size_t start = 0,
+
3141 _In_ size_t end = (size_t)-1,
+
3142 _In_ int flags = match_default)
+
3143 {
+
3144 assert(text || start >= end);
+
3145 if (start < end && text[start]) {
+
3146 wchar_t buf[3];
+
3147 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
3148 const wchar_t* chr_end = chr + stdex::strlen(chr);
+
3149 if ((chr[0] == L'-' ||
+
3150 chr[0] == L'.' ||
+
3151 chr[0] == L'_' ||
+
3152 chr[0] == L'~' ||
+
3153 chr[0] == L'%' ||
+
3154 chr[0] == L'!' ||
+
3155 chr[0] == L'$' ||
+
3156 chr[0] == L'&' ||
+
3157 chr[0] == L'\'' ||
+
3158 chr[0] == L'(' ||
+
3159 chr[0] == L')' ||
+
3160 chr[0] == L'*' ||
+
3161 chr[0] == L'+' ||
+
3162 chr[0] == L',' ||
+
3163 chr[0] == L';' ||
+
3164 chr[0] == L'=' ||
+
3165 chr[0] == L':') && chr[1] == 0 ||
+
3166 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
+
3167 {
+
3168 interval.start = start;
+
3169 return true;
+
3170 }
+
3171 }
+
3172 interval.start = (interval.end = start) + 1;
+
3173 return false;
+
3174 }
+
3175 };
+
3176
+
3180 template <class T>
+
3181 class basic_url_path_char : public basic_parser<T>
+
3182 {
+
3183 public:
+
3184 basic_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
+
3185
+
3186 virtual bool match(
+
3187 _In_reads_or_z_(end) const T* text,
+
3188 _In_ size_t start = 0,
+
3189 _In_ size_t end = (size_t)-1,
+
3190 _In_ int flags = match_default)
+
3191 {
+
3192 assert(text || start >= end);
+
3193 if (start < end && text[start]) {
+
3194 if (text[start] == '/' ||
+
3195 text[start] == '-' ||
+
3196 text[start] == '.' ||
+
3197 text[start] == '_' ||
+
3198 text[start] == '~' ||
+
3199 text[start] == '%' ||
+
3200 text[start] == '!' ||
+
3201 text[start] == '$' ||
+
3202 text[start] == '&' ||
+
3203 text[start] == '\'' ||
+
3204 text[start] == '(' ||
+
3205 text[start] == ')' ||
+
3206 text[start] == '*' ||
+
3207 text[start] == '+' ||
+
3208 text[start] == ',' ||
+
3209 text[start] == ';' ||
+
3210 text[start] == '=' ||
+
3211 text[start] == ':' ||
+
3212 text[start] == '@' ||
+
3213 text[start] == '?' ||
+
3214 text[start] == '#' ||
+
3215 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
+
3216 {
+
3217 interval.end = (interval.start = start) + 1;
+
3218 return true;
+
3219 }
+
3220 }
+
3221 interval.start = (interval.end = start) + 1;
+
3222 return false;
+
3223 }
+
3224 };
+
3225
+
3226 using url_path_char = basic_url_path_char<char>;
+
3227 using wurl_path_char = basic_url_path_char<wchar_t>;
+
3228#ifdef _UNICODE
+
3229 using turl_path_char = wurl_path_char;
+
3230#else
+
3231 using turl_path_char = url_path_char;
+
3232#endif
+
3233
+
3237 class sgml_url_path_char : public basic_url_path_char<char>
+
3238 {
+
3239 public:
+
3240 sgml_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_url_path_char<char>(locale) {}
+
3241
+
3242 virtual bool match(
+
3243 _In_reads_or_z_(end) const char* text,
+
3244 _In_ size_t start = 0,
+
3245 _In_ size_t end = (size_t)-1,
+
3246 _In_ int flags = match_default)
+
3247 {
+
3248 assert(text || start >= end);
+
3249 if (start < end && text[start]) {
+
3250 wchar_t buf[3];
+
3251 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
+
3252 const wchar_t* chr_end = chr + stdex::strlen(chr);
+
3253 if ((chr[0] == L'/' ||
+
3254 chr[0] == L'-' ||
+
3255 chr[0] == L'.' ||
+
3256 chr[0] == L'_' ||
+
3257 chr[0] == L'~' ||
+
3258 chr[0] == L'%' ||
+
3259 chr[0] == L'!' ||
+
3260 chr[0] == L'$' ||
+
3261 chr[0] == L'&' ||
+
3262 chr[0] == L'\'' ||
+
3263 chr[0] == L'(' ||
+
3264 chr[0] == L')' ||
+
3265 chr[0] == L'*' ||
+
3266 chr[0] == L'+' ||
+
3267 chr[0] == L',' ||
+
3268 chr[0] == L';' ||
+
3269 chr[0] == L'=' ||
+
3270 chr[0] == L':' ||
+
3271 chr[0] == L'@' ||
+
3272 chr[0] == L'?' ||
+
3273 chr[0] == L'#') && chr[1] == 0 ||
+
3274 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
+
3275 {
+
3276 interval.start = start;
+
3277 return true;
+
3278 }
+
3279 }
+
3280 interval.start = (interval.end = start) + 1;
+
3281 return false;
+
3282 }
+
3283 };
+
3284
+
3288 template <class T>
+
3289 class basic_url_path : public basic_parser<T>
+
3290 {
+
3291 public:
+
3292 basic_url_path(
+
3293 _In_ const std::shared_ptr<basic_parser<T>>& path_char,
+
3294 _In_ const std::shared_ptr<basic_parser<T>>& query_start,
+
3295 _In_ const std::shared_ptr<basic_parser<T>>& bookmark_start,
+
3296 _In_ const std::locale& locale = std::locale()) :
+
3297 basic_parser<T>(locale),
+
3298 m_path_char(path_char),
+
3299 m_query_start(query_start),
+
3300 m_bookmark_start(bookmark_start)
+
3301 {}
+
3302
+
3303 virtual bool match(
+
3304 _In_reads_or_z_(end) const T* text,
+
3305 _In_ size_t start = 0,
+
3306 _In_ size_t end = (size_t)-1,
+
3307 _In_ int flags = match_default)
+
3308 {
+
3309 assert(text || start >= end);
+
3310
+
3311 interval.end = start;
+
3312 path.start = start;
+
3313 query.start = 1;
+
3314 query.end = 0;
+
3315 bookmark.start = 1;
+
3316 bookmark.end = 0;
+
3317
+
3318 for (;;) {
+
3319 if (interval.end >= end || !text[interval.end])
+
3320 break;
+
3321 if (m_query_start->match(text, interval.end, end, flags)) {
+
3322 path.end = interval.end;
+
3323 query.start = interval.end = m_query_start->interval.end;
+
3324 for (;;) {
+
3325 if (interval.end >= end || !text[interval.end]) {
+
3326 query.end = interval.end;
+
3327 break;
+
3328 }
+
3329 if (m_bookmark_start->match(text, interval.end, end, flags)) {
+
3330 query.end = interval.end;
+
3331 bookmark.start = interval.end = m_bookmark_start->interval.end;
+
3332 for (;;) {
+
3333 if (interval.end >= end || !text[interval.end]) {
+
3334 bookmark.end = interval.end;
+
3335 break;
+
3336 }
+
3337 if (m_path_char->match(text, interval.end, end, flags))
+
3338 interval.end = m_path_char->interval.end;
+
3339 else {
+
3340 bookmark.end = interval.end;
+
3341 break;
+
3342 }
+
3343 }
+
3344 interval.start = start;
+
3345 return true;
+
3346 }
+
3347 if (m_path_char->match(text, interval.end, end, flags))
+
3348 interval.end = m_path_char->interval.end;
+
3349 else {
+
3350 query.end = interval.end;
+
3351 break;
+
3352 }
+
3353 }
+
3354 interval.start = start;
+
3355 return true;
+
3356 }
+
3357 if (m_bookmark_start->match(text, interval.end, end, flags)) {
+
3358 path.end = interval.end;
+
3359 bookmark.start = interval.end = m_bookmark_start->interval.end;
+
3360 for (;;) {
+
3361 if (interval.end >= end || !text[interval.end]) {
+
3362 bookmark.end = interval.end;
+
3363 break;
+
3364 }
+
3365 if (m_path_char->match(text, interval.end, end, flags))
+
3366 interval.end = m_path_char->interval.end;
+
3367 else {
+
3368 bookmark.end = interval.end;
+
3369 break;
+
3370 }
+
3371 }
+
3372 interval.start = start;
+
3373 return true;
+
3374 }
+
3375 if (m_path_char->match(text, interval.end, end, flags))
+
3376 interval.end = m_path_char->interval.end;
+
3377 else
+
3378 break;
+
3379 }
+
3380
+
3381 if (start < interval.end) {
+
3382 path.end = interval.end;
+
3383 interval.start = start;
+
3384 return true;
+
3385 }
+
3386
+
3387 path.start = 1;
+
3388 path.end = 0;
+
3389 bookmark.start = 1;
+
3390 bookmark.end = 0;
+
3391 interval.start = (interval.end = start) + 1;
+
3392 return false;
+
3393 }
+
3394
+
3395 virtual void invalidate()
+
3396 {
+
3397 path.start = 1;
+
3398 path.end = 0;
+
3399 query.start = 1;
+
3400 query.end = 0;
+
3401 bookmark.start = 1;
+
3402 bookmark.end = 0;
+
3403 basic_parser<T>::invalidate();
+
3404 }
+
3405
+
3406 public:
+
3407 stdex::interval<size_t> path;
+
3408 stdex::interval<size_t> query;
+
3409 stdex::interval<size_t> bookmark;
+
3410
+
3411 protected:
+
3412 std::shared_ptr<basic_parser<T>> m_path_char;
+
3413 std::shared_ptr<basic_parser<T>> m_query_start;
+
3414 std::shared_ptr<basic_parser<T>> m_bookmark_start;
+
3415 };
+
3416
+
3417 using url_path = basic_url_path<char>;
+
3418 using wurl_path = basic_url_path<wchar_t>;
+
3419#ifdef _UNICODE
+
3420 using turl_path = wurl_path;
+
3421#else
+
3422 using turl_path = url_path;
+
3423#endif
+
3424 using sgml_url_path = basic_url_path<char>;
+
3425
+
3429 template <class T>
+
3430 class basic_url : public basic_parser<T>
+
3431 {
+
3432 public:
+
3433 basic_url(
+
3434 _In_ const std::shared_ptr<basic_parser<T>>& _http_scheme,
+
3435 _In_ const std::shared_ptr<basic_parser<T>>& _ftp_scheme,
+
3436 _In_ const std::shared_ptr<basic_parser<T>>& _mailto_scheme,
+
3437 _In_ const std::shared_ptr<basic_parser<T>>& _file_scheme,
+
3438 _In_ const std::shared_ptr<basic_parser<T>>& colon,
+
3439 _In_ const std::shared_ptr<basic_parser<T>>& slash,
+
3440 _In_ const std::shared_ptr<basic_parser<T>>& _username,
+
3441 _In_ const std::shared_ptr<basic_parser<T>>& _password,
+
3442 _In_ const std::shared_ptr<basic_parser<T>>& at,
+
3443 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
+
3444 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
+
3445 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
+
3446 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
+
3447 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
+
3448 _In_ const std::shared_ptr<basic_parser<T>>& _port,
+
3449 _In_ const std::shared_ptr<basic_parser<T>>& _path,
+
3450 _In_ const std::locale& locale = std::locale()) :
+
3451 basic_parser<T>(locale),
+
3452 http_scheme(_http_scheme),
+
3453 ftp_scheme(_ftp_scheme),
+
3454 mailto_scheme(_mailto_scheme),
+
3455 file_scheme(_file_scheme),
+
3456 m_colon(colon),
+
3457 m_slash(slash),
+
3458 username(_username),
+
3459 password(_password),
+
3460 m_at(at),
+
3461 m_ip_lbracket(ip_lbracket),
+
3462 m_ip_rbracket(ip_rbracket),
+
3463 ipv4_host(_ipv4_host),
+
3464 ipv6_host(_ipv6_host),
+
3465 dns_host(_dns_host),
+
3466 port(_port),
+
3467 path(_path)
+
3468 {}
+
3469
+
3470 virtual bool match(
+
3471 _In_reads_or_z_(end) const T* text,
+
3472 _In_ size_t start = 0,
+
3473 _In_ size_t end = (size_t)-1,
+
3474 _In_ int flags = match_default)
+
3475 {
+
3476 assert(text || start >= end);
3477
-
3478 if (http_scheme->match(text, interval.end, end, flags) &&
-
3479 m_colon->match(text, http_scheme->interval.end, end, flags) &&
-
3480 m_slash->match(text, m_colon->interval.end, end, flags) &&
-
3481 m_slash->match(text, m_slash->interval.end, end, flags))
-
3482 {
-
3483 // http://
-
3484 interval.end = m_slash->interval.end;
-
3485 ftp_scheme->invalidate();
-
3486 mailto_scheme->invalidate();
-
3487 file_scheme->invalidate();
-
3488 }
-
3489 else if (ftp_scheme->match(text, interval.end, end, flags) &&
-
3490 m_colon->match(text, ftp_scheme->interval.end, end, flags) &&
-
3491 m_slash->match(text, m_colon->interval.end, end, flags) &&
-
3492 m_slash->match(text, m_slash->interval.end, end, flags))
-
3493 {
-
3494 // ftp://
-
3495 interval.end = m_slash->interval.end;
-
3496 http_scheme->invalidate();
-
3497 mailto_scheme->invalidate();
-
3498 file_scheme->invalidate();
-
3499 }
-
3500 else if (mailto_scheme->match(text, interval.end, end, flags) &&
-
3501 m_colon->match(text, mailto_scheme->interval.end, end, flags))
-
3502 {
-
3503 // mailto:
-
3504 interval.end = m_colon->interval.end;
-
3505 http_scheme->invalidate();
-
3506 ftp_scheme->invalidate();
-
3507 file_scheme->invalidate();
-
3508 }
-
3509 else if (file_scheme->match(text, interval.end, end, flags) &&
-
3510 m_colon->match(text, file_scheme->interval.end, end, flags) &&
-
3511 m_slash->match(text, m_colon->interval.end, end, flags) &&
-
3512 m_slash->match(text, m_slash->interval.end, end, flags))
-
3513 {
-
3514 // file://
-
3515 interval.end = m_slash->interval.end;
-
3516 http_scheme->invalidate();
-
3517 ftp_scheme->invalidate();
-
3518 mailto_scheme->invalidate();
-
3519 }
-
3520 else {
-
3521 // Default to http:
-
3522 http_scheme->invalidate();
-
3523 ftp_scheme->invalidate();
-
3524 mailto_scheme->invalidate();
-
3525 file_scheme->invalidate();
-
3526 }
-
3527
-
3528 if (ftp_scheme->interval) {
-
3529 if (username->match(text, interval.end, end, flags)) {
-
3530 if (m_colon->match(text, username->interval.end, end, flags) &&
-
3531 password->match(text, m_colon->interval.end, end, flags) &&
-
3532 m_at->match(text, password->interval.end, end, flags))
-
3533 {
-
3534 // Username and password
-
3535 interval.end = m_at->interval.end;
-
3536 }
-
3537 else if (m_at->match(text, interval.end, end, flags)) {
-
3538 // Username only
-
3539 interval.end = m_at->interval.end;
-
3540 password->invalidate();
-
3541 }
-
3542 else {
-
3543 username->invalidate();
-
3544 password->invalidate();
-
3545 }
-
3546 }
-
3547 else {
-
3548 username->invalidate();
-
3549 password->invalidate();
-
3550 }
-
3551
-
3552 if (ipv4_host->match(text, interval.end, end, flags)) {
-
3553 // Host is IPv4
-
3554 interval.end = ipv4_host->interval.end;
-
3555 ipv6_host->invalidate();
-
3556 dns_host->invalidate();
-
3557 }
-
3558 else if (
-
3559 m_ip_lbracket->match(text, interval.end, end, flags) &&
-
3560 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
-
3561 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
-
3562 {
-
3563 // Host is IPv6
-
3564 interval.end = m_ip_rbracket->interval.end;
-
3565 ipv4_host->invalidate();
-
3566 dns_host->invalidate();
-
3567 }
-
3568 else if (dns_host->match(text, interval.end, end, flags)) {
-
3569 // Host is hostname
-
3570 interval.end = dns_host->interval.end;
-
3571 ipv4_host->invalidate();
-
3572 ipv6_host->invalidate();
-
3573 }
-
3574 else {
-
3575 invalidate();
-
3576 return false;
-
3577 }
-
3578
-
3579 if (m_colon->match(text, interval.end, end, flags) &&
-
3580 port->match(text, m_colon->interval.end, end, flags))
-
3581 {
-
3582 // Port
-
3583 interval.end = port->interval.end;
-
3584 }
-
3585 else
-
3586 port->invalidate();
-
3587
-
3588 if (path->match(text, interval.end, end, flags)) {
-
3589 // Path
-
3590 interval.end = path->interval.end;
-
3591 }
-
3592
-
3593 interval.start = start;
-
3594 return true;
-
3595 }
-
3596
-
3597 if (mailto_scheme->interval) {
-
3598 if (username->match(text, interval.end, end, flags) &&
-
3599 m_at->match(text, username->interval.end, end, flags))
-
3600 {
-
3601 // Username
-
3602 interval.end = m_at->interval.end;
-
3603 }
-
3604 else {
-
3605 invalidate();
-
3606 return false;
-
3607 }
-
3608
-
3609 if (m_ip_lbracket->match(text, interval.end, end, flags) &&
-
3610 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
-
3611 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
-
3612 {
-
3613 // Host is IPv4
-
3614 interval.end = m_ip_rbracket->interval.end;
-
3615 ipv6_host->invalidate();
-
3616 dns_host->invalidate();
-
3617 }
-
3618 else if (
-
3619 m_ip_lbracket->match(text, interval.end, end, flags) &&
-
3620 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
-
3621 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
-
3622 {
-
3623 // Host is IPv6
-
3624 interval.end = m_ip_rbracket->interval.end;
-
3625 ipv4_host->invalidate();
-
3626 dns_host->invalidate();
-
3627 }
-
3628 else if (dns_host->match(text, interval.end, end, flags)) {
-
3629 // Host is hostname
-
3630 interval.end = dns_host->interval.end;
-
3631 ipv4_host->invalidate();
-
3632 ipv6_host->invalidate();
-
3633 }
-
3634 else {
-
3635 invalidate();
-
3636 return false;
-
3637 }
-
3638
-
3639 password->invalidate();
-
3640 port->invalidate();
-
3641 path->invalidate();
-
3642 interval.start = start;
-
3643 return true;
-
3644 }
-
3645
-
3646 if (file_scheme->interval) {
-
3647 if (path->match(text, interval.end, end, flags)) {
-
3648 // Path
-
3649 interval.end = path->interval.end;
-
3650 }
-
3651
-
3652 username->invalidate();
-
3653 password->invalidate();
-
3654 ipv4_host->invalidate();
-
3655 ipv6_host->invalidate();
-
3656 dns_host->invalidate();
-
3657 port->invalidate();
-
3658 interval.start = start;
-
3659 return true;
-
3660 }
-
3661
-
3662 // "http://" found or defaulted to
+
3478 interval.end = start;
+
3479
+
3480 if (http_scheme->match(text, interval.end, end, flags) &&
+
3481 m_colon->match(text, http_scheme->interval.end, end, flags) &&
+
3482 m_slash->match(text, m_colon->interval.end, end, flags) &&
+
3483 m_slash->match(text, m_slash->interval.end, end, flags))
+
3484 {
+
3485 // http://
+
3486 interval.end = m_slash->interval.end;
+
3487 ftp_scheme->invalidate();
+
3488 mailto_scheme->invalidate();
+
3489 file_scheme->invalidate();
+
3490 }
+
3491 else if (ftp_scheme->match(text, interval.end, end, flags) &&
+
3492 m_colon->match(text, ftp_scheme->interval.end, end, flags) &&
+
3493 m_slash->match(text, m_colon->interval.end, end, flags) &&
+
3494 m_slash->match(text, m_slash->interval.end, end, flags))
+
3495 {
+
3496 // ftp://
+
3497 interval.end = m_slash->interval.end;
+
3498 http_scheme->invalidate();
+
3499 mailto_scheme->invalidate();
+
3500 file_scheme->invalidate();
+
3501 }
+
3502 else if (mailto_scheme->match(text, interval.end, end, flags) &&
+
3503 m_colon->match(text, mailto_scheme->interval.end, end, flags))
+
3504 {
+
3505 // mailto:
+
3506 interval.end = m_colon->interval.end;
+
3507 http_scheme->invalidate();
+
3508 ftp_scheme->invalidate();
+
3509 file_scheme->invalidate();
+
3510 }
+
3511 else if (file_scheme->match(text, interval.end, end, flags) &&
+
3512 m_colon->match(text, file_scheme->interval.end, end, flags) &&
+
3513 m_slash->match(text, m_colon->interval.end, end, flags) &&
+
3514 m_slash->match(text, m_slash->interval.end, end, flags))
+
3515 {
+
3516 // file://
+
3517 interval.end = m_slash->interval.end;
+
3518 http_scheme->invalidate();
+
3519 ftp_scheme->invalidate();
+
3520 mailto_scheme->invalidate();
+
3521 }
+
3522 else {
+
3523 // Default to http:
+
3524 http_scheme->invalidate();
+
3525 ftp_scheme->invalidate();
+
3526 mailto_scheme->invalidate();
+
3527 file_scheme->invalidate();
+
3528 }
+
3529
+
3530 if (ftp_scheme->interval) {
+
3531 if (username->match(text, interval.end, end, flags)) {
+
3532 if (m_colon->match(text, username->interval.end, end, flags) &&
+
3533 password->match(text, m_colon->interval.end, end, flags) &&
+
3534 m_at->match(text, password->interval.end, end, flags))
+
3535 {
+
3536 // Username and password
+
3537 interval.end = m_at->interval.end;
+
3538 }
+
3539 else if (m_at->match(text, interval.end, end, flags)) {
+
3540 // Username only
+
3541 interval.end = m_at->interval.end;
+
3542 password->invalidate();
+
3543 }
+
3544 else {
+
3545 username->invalidate();
+
3546 password->invalidate();
+
3547 }
+
3548 }
+
3549 else {
+
3550 username->invalidate();
+
3551 password->invalidate();
+
3552 }
+
3553
+
3554 if (ipv4_host->match(text, interval.end, end, flags)) {
+
3555 // Host is IPv4
+
3556 interval.end = ipv4_host->interval.end;
+
3557 ipv6_host->invalidate();
+
3558 dns_host->invalidate();
+
3559 }
+
3560 else if (
+
3561 m_ip_lbracket->match(text, interval.end, end, flags) &&
+
3562 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
+
3563 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
+
3564 {
+
3565 // Host is IPv6
+
3566 interval.end = m_ip_rbracket->interval.end;
+
3567 ipv4_host->invalidate();
+
3568 dns_host->invalidate();
+
3569 }
+
3570 else if (dns_host->match(text, interval.end, end, flags)) {
+
3571 // Host is hostname
+
3572 interval.end = dns_host->interval.end;
+
3573 ipv4_host->invalidate();
+
3574 ipv6_host->invalidate();
+
3575 }
+
3576 else {
+
3577 invalidate();
+
3578 return false;
+
3579 }
+
3580
+
3581 if (m_colon->match(text, interval.end, end, flags) &&
+
3582 port->match(text, m_colon->interval.end, end, flags))
+
3583 {
+
3584 // Port
+
3585 interval.end = port->interval.end;
+
3586 }
+
3587 else
+
3588 port->invalidate();
+
3589
+
3590 if (path->match(text, interval.end, end, flags)) {
+
3591 // Path
+
3592 interval.end = path->interval.end;
+
3593 }
+
3594
+
3595 interval.start = start;
+
3596 return true;
+
3597 }
+
3598
+
3599 if (mailto_scheme->interval) {
+
3600 if (username->match(text, interval.end, end, flags) &&
+
3601 m_at->match(text, username->interval.end, end, flags))
+
3602 {
+
3603 // Username
+
3604 interval.end = m_at->interval.end;
+
3605 }
+
3606 else {
+
3607 invalidate();
+
3608 return false;
+
3609 }
+
3610
+
3611 if (m_ip_lbracket->match(text, interval.end, end, flags) &&
+
3612 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
+
3613 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
+
3614 {
+
3615 // Host is IPv4
+
3616 interval.end = m_ip_rbracket->interval.end;
+
3617 ipv6_host->invalidate();
+
3618 dns_host->invalidate();
+
3619 }
+
3620 else if (
+
3621 m_ip_lbracket->match(text, interval.end, end, flags) &&
+
3622 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
+
3623 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
+
3624 {
+
3625 // Host is IPv6
+
3626 interval.end = m_ip_rbracket->interval.end;
+
3627 ipv4_host->invalidate();
+
3628 dns_host->invalidate();
+
3629 }
+
3630 else if (dns_host->match(text, interval.end, end, flags)) {
+
3631 // Host is hostname
+
3632 interval.end = dns_host->interval.end;
+
3633 ipv4_host->invalidate();
+
3634 ipv6_host->invalidate();
+
3635 }
+
3636 else {
+
3637 invalidate();
+
3638 return false;
+
3639 }
+
3640
+
3641 password->invalidate();
+
3642 port->invalidate();
+
3643 path->invalidate();
+
3644 interval.start = start;
+
3645 return true;
+
3646 }
+
3647
+
3648 if (file_scheme->interval) {
+
3649 if (path->match(text, interval.end, end, flags)) {
+
3650 // Path
+
3651 interval.end = path->interval.end;
+
3652 }
+
3653
+
3654 username->invalidate();
+
3655 password->invalidate();
+
3656 ipv4_host->invalidate();
+
3657 ipv6_host->invalidate();
+
3658 dns_host->invalidate();
+
3659 port->invalidate();
+
3660 interval.start = start;
+
3661 return true;
+
3662 }
3663
-
3664 // If "http://" explicit, test for username&password.
-
3665 if (http_scheme->interval &&
-
3666 username->match(text, interval.end, end, flags))
-
3667 {
-
3668 if (m_colon->match(text, username->interval.end, end, flags) &&
-
3669 password->match(text, m_colon->interval.end, end, flags) &&
-
3670 m_at->match(text, password->interval.end, end, flags))
-
3671 {
-
3672 // Username and password
-
3673 interval.end = m_at->interval.end;
-
3674 }
-
3675 else if (m_at->match(text, username->interval.end, end, flags)) {
-
3676 // Username only
-
3677 interval.end = m_at->interval.end;
-
3678 password->invalidate();
-
3679 }
-
3680 else {
-
3681 username->invalidate();
-
3682 password->invalidate();
-
3683 }
-
3684 }
-
3685 else {
-
3686 username->invalidate();
-
3687 password->invalidate();
-
3688 }
-
3689
-
3690 if (ipv4_host->match(text, interval.end, end, flags)) {
-
3691 // Host is IPv4
-
3692 interval.end = ipv4_host->interval.end;
-
3693 ipv6_host->invalidate();
-
3694 dns_host->invalidate();
-
3695 }
-
3696 else if (
-
3697 m_ip_lbracket->match(text, interval.end, end, flags) &&
-
3698 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
-
3699 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
-
3700 {
-
3701 // Host is IPv6
-
3702 interval.end = m_ip_rbracket->interval.end;
-
3703 ipv4_host->invalidate();
-
3704 dns_host->invalidate();
-
3705 }
-
3706 else if (dns_host->match(text, interval.end, end, flags)) {
-
3707 // Host is hostname
-
3708 interval.end = dns_host->interval.end;
-
3709 ipv4_host->invalidate();
-
3710 ipv6_host->invalidate();
-
3711 }
-
3712 else {
-
3713 invalidate();
-
3714 return false;
-
3715 }
-
3716
-
3717 if (m_colon->match(text, interval.end, end, flags) &&
-
3718 port->match(text, m_colon->interval.end, end, flags))
-
3719 {
-
3720 // Port
-
3721 interval.end = port->interval.end;
-
3722 }
-
3723 else
-
3724 port->invalidate();
-
3725
-
3726 if (path->match(text, interval.end, end, flags)) {
-
3727 // Path
-
3728 interval.end = path->interval.end;
-
3729 }
-
3730
-
3731 interval.start = start;
-
3732 return true;
-
3733 }
-
3734
-
3735 virtual void invalidate()
-
3736 {
-
3737 http_scheme->invalidate();
-
3738 ftp_scheme->invalidate();
-
3739 mailto_scheme->invalidate();
-
3740 file_scheme->invalidate();
-
3741 username->invalidate();
-
3742 password->invalidate();
-
3743 ipv4_host->invalidate();
-
3744 ipv6_host->invalidate();
-
3745 dns_host->invalidate();
-
3746 port->invalidate();
-
3747 path->invalidate();
-
3748 basic_parser<T>::invalidate();
-
3749 }
-
3750
-
3751 public:
-
3752 std::shared_ptr<basic_parser<T>> http_scheme;
-
3753 std::shared_ptr<basic_parser<T>> ftp_scheme;
-
3754 std::shared_ptr<basic_parser<T>> mailto_scheme;
-
3755 std::shared_ptr<basic_parser<T>> file_scheme;
-
3756 std::shared_ptr<basic_parser<T>> username;
-
3757 std::shared_ptr<basic_parser<T>> password;
-
3758 std::shared_ptr<basic_parser<T>> ipv4_host;
-
3759 std::shared_ptr<basic_parser<T>> ipv6_host;
-
3760 std::shared_ptr<basic_parser<T>> dns_host;
-
3761 std::shared_ptr<basic_parser<T>> port;
-
3762 std::shared_ptr<basic_parser<T>> path;
-
3763
-
3764 protected:
-
3765 std::shared_ptr<basic_parser<T>> m_colon;
-
3766 std::shared_ptr<basic_parser<T>> m_slash;
-
3767 std::shared_ptr<basic_parser<T>> m_at;
-
3768 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
-
3769 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
-
3770 };
-
3771
-
3772 using url = basic_url<char>;
-
3773 using wurl = basic_url<wchar_t>;
-
3774#ifdef _UNICODE
-
3775 using turl = wurl;
-
3776#else
-
3777 using turl = url;
-
3778#endif
-
3779 using sgml_url = basic_url<char>;
-
3780
-
3784 template <class T>
-
3785 class basic_email_address : public basic_parser<T>
-
3786 {
-
3787 public:
-
3788 basic_email_address(
-
3789 _In_ const std::shared_ptr<basic_parser<T>>& _username,
-
3790 _In_ const std::shared_ptr<basic_parser<T>>& at,
-
3791 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
-
3792 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
-
3793 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
-
3794 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
-
3795 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
-
3796 _In_ const std::locale& locale = std::locale()) :
-
3797 basic_parser<T>(locale),
-
3798 username(_username),
-
3799 m_at(at),
-
3800 m_ip_lbracket(ip_lbracket),
-
3801 m_ip_rbracket(ip_rbracket),
-
3802 ipv4_host(_ipv4_host),
-
3803 ipv6_host(_ipv6_host),
-
3804 dns_host(_dns_host)
-
3805 {}
-
3806
-
3807 virtual bool match(
-
3808 _In_reads_or_z_(end) const T* text,
-
3809 _In_ size_t start = 0,
-
3810 _In_ size_t end = (size_t)-1,
-
3811 _In_ int flags = match_default)
-
3812 {
-
3813 assert(text || start >= end);
-
3814
-
3815 if (username->match(text, start, end, flags) &&
-
3816 m_at->match(text, username->interval.end, end, flags))
-
3817 {
-
3818 // Username@
-
3819 if (m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
-
3820 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
-
3821 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
-
3822 {
-
3823 // Host is IPv4
-
3824 interval.end = m_ip_rbracket->interval.end;
-
3825 ipv6_host->invalidate();
-
3826 dns_host->invalidate();
-
3827 }
-
3828 else if (
-
3829 m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
-
3830 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
-
3831 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
-
3832 {
-
3833 // Host is IPv6
-
3834 interval.end = m_ip_rbracket->interval.end;
-
3835 ipv4_host->invalidate();
-
3836 dns_host->invalidate();
-
3837 }
-
3838 else if (dns_host->match(text, m_at->interval.end, end, flags)) {
-
3839 // Host is hostname
-
3840 interval.end = dns_host->interval.end;
-
3841 ipv4_host->invalidate();
-
3842 ipv6_host->invalidate();
-
3843 }
-
3844 else
-
3845 goto error;
-
3846 interval.start = start;
-
3847 return true;
-
3848 }
-
3849
-
3850 error:
-
3851 username->invalidate();
-
3852 ipv4_host->invalidate();
-
3853 ipv6_host->invalidate();
-
3854 dns_host->invalidate();
-
3855 interval.start = (interval.end = start) + 1;
-
3856 return false;
-
3857 }
-
3858
-
3859 virtual void invalidate()
-
3860 {
-
3861 username->invalidate();
-
3862 ipv4_host->invalidate();
-
3863 ipv6_host->invalidate();
-
3864 dns_host->invalidate();
-
3865 basic_parser<T>::invalidate();
-
3866 }
-
3867
-
3868 public:
-
3869 std::shared_ptr<basic_parser<T>> username;
-
3870 std::shared_ptr<basic_parser<T>> ipv4_host;
-
3871 std::shared_ptr<basic_parser<T>> ipv6_host;
-
3872 std::shared_ptr<basic_parser<T>> dns_host;
-
3873
-
3874 protected:
-
3875 std::shared_ptr<basic_parser<T>> m_at;
-
3876 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
-
3877 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
-
3878 };
-
3879
-
3880 using email_address = basic_email_address<char>;
-
3881 using wemail_address = basic_email_address<wchar_t>;
-
3882#ifdef _UNICODE
-
3883 using temail_address = wemail_address;
-
3884#else
-
3885 using temail_address = email_address;
-
3886#endif
-
3887 using sgml_email_address = basic_email_address<char>;
-
3888
-
3892 template <class T>
-
3893 class basic_emoticon : public basic_parser<T>
-
3894 {
-
3895 public:
-
3896 basic_emoticon(
-
3897 _In_ const std::shared_ptr<basic_parser<T>>& _emoticon,
-
3898 _In_ const std::shared_ptr<basic_parser<T>>& _apex,
-
3899 _In_ const std::shared_ptr<basic_parser<T>>& _eyes,
-
3900 _In_ const std::shared_ptr<basic_parser<T>>& _nose,
-
3901 _In_ const std::shared_ptr<basic_set<T>>& _mouth,
-
3902 _In_ const std::locale& locale = std::locale()) :
-
3903 basic_parser<T>(locale),
-
3904 emoticon(_emoticon),
-
3905 apex(_apex),
-
3906 eyes(_eyes),
-
3907 nose(_nose),
-
3908 mouth(_mouth)
-
3909 {}
-
3910
-
3911 virtual bool match(
-
3912 _In_reads_or_z_(end) const T* text,
-
3913 _In_ size_t start = 0,
-
3914 _In_ size_t end = (size_t)-1,
-
3915 _In_ int flags = match_default)
-
3916 {
-
3917 assert(text || start >= end);
-
3918
-
3919 if (emoticon && emoticon->match(text, start, end, flags)) {
-
3920 if (apex) apex->invalidate();
-
3921 eyes->invalidate();
-
3922 if (nose) nose->invalidate();
-
3923 mouth->invalidate();
-
3924 interval.start = start;
-
3925 interval.end = emoticon->interval.end;
-
3926 return true;
-
3927 }
-
3928
-
3929 interval.end = start;
+
3664 // "http://" found or defaulted to
+
3665
+
3666 // If "http://" explicit, test for username&password.
+
3667 if (http_scheme->interval &&
+
3668 username->match(text, interval.end, end, flags))
+
3669 {
+
3670 if (m_colon->match(text, username->interval.end, end, flags) &&
+
3671 password->match(text, m_colon->interval.end, end, flags) &&
+
3672 m_at->match(text, password->interval.end, end, flags))
+
3673 {
+
3674 // Username and password
+
3675 interval.end = m_at->interval.end;
+
3676 }
+
3677 else if (m_at->match(text, username->interval.end, end, flags)) {
+
3678 // Username only
+
3679 interval.end = m_at->interval.end;
+
3680 password->invalidate();
+
3681 }
+
3682 else {
+
3683 username->invalidate();
+
3684 password->invalidate();
+
3685 }
+
3686 }
+
3687 else {
+
3688 username->invalidate();
+
3689 password->invalidate();
+
3690 }
+
3691
+
3692 if (ipv4_host->match(text, interval.end, end, flags)) {
+
3693 // Host is IPv4
+
3694 interval.end = ipv4_host->interval.end;
+
3695 ipv6_host->invalidate();
+
3696 dns_host->invalidate();
+
3697 }
+
3698 else if (
+
3699 m_ip_lbracket->match(text, interval.end, end, flags) &&
+
3700 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
+
3701 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
+
3702 {
+
3703 // Host is IPv6
+
3704 interval.end = m_ip_rbracket->interval.end;
+
3705 ipv4_host->invalidate();
+
3706 dns_host->invalidate();
+
3707 }
+
3708 else if (dns_host->match(text, interval.end, end, flags)) {
+
3709 // Host is hostname
+
3710 interval.end = dns_host->interval.end;
+
3711 ipv4_host->invalidate();
+
3712 ipv6_host->invalidate();
+
3713 }
+
3714 else {
+
3715 invalidate();
+
3716 return false;
+
3717 }
+
3718
+
3719 if (m_colon->match(text, interval.end, end, flags) &&
+
3720 port->match(text, m_colon->interval.end, end, flags))
+
3721 {
+
3722 // Port
+
3723 interval.end = port->interval.end;
+
3724 }
+
3725 else
+
3726 port->invalidate();
+
3727
+
3728 if (path->match(text, interval.end, end, flags)) {
+
3729 // Path
+
3730 interval.end = path->interval.end;
+
3731 }
+
3732
+
3733 interval.start = start;
+
3734 return true;
+
3735 }
+
3736
+
3737 virtual void invalidate()
+
3738 {
+
3739 http_scheme->invalidate();
+
3740 ftp_scheme->invalidate();
+
3741 mailto_scheme->invalidate();
+
3742 file_scheme->invalidate();
+
3743 username->invalidate();
+
3744 password->invalidate();
+
3745 ipv4_host->invalidate();
+
3746 ipv6_host->invalidate();
+
3747 dns_host->invalidate();
+
3748 port->invalidate();
+
3749 path->invalidate();
+
3750 basic_parser<T>::invalidate();
+
3751 }
+
3752
+
3753 public:
+
3754 std::shared_ptr<basic_parser<T>> http_scheme;
+
3755 std::shared_ptr<basic_parser<T>> ftp_scheme;
+
3756 std::shared_ptr<basic_parser<T>> mailto_scheme;
+
3757 std::shared_ptr<basic_parser<T>> file_scheme;
+
3758 std::shared_ptr<basic_parser<T>> username;
+
3759 std::shared_ptr<basic_parser<T>> password;
+
3760 std::shared_ptr<basic_parser<T>> ipv4_host;
+
3761 std::shared_ptr<basic_parser<T>> ipv6_host;
+
3762 std::shared_ptr<basic_parser<T>> dns_host;
+
3763 std::shared_ptr<basic_parser<T>> port;
+
3764 std::shared_ptr<basic_parser<T>> path;
+
3765
+
3766 protected:
+
3767 std::shared_ptr<basic_parser<T>> m_colon;
+
3768 std::shared_ptr<basic_parser<T>> m_slash;
+
3769 std::shared_ptr<basic_parser<T>> m_at;
+
3770 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
+
3771 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
+
3772 };
+
3773
+
3774 using url = basic_url<char>;
+
3775 using wurl = basic_url<wchar_t>;
+
3776#ifdef _UNICODE
+
3777 using turl = wurl;
+
3778#else
+
3779 using turl = url;
+
3780#endif
+
3781 using sgml_url = basic_url<char>;
+
3782
+
3786 template <class T>
+
3787 class basic_email_address : public basic_parser<T>
+
3788 {
+
3789 public:
+
3790 basic_email_address(
+
3791 _In_ const std::shared_ptr<basic_parser<T>>& _username,
+
3792 _In_ const std::shared_ptr<basic_parser<T>>& at,
+
3793 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
+
3794 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
+
3795 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
+
3796 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
+
3797 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
+
3798 _In_ const std::locale& locale = std::locale()) :
+
3799 basic_parser<T>(locale),
+
3800 username(_username),
+
3801 m_at(at),
+
3802 m_ip_lbracket(ip_lbracket),
+
3803 m_ip_rbracket(ip_rbracket),
+
3804 ipv4_host(_ipv4_host),
+
3805 ipv6_host(_ipv6_host),
+
3806 dns_host(_dns_host)
+
3807 {}
+
3808
+
3809 virtual bool match(
+
3810 _In_reads_or_z_(end) const T* text,
+
3811 _In_ size_t start = 0,
+
3812 _In_ size_t end = (size_t)-1,
+
3813 _In_ int flags = match_default)
+
3814 {
+
3815 assert(text || start >= end);
+
3816
+
3817 if (username->match(text, start, end, flags) &&
+
3818 m_at->match(text, username->interval.end, end, flags))
+
3819 {
+
3820 // Username@
+
3821 if (m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
+
3822 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
+
3823 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
+
3824 {
+
3825 // Host is IPv4
+
3826 interval.end = m_ip_rbracket->interval.end;
+
3827 ipv6_host->invalidate();
+
3828 dns_host->invalidate();
+
3829 }
+
3830 else if (
+
3831 m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
+
3832 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
+
3833 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
+
3834 {
+
3835 // Host is IPv6
+
3836 interval.end = m_ip_rbracket->interval.end;
+
3837 ipv4_host->invalidate();
+
3838 dns_host->invalidate();
+
3839 }
+
3840 else if (dns_host->match(text, m_at->interval.end, end, flags)) {
+
3841 // Host is hostname
+
3842 interval.end = dns_host->interval.end;
+
3843 ipv4_host->invalidate();
+
3844 ipv6_host->invalidate();
+
3845 }
+
3846 else
+
3847 goto error;
+
3848 interval.start = start;
+
3849 return true;
+
3850 }
+
3851
+
3852 error:
+
3853 username->invalidate();
+
3854 ipv4_host->invalidate();
+
3855 ipv6_host->invalidate();
+
3856 dns_host->invalidate();
+
3857 interval.start = (interval.end = start) + 1;
+
3858 return false;
+
3859 }
+
3860
+
3861 virtual void invalidate()
+
3862 {
+
3863 username->invalidate();
+
3864 ipv4_host->invalidate();
+
3865 ipv6_host->invalidate();
+
3866 dns_host->invalidate();
+
3867 basic_parser<T>::invalidate();
+
3868 }
+
3869
+
3870 public:
+
3871 std::shared_ptr<basic_parser<T>> username;
+
3872 std::shared_ptr<basic_parser<T>> ipv4_host;
+
3873 std::shared_ptr<basic_parser<T>> ipv6_host;
+
3874 std::shared_ptr<basic_parser<T>> dns_host;
+
3875
+
3876 protected:
+
3877 std::shared_ptr<basic_parser<T>> m_at;
+
3878 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
+
3879 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
+
3880 };
+
3881
+
3882 using email_address = basic_email_address<char>;
+
3883 using wemail_address = basic_email_address<wchar_t>;
+
3884#ifdef _UNICODE
+
3885 using temail_address = wemail_address;
+
3886#else
+
3887 using temail_address = email_address;
+
3888#endif
+
3889 using sgml_email_address = basic_email_address<char>;
+
3890
+
3894 template <class T>
+
3895 class basic_emoticon : public basic_parser<T>
+
3896 {
+
3897 public:
+
3898 basic_emoticon(
+
3899 _In_ const std::shared_ptr<basic_parser<T>>& _emoticon,
+
3900 _In_ const std::shared_ptr<basic_parser<T>>& _apex,
+
3901 _In_ const std::shared_ptr<basic_parser<T>>& _eyes,
+
3902 _In_ const std::shared_ptr<basic_parser<T>>& _nose,
+
3903 _In_ const std::shared_ptr<basic_set<T>>& _mouth,
+
3904 _In_ const std::locale& locale = std::locale()) :
+
3905 basic_parser<T>(locale),
+
3906 emoticon(_emoticon),
+
3907 apex(_apex),
+
3908 eyes(_eyes),
+
3909 nose(_nose),
+
3910 mouth(_mouth)
+
3911 {}
+
3912
+
3913 virtual bool match(
+
3914 _In_reads_or_z_(end) const T* text,
+
3915 _In_ size_t start = 0,
+
3916 _In_ size_t end = (size_t)-1,
+
3917 _In_ int flags = match_default)
+
3918 {
+
3919 assert(text || start >= end);
+
3920
+
3921 if (emoticon && emoticon->match(text, start, end, flags)) {
+
3922 if (apex) apex->invalidate();
+
3923 eyes->invalidate();
+
3924 if (nose) nose->invalidate();
+
3925 mouth->invalidate();
+
3926 interval.start = start;
+
3927 interval.end = emoticon->interval.end;
+
3928 return true;
+
3929 }
3930
-
3931 if (apex && apex->match(text, interval.end, end, flags))
-
3932 interval.end = apex->interval.end;
-
3933
-
3934 if (eyes->match(text, interval.end, end, flags)) {
-
3935 if (nose && nose->match(text, eyes->interval.end, end, flags) &&
-
3936 mouth->match(text, nose->interval.end, end, flags))
-
3937 {
-
3938 size_t
-
3939 start_mouth = mouth->interval.start,
-
3940 hit_offset = mouth->hit_offset;
-
3941 // Mouth may repeat :-)))))))
-
3942 for (interval.end = mouth->interval.end; mouth->match(text, interval.end, end, flags) && mouth->hit_offset == hit_offset; interval.end = mouth->interval.end);
-
3943 mouth->interval.start = start_mouth;
-
3944 mouth->interval.end = interval.end;
-
3945 interval.start = start;
-
3946 return true;
-
3947 }
-
3948 if (mouth->match(text, eyes->interval.end, end, flags)) {
-
3949 size_t
-
3950 start_mouth = mouth->interval.start,
-
3951 hit_offset = mouth->hit_offset;
-
3952 // Mouth may repeat :-)))))))
-
3953 for (interval.end = mouth->interval.end; mouth->match(text, interval.end, end, flags) && mouth->hit_offset == hit_offset; interval.end = mouth->interval.end);
-
3954 if (nose) nose->invalidate();
-
3955 mouth->interval.start = start_mouth;
-
3956 mouth->interval.end = interval.end;
-
3957 interval.start = start;
-
3958 return true;
-
3959 }
-
3960 }
-
3961
-
3962 if (emoticon) emoticon->invalidate();
-
3963 if (apex) apex->invalidate();
-
3964 eyes->invalidate();
-
3965 if (nose) nose->invalidate();
-
3966 mouth->invalidate();
-
3967 interval.start = (interval.end = start) + 1;
-
3968 return false;
-
3969 }
-
3970
-
3971 virtual void invalidate()
-
3972 {
-
3973 if (emoticon) emoticon->invalidate();
-
3974 if (apex) apex->invalidate();
-
3975 eyes->invalidate();
-
3976 if (nose) nose->invalidate();
-
3977 mouth->invalidate();
-
3978 basic_parser<T>::invalidate();
-
3979 }
-
3980
-
3981 public:
-
3982 std::shared_ptr<basic_parser<T>> emoticon;
-
3983 std::shared_ptr<basic_parser<T>> apex;
-
3984 std::shared_ptr<basic_parser<T>> eyes;
-
3985 std::shared_ptr<basic_parser<T>> nose;
-
3986 std::shared_ptr<basic_set<T>> mouth;
-
3987 };
-
3988
-
3989 using emoticon = basic_emoticon<char>;
-
3990 using wemoticon = basic_emoticon<wchar_t>;
-
3991#ifdef _UNICODE
-
3992 using temoticon = wemoticon;
-
3993#else
-
3994 using temoticon = emoticon;
-
3995#endif
-
3996 using sgml_emoticon = basic_emoticon<char>;
-
3997
-
4001 ENUM_FLAGS(date_format_t, int) {
-
4002 none = 0,
-
4003 dmy = 0x1,
-
4004 mdy = 0x2,
-
4005 ymd = 0x4,
-
4006 ym = 0x8,
-
4007 my = 0x10,
-
4008 dm = 0x20,
-
4009 md = 0x40,
-
4010 };
-
4011
-
4015 template <class T>
-
4016 class basic_date : public basic_parser<T>
-
4017 {
-
4018 public:
-
4019 basic_date(
-
4020 _In_ int format_mask,
-
4021 _In_ const std::shared_ptr<basic_integer<T>>& _day,
-
4022 _In_ const std::shared_ptr<basic_integer<T>>& _month,
-
4023 _In_ const std::shared_ptr<basic_integer<T>>& _year,
-
4024 _In_ const std::shared_ptr<basic_set<T>>& separator,
-
4025 _In_ const std::shared_ptr<basic_parser<T>>& space,
-
4026 _In_ const std::locale& locale = std::locale()) :
-
4027 basic_parser<T>(locale),
-
4028 format(date_format_t::none),
-
4029 m_format_mask(format_mask),
-
4030 day(_day),
-
4031 month(_month),
-
4032 year(_year),
-
4033 m_separator(separator),
-
4034 m_space(space)
-
4035 {}
-
4036
-
4037 virtual bool match(
-
4038 _In_reads_or_z_(end) const T* text,
-
4039 _In_ size_t start = 0,
-
4040 _In_ size_t end = (size_t)-1,
-
4041 _In_ int flags = match_default)
-
4042 {
-
4043 assert(text || start >= end);
-
4044
-
4045 const int space_match_flags = flags & ~match_multiline; // Spaces in dates must never be broken in new line.
-
4046 if ((m_format_mask & date_format_t::dmy) == date_format_t::dmy) {
-
4047 if (day->match(text, start, end, flags)) {
-
4048 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4049 if (m_separator->match(text, interval.end, end, flags)) {
-
4050 size_t hit_offset = m_separator->hit_offset;
-
4051 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4052 if (month->match(text, interval.end, end, flags)) {
-
4053 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4054 if (m_separator->match(text, interval.end, end, flags) &&
-
4055 m_separator->hit_offset == hit_offset) // Both separators must match.
-
4056 {
-
4057 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4058 if (year->match(text, interval.end, end, flags) &&
-
4059 is_valid(day->value, month->value))
-
4060 {
-
4061 interval.start = start;
-
4062 interval.end = year->interval.end;
-
4063 format = date_format_t::dmy;
-
4064 return true;
-
4065 }
-
4066 }
-
4067 }
-
4068 }
-
4069 }
-
4070 }
-
4071
-
4072 if ((m_format_mask & date_format_t::mdy) == date_format_t::mdy) {
-
4073 if (month->match(text, start, end, flags)) {
-
4074 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4075 if (m_separator->match(text, interval.end, end, flags)) {
-
4076 size_t hit_offset = m_separator->hit_offset;
-
4077 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4078 if (day->match(text, interval.end, end, flags)) {
-
4079 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4080 if (m_separator->match(text, interval.end, end, flags) &&
-
4081 m_separator->hit_offset == hit_offset) // Both separators must match.
-
4082 {
-
4083 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4084 if (year->match(text, interval.end, end, flags) &&
-
4085 is_valid(day->value, month->value))
-
4086 {
-
4087 interval.start = start;
-
4088 interval.end = year->interval.end;
-
4089 format = date_format_t::mdy;
-
4090 return true;
-
4091 }
-
4092 }
-
4093 }
-
4094 }
-
4095 }
-
4096 }
-
4097
-
4098 if ((m_format_mask & date_format_t::ymd) == date_format_t::ymd) {
-
4099 if (year->match(text, start, end, flags)) {
-
4100 for (interval.end = year->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4101 if (m_separator->match(text, interval.end, end, flags)) {
-
4102 size_t hit_offset = m_separator->hit_offset;
-
4103 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4104 if (month->match(text, interval.end, end, flags)) {
-
4105 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4106 if (m_separator->match(text, interval.end, end, flags) &&
-
4107 m_separator->hit_offset == hit_offset) // Both separators must match.
-
4108 {
-
4109 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4110 if (day->match(text, interval.end, end, flags) &&
-
4111 is_valid(day->value, month->value))
-
4112 {
-
4113 interval.start = start;
-
4114 interval.end = day->interval.end;
-
4115 format = date_format_t::ymd;
-
4116 return true;
-
4117 }
-
4118 }
-
4119 }
-
4120 }
-
4121 }
-
4122 }
-
4123
-
4124 if ((m_format_mask & date_format_t::ym) == date_format_t::ym) {
-
4125 if (year->match(text, start, end, flags)) {
-
4126 for (interval.end = year->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4127 if (m_separator->match(text, interval.end, end, flags)) {
-
4128 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4129 if (month->match(text, interval.end, end, flags) &&
-
4130 is_valid((size_t)-1, month->value))
-
4131 {
-
4132 if (day) day->invalidate();
-
4133 interval.start = start;
-
4134 interval.end = month->interval.end;
-
4135 format = date_format_t::ym;
-
4136 return true;
-
4137 }
-
4138 }
-
4139 }
-
4140 }
-
4141
-
4142 if ((m_format_mask & date_format_t::my) == date_format_t::my) {
-
4143 if (month->match(text, start, end, flags)) {
-
4144 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4145 if (m_separator->match(text, interval.end, end, flags)) {
-
4146 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4147 if (year->match(text, interval.end, end, flags) &&
-
4148 is_valid((size_t)-1, month->value))
-
4149 {
-
4150 if (day) day->invalidate();
-
4151 interval.start = start;
-
4152 interval.end = year->interval.end;
-
4153 format = date_format_t::my;
-
4154 return true;
-
4155 }
-
4156 }
-
4157 }
-
4158 }
-
4159
-
4160 if ((m_format_mask & date_format_t::dm) == date_format_t::dm) {
-
4161 if (day->match(text, start, end, flags)) {
-
4162 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4163 if (m_separator->match(text, interval.end, end, flags)) {
-
4164 size_t hit_offset = m_separator->hit_offset;
-
4165 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4166 if (month->match(text, interval.end, end, flags) &&
-
4167 is_valid(day->value, month->value))
-
4168 {
-
4169 if (year) year->invalidate();
-
4170 interval.start = start;
-
4171 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4172 if (m_separator->match(text, interval.end, end, flags) &&
-
4173 m_separator->hit_offset == hit_offset) // Both separators must match.
-
4174 interval.end = m_separator->interval.end;
-
4175 else
-
4176 interval.end = month->interval.end;
-
4177 format = date_format_t::dm;
-
4178 return true;
-
4179 }
-
4180 }
-
4181 }
-
4182 }
-
4183
-
4184 if ((m_format_mask & date_format_t::md) == date_format_t::md) {
-
4185 if (month->match(text, start, end, flags)) {
-
4186 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4187 if (m_separator->match(text, interval.end, end, flags)) {
-
4188 size_t hit_offset = m_separator->hit_offset;
-
4189 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4190 if (day->match(text, interval.end, end, flags) &&
-
4191 is_valid(day->value, month->value))
-
4192 {
-
4193 if (year) year->invalidate();
-
4194 interval.start = start;
-
4195 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
-
4196 if (m_separator->match(text, interval.end, end, flags) &&
-
4197 m_separator->hit_offset == hit_offset) // Both separators must match.
-
4198 interval.end = m_separator->interval.end;
-
4199 else
-
4200 interval.end = day->interval.end;
-
4201 format = date_format_t::md;
-
4202 return true;
-
4203 }
-
4204 }
-
4205 }
-
4206 }
-
4207
-
4208 if (day) day->invalidate();
-
4209 if (month) month->invalidate();
-
4210 if (year) year->invalidate();
-
4211 format = date_format_t::none;
-
4212 interval.start = (interval.end = start) + 1;
-
4213 return false;
-
4214 }
-
4215
-
4216 virtual void invalidate()
-
4217 {
-
4218 if (day) day->invalidate();
-
4219 if (month) month->invalidate();
-
4220 if (year) year->invalidate();
-
4221 format = date_format_t::none;
-
4222 basic_parser<T>::invalidate();
-
4223 }
-
4224
-
4225 protected:
-
4226 static inline bool is_valid(size_t day, size_t month)
-
4227 {
-
4228 if (month == (size_t)-1) {
-
4229 // Default to January. This allows validating day only, as January has all 31 days.
-
4230 month = 1;
-
4231 }
-
4232 if (day == (size_t)-1) {
-
4233 // Default to 1st day in month. This allows validating month only, as each month has 1st day.
-
4234 day = 1;
-
4235 }
-
4236
-
4237 switch (month) {
-
4238 case 1:
-
4239 case 3:
-
4240 case 5:
-
4241 case 7:
-
4242 case 8:
-
4243 case 10:
-
4244 case 12:
-
4245 return 1 <= day && day <= 31;
-
4246 case 2:
-
4247 return 1 <= day && day <= 29;
-
4248 case 4:
-
4249 case 6:
-
4250 case 9:
-
4251 case 11:
-
4252 return 1 <= day && day <= 30;
-
4253 default:
-
4254 return false;
-
4255 }
-
4256 }
-
4257
-
4258 public:
-
4259 date_format_t format;
-
4260 std::shared_ptr<basic_integer<T>> day;
-
4261 std::shared_ptr<basic_integer<T>> month;
-
4262 std::shared_ptr<basic_integer<T>> year;
-
4263
-
4264 protected:
-
4265 int m_format_mask;
-
4266 std::shared_ptr<basic_set<T>> m_separator;
-
4267 std::shared_ptr<basic_parser<T>> m_space;
-
4268 };
-
4269
-
4270 using date = basic_date<char>;
-
4271 using wdate = basic_date<wchar_t>;
-
4272#ifdef _UNICODE
-
4273 using tdate = wdate;
-
4274#else
-
4275 using tdate = date;
-
4276#endif
-
4277 using sgml_date = basic_date<char>;
-
4278
-
4282 template <class T>
-
4283 class basic_time : public basic_parser<T>
-
4284 {
-
4285 public:
-
4286 basic_time(
-
4287 _In_ const std::shared_ptr<basic_integer10<T>>& _hour,
-
4288 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
-
4289 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
-
4290 _In_ const std::shared_ptr<basic_integer10<T>>& _millisecond,
-
4291 _In_ const std::shared_ptr<basic_set<T>>& separator,
-
4292 _In_ const std::shared_ptr<basic_parser<T>>& millisecond_separator,
-
4293 _In_ const std::locale& locale = std::locale()) :
-
4294 basic_parser<T>(locale),
-
4295 hour(_hour),
-
4296 minute(_minute),
-
4297 second(_second),
-
4298 millisecond(_millisecond),
-
4299 m_separator(separator),
-
4300 m_millisecond_separator(millisecond_separator)
-
4301 {}
-
4302
-
4303 virtual bool match(
-
4304 _In_reads_or_z_(end) const T* text,
-
4305 _In_ size_t start = 0,
-
4306 _In_ size_t end = (size_t)-1,
-
4307 _In_ int flags = match_default)
-
4308 {
-
4309 assert(text || start >= end);
-
4310
-
4311 if (hour->match(text, start, end, flags) &&
-
4312 m_separator->match(text, hour->interval.end, end, flags) &&
-
4313 minute->match(text, m_separator->interval.end, end, flags) &&
-
4314 minute->value < 60)
-
4315 {
-
4316 // hh::mm
-
4317 size_t hit_offset = m_separator->hit_offset;
-
4318 if (m_separator->match(text, minute->interval.end, end, flags) &&
-
4319 m_separator->hit_offset == hit_offset && // Both separators must match.
-
4320 second && second->match(text, m_separator->interval.end, end, flags) &&
-
4321 second->value < 60)
-
4322 {
-
4323 // hh::mm:ss
-
4324 if (m_millisecond_separator && m_millisecond_separator->match(text, second->interval.end, end, flags) &&
-
4325 millisecond && millisecond->match(text, m_millisecond_separator->interval.end, end, flags) &&
-
4326 millisecond->value < 1000)
-
4327 {
-
4328 // hh::mm:ss.mmmm
-
4329 interval.end = millisecond->interval.end;
-
4330 }
-
4331 else {
-
4332 if (millisecond) millisecond->invalidate();
-
4333 interval.end = second->interval.end;
-
4334 }
-
4335 }
-
4336 else {
-
4337 if (second) second->invalidate();
-
4338 if (millisecond) millisecond->invalidate();
-
4339 interval.end = minute->interval.end;
-
4340 }
-
4341 interval.start = start;
-
4342 return true;
-
4343 }
-
4344
-
4345 hour->invalidate();
-
4346 minute->invalidate();
-
4347 if (second) second->invalidate();
-
4348 if (millisecond) millisecond->invalidate();
-
4349 interval.start = (interval.end = start) + 1;
-
4350 return false;
-
4351 }
-
4352
-
4353 virtual void invalidate()
-
4354 {
-
4355 hour->invalidate();
-
4356 minute->invalidate();
-
4357 if (second) second->invalidate();
-
4358 if (millisecond) millisecond->invalidate();
-
4359 basic_parser<T>::invalidate();
-
4360 }
-
4361
-
4362 public:
-
4363 std::shared_ptr<basic_integer10<T>> hour;
-
4364 std::shared_ptr<basic_integer10<T>> minute;
-
4365 std::shared_ptr<basic_integer10<T>> second;
-
4366 std::shared_ptr<basic_integer10<T>> millisecond;
-
4367
-
4368 protected:
-
4369 std::shared_ptr<basic_set<T>> m_separator;
-
4370 std::shared_ptr<basic_parser<T>> m_millisecond_separator;
-
4371 };
-
4372
-
4373 using time = basic_time<char>;
-
4374 using wtime = basic_time<wchar_t>;
-
4375#ifdef _UNICODE
-
4376 using ttime = wtime;
-
4377#else
-
4378 using ttime = time;
-
4379#endif
-
4380 using sgml_time = basic_time<char>;
-
4381
-
4385 template <class T>
-
4386 class basic_angle : public basic_parser<T>
-
4387 {
-
4388 public:
-
4389 basic_angle(
-
4390 _In_ const std::shared_ptr<basic_integer10<T>>& _degree,
-
4391 _In_ const std::shared_ptr<basic_parser<T>>& _degree_separator,
-
4392 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
-
4393 _In_ const std::shared_ptr<basic_parser<T>>& _minute_separator,
-
4394 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
-
4395 _In_ const std::shared_ptr<basic_parser<T>>& _second_separator,
-
4396 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
-
4397 _In_ const std::locale& locale = std::locale()) :
-
4398 basic_parser<T>(locale),
-
4399 degree(_degree),
-
4400 degree_separator(_degree_separator),
-
4401 minute(_minute),
-
4402 minute_separator(_minute_separator),
-
4403 second(_second),
-
4404 second_separator(_second_separator),
-
4405 decimal(_decimal)
-
4406 {}
-
4407
-
4408 virtual bool match(
-
4409 _In_reads_or_z_(end) const T* text,
-
4410 _In_ size_t start = 0,
-
4411 _In_ size_t end = (size_t)-1,
-
4412 _In_ int flags = match_default)
-
4413 {
-
4414 assert(text || start >= end);
-
4415
-
4416 interval.end = start;
+
3931 interval.end = start;
+
3932
+
3933 if (apex && apex->match(text, interval.end, end, flags))
+
3934 interval.end = apex->interval.end;
+
3935
+
3936 if (eyes->match(text, interval.end, end, flags)) {
+
3937 if (nose && nose->match(text, eyes->interval.end, end, flags) &&
+
3938 mouth->match(text, nose->interval.end, end, flags))
+
3939 {
+
3940 size_t
+
3941 start_mouth = mouth->interval.start,
+
3942 hit_offset = mouth->hit_offset;
+
3943 // Mouth may repeat :-)))))))
+
3944 for (interval.end = mouth->interval.end; mouth->match(text, interval.end, end, flags) && mouth->hit_offset == hit_offset; interval.end = mouth->interval.end);
+
3945 mouth->interval.start = start_mouth;
+
3946 mouth->interval.end = interval.end;
+
3947 interval.start = start;
+
3948 return true;
+
3949 }
+
3950 if (mouth->match(text, eyes->interval.end, end, flags)) {
+
3951 size_t
+
3952 start_mouth = mouth->interval.start,
+
3953 hit_offset = mouth->hit_offset;
+
3954 // Mouth may repeat :-)))))))
+
3955 for (interval.end = mouth->interval.end; mouth->match(text, interval.end, end, flags) && mouth->hit_offset == hit_offset; interval.end = mouth->interval.end);
+
3956 if (nose) nose->invalidate();
+
3957 mouth->interval.start = start_mouth;
+
3958 mouth->interval.end = interval.end;
+
3959 interval.start = start;
+
3960 return true;
+
3961 }
+
3962 }
+
3963
+
3964 if (emoticon) emoticon->invalidate();
+
3965 if (apex) apex->invalidate();
+
3966 eyes->invalidate();
+
3967 if (nose) nose->invalidate();
+
3968 mouth->invalidate();
+
3969 interval.start = (interval.end = start) + 1;
+
3970 return false;
+
3971 }
+
3972
+
3973 virtual void invalidate()
+
3974 {
+
3975 if (emoticon) emoticon->invalidate();
+
3976 if (apex) apex->invalidate();
+
3977 eyes->invalidate();
+
3978 if (nose) nose->invalidate();
+
3979 mouth->invalidate();
+
3980 basic_parser<T>::invalidate();
+
3981 }
+
3982
+
3983 public:
+
3984 std::shared_ptr<basic_parser<T>> emoticon;
+
3985 std::shared_ptr<basic_parser<T>> apex;
+
3986 std::shared_ptr<basic_parser<T>> eyes;
+
3987 std::shared_ptr<basic_parser<T>> nose;
+
3988 std::shared_ptr<basic_set<T>> mouth;
+
3989 };
+
3990
+
3991 using emoticon = basic_emoticon<char>;
+
3992 using wemoticon = basic_emoticon<wchar_t>;
+
3993#ifdef _UNICODE
+
3994 using temoticon = wemoticon;
+
3995#else
+
3996 using temoticon = emoticon;
+
3997#endif
+
3998 using sgml_emoticon = basic_emoticon<char>;
+
3999
+
4003 ENUM_FLAGS(date_format_t, int) {
+
4004 none = 0,
+
4005 dmy = 0x1,
+
4006 mdy = 0x2,
+
4007 ymd = 0x4,
+
4008 ym = 0x8,
+
4009 my = 0x10,
+
4010 dm = 0x20,
+
4011 md = 0x40,
+
4012 };
+
4013
+
4017 template <class T>
+
4018 class basic_date : public basic_parser<T>
+
4019 {
+
4020 public:
+
4021 basic_date(
+
4022 _In_ int format_mask,
+
4023 _In_ const std::shared_ptr<basic_integer<T>>& _day,
+
4024 _In_ const std::shared_ptr<basic_integer<T>>& _month,
+
4025 _In_ const std::shared_ptr<basic_integer<T>>& _year,
+
4026 _In_ const std::shared_ptr<basic_set<T>>& separator,
+
4027 _In_ const std::shared_ptr<basic_parser<T>>& space,
+
4028 _In_ const std::locale& locale = std::locale()) :
+
4029 basic_parser<T>(locale),
+
4030 format(date_format_t::none),
+
4031 m_format_mask(format_mask),
+
4032 day(_day),
+
4033 month(_month),
+
4034 year(_year),
+
4035 m_separator(separator),
+
4036 m_space(space)
+
4037 {}
+
4038
+
4039 virtual bool match(
+
4040 _In_reads_or_z_(end) const T* text,
+
4041 _In_ size_t start = 0,
+
4042 _In_ size_t end = (size_t)-1,
+
4043 _In_ int flags = match_default)
+
4044 {
+
4045 assert(text || start >= end);
+
4046
+
4047 const int space_match_flags = flags & ~match_multiline; // Spaces in dates must never be broken in new line.
+
4048 if ((m_format_mask & date_format_t::dmy) == date_format_t::dmy) {
+
4049 if (day->match(text, start, end, flags)) {
+
4050 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4051 if (m_separator->match(text, interval.end, end, flags)) {
+
4052 size_t hit_offset = m_separator->hit_offset;
+
4053 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4054 if (month->match(text, interval.end, end, flags)) {
+
4055 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4056 if (m_separator->match(text, interval.end, end, flags) &&
+
4057 m_separator->hit_offset == hit_offset) // Both separators must match.
+
4058 {
+
4059 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4060 if (year->match(text, interval.end, end, flags) &&
+
4061 is_valid(day->value, month->value))
+
4062 {
+
4063 interval.start = start;
+
4064 interval.end = year->interval.end;
+
4065 format = date_format_t::dmy;
+
4066 return true;
+
4067 }
+
4068 }
+
4069 }
+
4070 }
+
4071 }
+
4072 }
+
4073
+
4074 if ((m_format_mask & date_format_t::mdy) == date_format_t::mdy) {
+
4075 if (month->match(text, start, end, flags)) {
+
4076 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4077 if (m_separator->match(text, interval.end, end, flags)) {
+
4078 size_t hit_offset = m_separator->hit_offset;
+
4079 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4080 if (day->match(text, interval.end, end, flags)) {
+
4081 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4082 if (m_separator->match(text, interval.end, end, flags) &&
+
4083 m_separator->hit_offset == hit_offset) // Both separators must match.
+
4084 {
+
4085 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4086 if (year->match(text, interval.end, end, flags) &&
+
4087 is_valid(day->value, month->value))
+
4088 {
+
4089 interval.start = start;
+
4090 interval.end = year->interval.end;
+
4091 format = date_format_t::mdy;
+
4092 return true;
+
4093 }
+
4094 }
+
4095 }
+
4096 }
+
4097 }
+
4098 }
+
4099
+
4100 if ((m_format_mask & date_format_t::ymd) == date_format_t::ymd) {
+
4101 if (year->match(text, start, end, flags)) {
+
4102 for (interval.end = year->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4103 if (m_separator->match(text, interval.end, end, flags)) {
+
4104 size_t hit_offset = m_separator->hit_offset;
+
4105 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4106 if (month->match(text, interval.end, end, flags)) {
+
4107 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4108 if (m_separator->match(text, interval.end, end, flags) &&
+
4109 m_separator->hit_offset == hit_offset) // Both separators must match.
+
4110 {
+
4111 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4112 if (day->match(text, interval.end, end, flags) &&
+
4113 is_valid(day->value, month->value))
+
4114 {
+
4115 interval.start = start;
+
4116 interval.end = day->interval.end;
+
4117 format = date_format_t::ymd;
+
4118 return true;
+
4119 }
+
4120 }
+
4121 }
+
4122 }
+
4123 }
+
4124 }
+
4125
+
4126 if ((m_format_mask & date_format_t::ym) == date_format_t::ym) {
+
4127 if (year->match(text, start, end, flags)) {
+
4128 for (interval.end = year->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4129 if (m_separator->match(text, interval.end, end, flags)) {
+
4130 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4131 if (month->match(text, interval.end, end, flags) &&
+
4132 is_valid((size_t)-1, month->value))
+
4133 {
+
4134 if (day) day->invalidate();
+
4135 interval.start = start;
+
4136 interval.end = month->interval.end;
+
4137 format = date_format_t::ym;
+
4138 return true;
+
4139 }
+
4140 }
+
4141 }
+
4142 }
+
4143
+
4144 if ((m_format_mask & date_format_t::my) == date_format_t::my) {
+
4145 if (month->match(text, start, end, flags)) {
+
4146 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4147 if (m_separator->match(text, interval.end, end, flags)) {
+
4148 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4149 if (year->match(text, interval.end, end, flags) &&
+
4150 is_valid((size_t)-1, month->value))
+
4151 {
+
4152 if (day) day->invalidate();
+
4153 interval.start = start;
+
4154 interval.end = year->interval.end;
+
4155 format = date_format_t::my;
+
4156 return true;
+
4157 }
+
4158 }
+
4159 }
+
4160 }
+
4161
+
4162 if ((m_format_mask & date_format_t::dm) == date_format_t::dm) {
+
4163 if (day->match(text, start, end, flags)) {
+
4164 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4165 if (m_separator->match(text, interval.end, end, flags)) {
+
4166 size_t hit_offset = m_separator->hit_offset;
+
4167 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4168 if (month->match(text, interval.end, end, flags) &&
+
4169 is_valid(day->value, month->value))
+
4170 {
+
4171 if (year) year->invalidate();
+
4172 interval.start = start;
+
4173 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4174 if (m_separator->match(text, interval.end, end, flags) &&
+
4175 m_separator->hit_offset == hit_offset) // Both separators must match.
+
4176 interval.end = m_separator->interval.end;
+
4177 else
+
4178 interval.end = month->interval.end;
+
4179 format = date_format_t::dm;
+
4180 return true;
+
4181 }
+
4182 }
+
4183 }
+
4184 }
+
4185
+
4186 if ((m_format_mask & date_format_t::md) == date_format_t::md) {
+
4187 if (month->match(text, start, end, flags)) {
+
4188 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4189 if (m_separator->match(text, interval.end, end, flags)) {
+
4190 size_t hit_offset = m_separator->hit_offset;
+
4191 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4192 if (day->match(text, interval.end, end, flags) &&
+
4193 is_valid(day->value, month->value))
+
4194 {
+
4195 if (year) year->invalidate();
+
4196 interval.start = start;
+
4197 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
+
4198 if (m_separator->match(text, interval.end, end, flags) &&
+
4199 m_separator->hit_offset == hit_offset) // Both separators must match.
+
4200 interval.end = m_separator->interval.end;
+
4201 else
+
4202 interval.end = day->interval.end;
+
4203 format = date_format_t::md;
+
4204 return true;
+
4205 }
+
4206 }
+
4207 }
+
4208 }
+
4209
+
4210 if (day) day->invalidate();
+
4211 if (month) month->invalidate();
+
4212 if (year) year->invalidate();
+
4213 format = date_format_t::none;
+
4214 interval.start = (interval.end = start) + 1;
+
4215 return false;
+
4216 }
+
4217
+
4218 virtual void invalidate()
+
4219 {
+
4220 if (day) day->invalidate();
+
4221 if (month) month->invalidate();
+
4222 if (year) year->invalidate();
+
4223 format = date_format_t::none;
+
4224 basic_parser<T>::invalidate();
+
4225 }
+
4226
+
4227 protected:
+
4228 static inline bool is_valid(size_t day, size_t month)
+
4229 {
+
4230 if (month == (size_t)-1) {
+
4231 // Default to January. This allows validating day only, as January has all 31 days.
+
4232 month = 1;
+
4233 }
+
4234 if (day == (size_t)-1) {
+
4235 // Default to 1st day in month. This allows validating month only, as each month has 1st day.
+
4236 day = 1;
+
4237 }
+
4238
+
4239 switch (month) {
+
4240 case 1:
+
4241 case 3:
+
4242 case 5:
+
4243 case 7:
+
4244 case 8:
+
4245 case 10:
+
4246 case 12:
+
4247 return 1 <= day && day <= 31;
+
4248 case 2:
+
4249 return 1 <= day && day <= 29;
+
4250 case 4:
+
4251 case 6:
+
4252 case 9:
+
4253 case 11:
+
4254 return 1 <= day && day <= 30;
+
4255 default:
+
4256 return false;
+
4257 }
+
4258 }
+
4259
+
4260 public:
+
4261 date_format_t format;
+
4262 std::shared_ptr<basic_integer<T>> day;
+
4263 std::shared_ptr<basic_integer<T>> month;
+
4264 std::shared_ptr<basic_integer<T>> year;
+
4265
+
4266 protected:
+
4267 int m_format_mask;
+
4268 std::shared_ptr<basic_set<T>> m_separator;
+
4269 std::shared_ptr<basic_parser<T>> m_space;
+
4270 };
+
4271
+
4272 using date = basic_date<char>;
+
4273 using wdate = basic_date<wchar_t>;
+
4274#ifdef _UNICODE
+
4275 using tdate = wdate;
+
4276#else
+
4277 using tdate = date;
+
4278#endif
+
4279 using sgml_date = basic_date<char>;
+
4280
+
4284 template <class T>
+
4285 class basic_time : public basic_parser<T>
+
4286 {
+
4287 public:
+
4288 basic_time(
+
4289 _In_ const std::shared_ptr<basic_integer10<T>>& _hour,
+
4290 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
+
4291 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
+
4292 _In_ const std::shared_ptr<basic_integer10<T>>& _millisecond,
+
4293 _In_ const std::shared_ptr<basic_set<T>>& separator,
+
4294 _In_ const std::shared_ptr<basic_parser<T>>& millisecond_separator,
+
4295 _In_ const std::locale& locale = std::locale()) :
+
4296 basic_parser<T>(locale),
+
4297 hour(_hour),
+
4298 minute(_minute),
+
4299 second(_second),
+
4300 millisecond(_millisecond),
+
4301 m_separator(separator),
+
4302 m_millisecond_separator(millisecond_separator)
+
4303 {}
+
4304
+
4305 virtual bool match(
+
4306 _In_reads_or_z_(end) const T* text,
+
4307 _In_ size_t start = 0,
+
4308 _In_ size_t end = (size_t)-1,
+
4309 _In_ int flags = match_default)
+
4310 {
+
4311 assert(text || start >= end);
+
4312
+
4313 if (hour->match(text, start, end, flags) &&
+
4314 m_separator->match(text, hour->interval.end, end, flags) &&
+
4315 minute->match(text, m_separator->interval.end, end, flags) &&
+
4316 minute->value < 60)
+
4317 {
+
4318 // hh::mm
+
4319 size_t hit_offset = m_separator->hit_offset;
+
4320 if (m_separator->match(text, minute->interval.end, end, flags) &&
+
4321 m_separator->hit_offset == hit_offset && // Both separators must match.
+
4322 second && second->match(text, m_separator->interval.end, end, flags) &&
+
4323 second->value < 60)
+
4324 {
+
4325 // hh::mm:ss
+
4326 if (m_millisecond_separator && m_millisecond_separator->match(text, second->interval.end, end, flags) &&
+
4327 millisecond && millisecond->match(text, m_millisecond_separator->interval.end, end, flags) &&
+
4328 millisecond->value < 1000)
+
4329 {
+
4330 // hh::mm:ss.mmmm
+
4331 interval.end = millisecond->interval.end;
+
4332 }
+
4333 else {
+
4334 if (millisecond) millisecond->invalidate();
+
4335 interval.end = second->interval.end;
+
4336 }
+
4337 }
+
4338 else {
+
4339 if (second) second->invalidate();
+
4340 if (millisecond) millisecond->invalidate();
+
4341 interval.end = minute->interval.end;
+
4342 }
+
4343 interval.start = start;
+
4344 return true;
+
4345 }
+
4346
+
4347 hour->invalidate();
+
4348 minute->invalidate();
+
4349 if (second) second->invalidate();
+
4350 if (millisecond) millisecond->invalidate();
+
4351 interval.start = (interval.end = start) + 1;
+
4352 return false;
+
4353 }
+
4354
+
4355 virtual void invalidate()
+
4356 {
+
4357 hour->invalidate();
+
4358 minute->invalidate();
+
4359 if (second) second->invalidate();
+
4360 if (millisecond) millisecond->invalidate();
+
4361 basic_parser<T>::invalidate();
+
4362 }
+
4363
+
4364 public:
+
4365 std::shared_ptr<basic_integer10<T>> hour;
+
4366 std::shared_ptr<basic_integer10<T>> minute;
+
4367 std::shared_ptr<basic_integer10<T>> second;
+
4368 std::shared_ptr<basic_integer10<T>> millisecond;
+
4369
+
4370 protected:
+
4371 std::shared_ptr<basic_set<T>> m_separator;
+
4372 std::shared_ptr<basic_parser<T>> m_millisecond_separator;
+
4373 };
+
4374
+
4375 using time = basic_time<char>;
+
4376 using wtime = basic_time<wchar_t>;
+
4377#ifdef _UNICODE
+
4378 using ttime = wtime;
+
4379#else
+
4380 using ttime = time;
+
4381#endif
+
4382 using sgml_time = basic_time<char>;
+
4383
+
4387 template <class T>
+
4388 class basic_angle : public basic_parser<T>
+
4389 {
+
4390 public:
+
4391 basic_angle(
+
4392 _In_ const std::shared_ptr<basic_integer10<T>>& _degree,
+
4393 _In_ const std::shared_ptr<basic_parser<T>>& _degree_separator,
+
4394 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
+
4395 _In_ const std::shared_ptr<basic_parser<T>>& _minute_separator,
+
4396 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
+
4397 _In_ const std::shared_ptr<basic_parser<T>>& _second_separator,
+
4398 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
+
4399 _In_ const std::locale& locale = std::locale()) :
+
4400 basic_parser<T>(locale),
+
4401 degree(_degree),
+
4402 degree_separator(_degree_separator),
+
4403 minute(_minute),
+
4404 minute_separator(_minute_separator),
+
4405 second(_second),
+
4406 second_separator(_second_separator),
+
4407 decimal(_decimal)
+
4408 {}
+
4409
+
4410 virtual bool match(
+
4411 _In_reads_or_z_(end) const T* text,
+
4412 _In_ size_t start = 0,
+
4413 _In_ size_t end = (size_t)-1,
+
4414 _In_ int flags = match_default)
+
4415 {
+
4416 assert(text || start >= end);
4417
-
4418 if (degree->match(text, interval.end, end, flags) &&
-
4419 degree_separator->match(text, degree->interval.end, end, flags))
-
4420 {
-
4421 // Degrees
-
4422 interval.end = degree_separator->interval.end;
-
4423 }
-
4424 else {
-
4425 degree->invalidate();
-
4426 degree_separator->invalidate();
-
4427 }
-
4428
-
4429 if (minute->match(text, interval.end, end, flags) &&
-
4430 minute->value < 60 &&
-
4431 minute_separator->match(text, minute->interval.end, end, flags))
-
4432 {
-
4433 // Minutes
-
4434 interval.end = minute_separator->interval.end;
-
4435 }
-
4436 else {
-
4437 minute->invalidate();
-
4438 minute_separator->invalidate();
-
4439 }
-
4440
-
4441 if (second && second->match(text, interval.end, end, flags) &&
-
4442 second->value < 60)
-
4443 {
-
4444 // Seconds
-
4445 interval.end = second->interval.end;
-
4446 if (second_separator && second_separator->match(text, interval.end, end, flags))
-
4447 interval.end = second_separator->interval.end;
-
4448 else
-
4449 if (second_separator) second_separator->invalidate();
-
4450 }
-
4451 else {
-
4452 if (second) second->invalidate();
-
4453 if (second_separator) second_separator->invalidate();
-
4454 }
-
4455
-
4456 if (degree->interval.start < degree->interval.end ||
-
4457 minute->interval.start < minute->interval.end ||
-
4458 second && second->interval.start < second->interval.end)
-
4459 {
-
4460 if (decimal && decimal->match(text, interval.end, end, flags)) {
-
4461 // Decimals
-
4462 interval.end = decimal->interval.end;
-
4463 }
-
4464 else if (decimal)
-
4465 decimal->invalidate();
-
4466 interval.start = start;
-
4467 return true;
-
4468 }
-
4469 if (decimal) decimal->invalidate();
-
4470 interval.start = (interval.end = start) + 1;
-
4471 return false;
-
4472 }
-
4473
-
4474 virtual void invalidate()
-
4475 {
-
4476 degree->invalidate();
-
4477 degree_separator->invalidate();
-
4478 minute->invalidate();
-
4479 minute_separator->invalidate();
-
4480 if (second) second->invalidate();
-
4481 if (second_separator) second_separator->invalidate();
-
4482 if (decimal) decimal->invalidate();
-
4483 basic_parser<T>::invalidate();
-
4484 }
-
4485
-
4486 public:
-
4487 std::shared_ptr<basic_integer10<T>> degree;
-
4488 std::shared_ptr<basic_parser<T>> degree_separator;
-
4489 std::shared_ptr<basic_integer10<T>> minute;
-
4490 std::shared_ptr<basic_parser<T>> minute_separator;
-
4491 std::shared_ptr<basic_integer10<T>> second;
-
4492 std::shared_ptr<basic_parser<T>> second_separator;
-
4493 std::shared_ptr<basic_parser<T>> decimal;
-
4494 };
-
4495
-
4496 using angle = basic_angle<char>;
-
4497 using wangle = basic_angle<wchar_t>;
-
4498#ifdef _UNICODE
-
4499 using RRegElKot = wangle;
-
4500#else
-
4501 using RRegElKot = angle;
-
4502#endif
-
4503 using sgml_angle = basic_angle<char>;
-
4504
-
4508 template <class T>
-
4509 class basic_phone_number : public basic_parser<T>
-
4510 {
-
4511 public:
-
4512 basic_phone_number(
-
4513 _In_ const std::shared_ptr<basic_parser<T>>& digit,
-
4514 _In_ const std::shared_ptr<basic_parser<T>>& plus_sign,
-
4515 _In_ const std::shared_ptr<basic_set<T>>& lparenthesis,
-
4516 _In_ const std::shared_ptr<basic_set<T>>& rparenthesis,
-
4517 _In_ const std::shared_ptr<basic_parser<T>>& separator,
-
4518 _In_ const std::shared_ptr<basic_parser<T>>& space,
-
4519 _In_ const std::locale& locale = std::locale()) :
-
4520 basic_parser<T>(locale),
-
4521 m_digit(digit),
-
4522 m_plus_sign(plus_sign),
-
4523 m_lparenthesis(lparenthesis),
-
4524 m_rparenthesis(rparenthesis),
-
4525 m_separator(separator),
-
4526 m_space(space)
-
4527 {}
-
4528
-
4529 virtual bool match(
-
4530 _In_reads_or_z_(end) const T* text,
-
4531 _In_ size_t start = 0,
-
4532 _In_ size_t end = (size_t)-1,
-
4533 _In_ int flags = match_default)
-
4534 {
-
4535 assert(text || start >= end);
-
4536
-
4537 size_t safe_digit_end = start, safe_value_size = 0;
-
4538 bool has_digits = false, after_digit = false, in_parentheses = false, after_parentheses = false;
-
4539 const int space_match_flags = flags & ~match_multiline; // Spaces in phone numbers must never be broken in new line.
-
4540
-
4541 interval.end = start;
-
4542 value.clear();
-
4543 m_lparenthesis->invalidate();
-
4544 m_rparenthesis->invalidate();
-
4545
-
4546 if (m_plus_sign && m_plus_sign->match(text, interval.end, end, flags)) {
-
4547 value.append(text + m_plus_sign->interval.start, text + m_plus_sign->interval.end);
-
4548 safe_value_size = value.size();
-
4549 interval.end = m_plus_sign->interval.end;
-
4550 }
-
4551
-
4552 for (;;) {
-
4553 assert(text || interval.end >= end);
-
4554 if (interval.end >= end || !text[interval.end])
-
4555 break;
-
4556 if (m_digit->match(text, interval.end, end, flags)) {
-
4557 // Digit
-
4558 value.append(text + m_digit->interval.start, text + m_digit->interval.end);
-
4559 interval.end = m_digit->interval.end;
-
4560 if (!in_parentheses) {
-
4561 safe_digit_end = interval.end;
-
4562 safe_value_size = value.size();
-
4563 has_digits = true;
-
4564 }
-
4565 after_digit = true;
-
4566 after_parentheses = false;
-
4567 }
-
4568 else if (
-
4569 m_lparenthesis && !m_lparenthesis->interval && // No left parenthesis yet
-
4570 m_rparenthesis && !m_rparenthesis->interval && // Right parenthesis after left
-
4571 m_lparenthesis->match(text, interval.end, end, flags))
-
4572 {
-
4573 // Left parenthesis
-
4574 value.append(text + m_lparenthesis->interval.start, m_lparenthesis->interval.size());
-
4575 interval.end = m_lparenthesis->interval.end;
-
4576 in_parentheses = true;
-
4577 after_digit = false;
-
4578 after_parentheses = false;
-
4579 }
-
4580 else if (
-
4581 in_parentheses && // After left parenthesis
-
4582 m_rparenthesis && !m_rparenthesis->interval && // No right parenthesis yet
-
4583 m_rparenthesis->match(text, interval.end, end, flags) &&
-
4584 m_lparenthesis->hit_offset == m_rparenthesis->hit_offset) // Left and right parentheses must match
-
4585 {
-
4586 // Right parenthesis
-
4587 value.append(text + m_rparenthesis->interval.start, text + m_rparenthesis->interval.end);
-
4588 interval.end = m_rparenthesis->interval.end;
-
4589 safe_digit_end = interval.end;
-
4590 safe_value_size = value.size();
-
4591 in_parentheses = false;
-
4592 after_digit = false;
-
4593 after_parentheses = true;
-
4594 }
-
4595 else if (
-
4596 after_digit &&
-
4597 !in_parentheses && // No separators inside parentheses
-
4598 !after_parentheses && // No separators following right parenthesis
-
4599 m_separator && m_separator->match(text, interval.end, end, flags))
-
4600 {
-
4601 // Separator
-
4602 interval.end = m_separator->interval.end;
-
4603 after_digit = false;
-
4604 after_parentheses = false;
-
4605 }
-
4606 else if (
-
4607 (after_digit || after_parentheses) &&
-
4608 m_space && m_space->match(text, interval.end, end, space_match_flags))
-
4609 {
-
4610 // Space
-
4611 interval.end = m_space->interval.end;
-
4612 after_digit = false;
-
4613 after_parentheses = false;
-
4614 }
-
4615 else
-
4616 break;
-
4617 }
-
4618 if (has_digits) {
-
4619 value.erase(safe_value_size);
-
4620 interval.start = start;
-
4621 interval.end = safe_digit_end;
-
4622 return true;
-
4623 }
-
4624 value.clear();
-
4625 interval.start = (interval.end = start) + 1;
-
4626 return false;
-
4627 }
-
4628
-
4629 virtual void invalidate()
-
4630 {
-
4631 value.clear();
-
4632 basic_parser<T>::invalidate();
-
4633 }
-
4634
-
4635 public:
-
4636 std::basic_string<T> value;
-
4637
-
4638 protected:
-
4639 std::shared_ptr<basic_parser<T>> m_digit;
-
4640 std::shared_ptr<basic_parser<T>> m_plus_sign;
-
4641 std::shared_ptr<basic_set<T>> m_lparenthesis;
-
4642 std::shared_ptr<basic_set<T>> m_rparenthesis;
-
4643 std::shared_ptr<basic_parser<T>> m_separator;
-
4644 std::shared_ptr<basic_parser<T>> m_space;
-
4645 };
-
4646
-
4647 using phone_number = basic_phone_number<char>;
-
4648 using wphone_number = basic_phone_number<wchar_t>;
-
4649#ifdef _UNICODE
-
4650 using tphone_number = wphone_number;
-
4651#else
-
4652 using tphone_number = phone_number;
-
4653#endif
-
4654 using sgml_phone_number = basic_phone_number<char>;
-
4655
-
4659 template <class T>
-
4660 class basic_chemical_formula : public basic_parser<T>
-
4661 {
-
4662 public:
-
4663 basic_chemical_formula(
-
4664 _In_ const std::shared_ptr<basic_parser<T>>& element,
-
4665 _In_ const std::shared_ptr<basic_parser<T>>& digit,
-
4666 _In_ const std::shared_ptr<basic_parser<T>>& sign,
-
4667 _In_ const std::locale& locale = std::locale()) :
-
4668 basic_parser<T>(locale),
-
4669 m_element(element),
-
4670 m_digit(digit),
-
4671 m_sign(sign),
-
4672 has_digits(false),
-
4673 has_charge(false)
-
4674 {}
-
4675
-
4676 virtual bool match(
-
4677 _In_reads_or_z_(end) const T* text,
-
4678 _In_ size_t start = 0,
-
4679 _In_ size_t end = (size_t)-1,
-
4680 _In_ int flags = match_default)
-
4681 {
-
4682 assert(text || start >= end);
-
4683
-
4684 has_digits = false;
-
4685 has_charge = false;
-
4686 interval.end = start;
-
4687
-
4688 const int element_match_flags = flags & ~match_case_insensitive; // Chemical elements are always case-sensitive.
-
4689 for (;;) {
-
4690 if (m_element->match(text, interval.end, end, element_match_flags)) {
-
4691 interval.end = m_element->interval.end;
-
4692 while (m_digit->match(text, interval.end, end, flags)) {
-
4693 interval.end = m_digit->interval.end;
-
4694 has_digits = true;
-
4695 }
-
4696 }
-
4697 else if (start < interval.end) {
-
4698 if (m_sign->match(text, interval.end, end, flags)) {
-
4699 interval.end = m_sign->interval.end;
-
4700 has_charge = true;
-
4701 }
-
4702 interval.start = start;
-
4703 return true;
-
4704 }
-
4705 else {
-
4706 interval.start = (interval.end = start) + 1;
-
4707 return false;
-
4708 }
-
4709 }
-
4710 }
-
4711
-
4712 virtual void invalidate()
-
4713 {
-
4714 has_digits = false;
-
4715 has_charge = false;
-
4716 basic_parser<T>::invalidate();
-
4717 }
-
4718
-
4719 public:
-
4720 bool has_digits;
-
4721 bool has_charge;
-
4722
-
4723 protected:
-
4724 std::shared_ptr<basic_parser<T>> m_element;
-
4725 std::shared_ptr<basic_parser<T>> m_digit;
-
4726 std::shared_ptr<basic_parser<T>> m_sign;
-
4727 };
-
4728
-
4729 using chemical_formula = basic_chemical_formula<char>;
-
4730 using wchemical_formula = basic_chemical_formula<wchar_t>;
-
4731#ifdef _UNICODE
-
4732 using tchemical_formula = wchemical_formula;
-
4733#else
-
4734 using tchemical_formula = chemical_formula;
-
4735#endif
-
4736 using sgml_chemical_formula = basic_chemical_formula<char>;
-
4737
-
4741 class http_line_break : public parser
-
4742 {
-
4743 public:
-
4744 virtual bool match(
-
4745 _In_reads_or_z_(end) const char* text,
-
4746 _In_ size_t start = 0,
-
4747 _In_ size_t end = (size_t)-1,
-
4748 _In_ int flags = match_default)
-
4749 {
-
4750 assert(text || start >= end);
-
4751 interval.end = start;
-
4752
-
4753 assert(text || interval.end >= end);
-
4754 if (interval.end < end && text[interval.end]) {
-
4755 if (text[interval.end] == '\r') {
-
4756 interval.end++;
-
4757 if (interval.end < end && text[interval.end] == '\n') {
-
4758 interval.start = start;
-
4759 interval.end++;
-
4760 return true;
-
4761 }
-
4762 }
-
4763 else if (text[interval.end] == '\n') {
-
4764 interval.start = start;
-
4765 interval.end++;
-
4766 return true;
-
4767 }
-
4768 }
-
4769 interval.start = (interval.end = start) + 1;
-
4770 return false;
-
4771 }
-
4772 };
-
4773
-
4777 class http_space : public parser
-
4778 {
-
4779 public:
-
4780 virtual bool match(
-
4781 _In_reads_or_z_(end) const char* text,
-
4782 _In_ size_t start = 0,
-
4783 _In_ size_t end = (size_t)-1,
-
4784 _In_ int flags = match_default)
-
4785 {
-
4786 assert(text || start >= end);
-
4787 interval.end = start;
-
4788 if (m_line_break.match(text, interval.end, end, flags)) {
-
4789 interval.end = m_line_break.interval.end;
-
4790 if (interval.end < end && text[interval.end] && isspace(text[interval.end])) {
-
4791 interval.start = start;
-
4792 interval.end++;
-
4793 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
-
4794 return true;
-
4795 }
-
4796 }
-
4797 else if (interval.end < end && text[interval.end] && isspace(text[interval.end])) {
-
4798 interval.start = start;
-
4799 interval.end++;
-
4800 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
-
4801 return true;
-
4802 }
-
4803 interval.start = (interval.end = start) + 1;
-
4804 return false;
-
4805 }
-
4806
-
4807 protected:
-
4808 http_line_break m_line_break;
-
4809 };
-
4810
-
4814 class http_text_char : public parser
-
4815 {
-
4816 public:
-
4817 virtual bool match(
-
4818 _In_reads_or_z_(end) const char* text,
-
4819 _In_ size_t start = 0,
-
4820 _In_ size_t end = (size_t)-1,
-
4821 _In_ int flags = match_default)
-
4822 {
-
4823 assert(text || start >= end);
-
4824 interval.end = start;
-
4825
-
4826 assert(text || interval.end >= end);
-
4827 if (m_space.match(text, interval.end, end, flags)) {
-
4828 interval.start = start;
-
4829 interval.end = m_space.interval.end;
-
4830 return true;
-
4831 }
-
4832 else if (interval.end < end && text[interval.end] && text[interval.end] >= 0x20) {
-
4833 interval.start = start;
-
4834 interval.end++;
-
4835 return true;
-
4836 }
-
4837 interval.start = (interval.end = start) + 1;
-
4838 return false;
-
4839 }
-
4840
-
4841 protected:
-
4842 http_space m_space;
-
4843 };
-
4844
-
4848 class http_token : public parser
-
4849 {
-
4850 public:
-
4851 virtual bool match(
-
4852 _In_reads_or_z_(end) const char* text,
-
4853 _In_ size_t start = 0,
-
4854 _In_ size_t end = (size_t)-1,
-
4855 _In_ int flags = match_default)
-
4856 {
-
4857 assert(text || start >= end);
-
4858 interval.end = start;
-
4859 for (;;) {
-
4860 if (interval.end < end && text[interval.end]) {
-
4861 if ((unsigned int)text[interval.end] < 0x20 ||
-
4862 (unsigned int)text[interval.end] == 0x7f ||
-
4863 text[interval.end] == '(' ||
-
4864 text[interval.end] == ')' ||
-
4865 text[interval.end] == '<' ||
-
4866 text[interval.end] == '>' ||
-
4867 text[interval.end] == '@' ||
-
4868 text[interval.end] == ',' ||
-
4869 text[interval.end] == ';' ||
-
4870 text[interval.end] == ':' ||
-
4871 text[interval.end] == '\\' ||
-
4872 text[interval.end] == '\"' ||
-
4873 text[interval.end] == '/' ||
-
4874 text[interval.end] == '[' ||
-
4875 text[interval.end] == ']' ||
-
4876 text[interval.end] == '?' ||
-
4877 text[interval.end] == '=' ||
-
4878 text[interval.end] == '{' ||
-
4879 text[interval.end] == '}' ||
-
4880 isspace(text[interval.end]))
-
4881 break;
-
4882 else
-
4883 interval.end++;
-
4884 }
-
4885 else
-
4886 break;
-
4887 }
-
4888 if (start < interval.end) {
-
4889 interval.start = start;
-
4890 return true;
-
4891 }
-
4892 else {
-
4893 interval.start = (interval.end = start) + 1;
-
4894 return false;
-
4895 }
-
4896 }
-
4897 };
-
4898
-
4902 class http_quoted_string : public parser
-
4903 {
-
4904 public:
-
4905 virtual bool match(
-
4906 _In_reads_or_z_(end) const char* text,
-
4907 _In_ size_t start = 0,
-
4908 _In_ size_t end = (size_t)-1,
-
4909 _In_ int flags = match_default)
-
4910 {
-
4911 assert(text || start >= end);
-
4912 interval.end = start;
-
4913 if (interval.end < end && text[interval.end] != '"')
-
4914 goto error;
-
4915 interval.end++;
-
4916 content.start = interval.end;
-
4917 for (;;) {
-
4918 assert(text || interval.end >= end);
-
4919 if (interval.end < end && text[interval.end]) {
-
4920 if (text[interval.end] == '"') {
-
4921 content.end = interval.end;
-
4922 interval.end++;
-
4923 break;
-
4924 }
-
4925 else if (text[interval.end] == '\\') {
-
4926 interval.end++;
-
4927 if (interval.end < end && text[interval.end]) {
-
4928 interval.end++;
-
4929 }
-
4930 else
-
4931 goto error;
-
4932 }
-
4933 else if (m_chr.match(text, interval.end, end, flags))
-
4934 interval.end++;
-
4935 else
-
4936 goto error;
-
4937 }
-
4938 else
-
4939 goto error;
-
4940 }
-
4941 interval.start = start;
-
4942 return true;
-
4943
-
4944 error:
-
4945 content.start = 1;
-
4946 content.end = 0;
-
4947 interval.start = (interval.end = start) + 1;
-
4948 return false;
-
4949 }
-
4950
-
4951 virtual void invalidate()
-
4952 {
-
4953 content.start = 1;
-
4954 content.end = 0;
-
4955 parser::invalidate();
-
4956 }
-
4957
-
4958 public:
-
4959 stdex::interval<size_t> content;
-
4960
-
4961 protected:
-
4962 http_text_char m_chr;
-
4963 };
-
4964
-
4968 class http_value : public parser
-
4969 {
-
4970 public:
-
4971 virtual bool match(
-
4972 _In_reads_or_z_(end) const char* text,
-
4973 _In_ size_t start = 0,
-
4974 _In_ size_t end = (size_t)-1,
-
4975 _In_ int flags = match_default)
-
4976 {
-
4977 assert(text || start >= end);
-
4978 interval.end = start;
-
4979 if (string.match(text, interval.end, end, flags)) {
-
4980 token.invalidate();
-
4981 interval.end = string.interval.end;
-
4982 interval.start = start;
-
4983 return true;
-
4984 }
-
4985 else if (token.match(text, interval.end, end, flags)) {
-
4986 string.invalidate();
-
4987 interval.end = token.interval.end;
-
4988 interval.start = start;
-
4989 return true;
-
4990 }
-
4991 else {
-
4992 interval.start = (interval.end = start) + 1;
-
4993 return false;
-
4994 }
-
4995 }
-
4996
-
4997 virtual void invalidate()
-
4998 {
-
4999 string.invalidate();
-
5000 token.invalidate();
-
5001 parser::invalidate();
-
5002 }
-
5003
-
5004 public:
-
5005 http_quoted_string string;
-
5006 http_token token;
-
5007 };
-
5008
-
5012 class http_parameter : public parser
-
5013 {
-
5014 public:
-
5015 virtual bool match(
-
5016 _In_reads_or_z_(end) const char* text,
-
5017 _In_ size_t start = 0,
-
5018 _In_ size_t end = (size_t)-1,
-
5019 _In_ int flags = match_default)
-
5020 {
-
5021 assert(text || start >= end);
-
5022 interval.end = start;
-
5023 if (name.match(text, interval.end, end, flags))
-
5024 interval.end = name.interval.end;
-
5025 else
-
5026 goto error;
-
5027 while (m_space.match(text, interval.end, end, flags))
-
5028 interval.end = m_space.interval.end;
-
5029 assert(text || interval.end >= end);
-
5030 if (interval.end < end && text[interval.end] == '=')
-
5031 interval.end++;
-
5032 else
-
5033 while (m_space.match(text, interval.end, end, flags))
-
5034 interval.end = m_space.interval.end;
-
5035 if (value.match(text, interval.end, end, flags))
-
5036 interval.end = value.interval.end;
-
5037 else
-
5038 goto error;
-
5039 interval.start = start;
-
5040 return true;
-
5041
-
5042 error:
-
5043 name.invalidate();
-
5044 value.invalidate();
-
5045 interval.start = (interval.end = start) + 1;
-
5046 return false;
-
5047 }
-
5048
-
5049 virtual void invalidate()
-
5050 {
-
5051 name.invalidate();
-
5052 value.invalidate();
-
5053 parser::invalidate();
-
5054 }
-
5055
-
5056 public:
-
5057 http_token name;
-
5058 http_value value;
-
5059
-
5060 protected:
-
5061 http_space m_space;
-
5062 };
-
5063
-
5067 class http_any_type : public parser
-
5068 {
-
5069 public:
-
5070 virtual bool match(
-
5071 _In_reads_or_z_(end) const char* text,
-
5072 _In_ size_t start = 0,
-
5073 _In_ size_t end = (size_t)-1,
-
5074 _In_ int flags = match_default)
-
5075 {
-
5076 assert(text || start >= end);
-
5077 if (start + 2 < end &&
-
5078 text[start] == '*' &&
-
5079 text[start + 1] == '/' &&
-
5080 text[start + 2] == '*')
-
5081 {
-
5082 interval.end = (interval.start = start) + 3;
-
5083 return true;
-
5084 }
-
5085 else if (start < end && text[start] == '*') {
-
5086 interval.end = (interval.start = start) + 1;
-
5087 return true;
-
5088 }
-
5089 else {
-
5090 interval.start = (interval.end = start) + 1;
-
5091 return false;
-
5092 }
-
5093 }
-
5094 };
-
5095
-
5099 class http_media_range : public parser
-
5100 {
-
5101 public:
-
5102 virtual bool match(
-
5103 _In_reads_or_z_(end) const char* text,
-
5104 _In_ size_t start = 0,
-
5105 _In_ size_t end = (size_t)-1,
-
5106 _In_ int flags = match_default)
-
5107 {
-
5108 assert(text || start >= end);
-
5109 interval.end = start;
-
5110 if (type.match(text, interval.end, end, flags))
-
5111 interval.end = type.interval.end;
-
5112 else
-
5113 goto error;
-
5114 while (m_space.match(text, interval.end, end, flags))
-
5115 interval.end = m_space.interval.end;
-
5116 if (interval.end < end && text[interval.end] == '/')
-
5117 interval.end++;
-
5118 else
-
5119 goto error;
-
5120 while (m_space.match(text, interval.end, end, flags))
-
5121 interval.end = m_space.interval.end;
-
5122 if (subtype.match(text, interval.end, end, flags))
-
5123 interval.end = subtype.interval.end;
-
5124 else
-
5125 goto error;
-
5126 interval.start = start;
-
5127 return true;
-
5128
-
5129 error:
-
5130 type.invalidate();
-
5131 subtype.invalidate();
-
5132 interval.start = (interval.end = start) + 1;
-
5133 return false;
-
5134 }
-
5135
-
5136 virtual void invalidate()
-
5137 {
-
5138 type.invalidate();
-
5139 subtype.invalidate();
-
5140 parser::invalidate();
-
5141 }
-
5142
-
5143 public:
-
5144 http_token type;
-
5145 http_token subtype;
-
5146
-
5147 protected:
-
5148 http_space m_space;
-
5149 };
-
5150
-
5154 class http_media_type : public http_media_range
-
5155 {
-
5156 public:
-
5157 virtual bool match(
-
5158 _In_reads_or_z_(end) const char* text,
-
5159 _In_ size_t start = 0,
-
5160 _In_ size_t end = (size_t)-1,
-
5161 _In_ int flags = match_default)
-
5162 {
-
5163 assert(text || start >= end);
-
5164 if (!http_media_range::match(text, start, end, flags))
-
5165 goto error;
-
5166 params.clear();
-
5167 for (;;) {
-
5168 if (interval.end < end && text[interval.end]) {
-
5169 if (m_space.match(text, interval.end, end, flags))
-
5170 interval.end = m_space.interval.end;
-
5171 else if (text[interval.end] == ';') {
-
5172 interval.end++;
-
5173 while (m_space.match(text, interval.end, end, flags))
-
5174 interval.end = m_space.interval.end;
-
5175 http_parameter param;
-
5176 if (param.match(text, interval.end, end, flags)) {
-
5177 interval.end = param.interval.end;
-
5178 params.push_back(std::move(param));
-
5179 }
-
5180 else
-
5181 break;
-
5182 }
-
5183 else
-
5184 break;
-
5185 }
-
5186 else
-
5187 break;
-
5188 }
-
5189 interval.end = params.empty() ? subtype.interval.end : params.back().interval.end;
-
5190 return true;
-
5191
-
5192 error:
-
5193 http_media_range::invalidate();
-
5194 params.clear();
-
5195 interval.start = (interval.end = start) + 1;
-
5196 return false;
-
5197 }
-
5198
-
5199 virtual void invalidate()
-
5200 {
-
5201 params.clear();
-
5202 http_media_range::invalidate();
-
5203 }
-
5204
-
5205 public:
-
5206 std::list<http_parameter> params;
-
5207 };
-
5208
-
5212 class http_url_server : public parser
-
5213 {
-
5214 public:
-
5215 virtual bool match(
-
5216 _In_reads_or_z_(end) const char* text,
-
5217 _In_ size_t start = 0,
-
5218 _In_ size_t end = (size_t)-1,
-
5219 _In_ int flags = match_default)
-
5220 {
-
5221 assert(text || start >= end);
-
5222 interval.end = start;
-
5223 for (;;) {
-
5224 if (interval.end < end && text[interval.end]) {
-
5225 if ((unsigned int)text[interval.end] < 0x20 ||
-
5226 (unsigned int)text[interval.end] == 0x7f ||
-
5227 text[interval.end] == ':' ||
-
5228 text[interval.end] == '/' ||
-
5229 isspace(text[interval.end]))
-
5230 break;
-
5231 else
-
5232 interval.end++;
-
5233 }
-
5234 else
-
5235 break;
-
5236 }
-
5237 if (start < interval.end) {
-
5238 interval.start = start;
-
5239 return true;
-
5240 }
-
5241 interval.start = (interval.end = start) + 1;
-
5242 return false;
-
5243 }
-
5244 };
-
5245
-
5249 class http_url_port : public parser
-
5250 {
-
5251 public:
-
5252 http_url_port(_In_ const std::locale& locale = std::locale()) :
-
5253 parser(locale),
-
5254 value(0)
-
5255 {}
-
5256
-
5257 virtual bool match(
-
5258 _In_reads_or_z_(end) const char* text,
-
5259 _In_ size_t start = 0,
-
5260 _In_ size_t end = (size_t)-1,
-
5261 _In_ int flags = match_default)
-
5262 {
-
5263 assert(text || start >= end);
-
5264 value = 0;
-
5265 interval.end = start;
-
5266 for (;;) {
-
5267 if (interval.end < end && text[interval.end]) {
-
5268 if ('0' <= text[interval.end] && text[interval.end] <= '9') {
-
5269 size_t _value = (size_t)value * 10 + text[interval.end] - '0';
-
5270 if (_value > (uint16_t)-1) {
-
5271 value = 0;
-
5272 interval.start = (interval.end = start) + 1;
-
5273 return false;
-
5274 }
-
5275 value = (uint16_t)_value;
-
5276 interval.end++;
-
5277 }
-
5278 else
-
5279 break;
-
5280 }
-
5281 else
-
5282 break;
-
5283 }
-
5284 if (start < interval.end) {
-
5285 interval.start = start;
-
5286 return true;
-
5287 }
-
5288 interval.start = (interval.end = start) + 1;
-
5289 return false;
-
5290 }
-
5291
-
5292 virtual void invalidate()
-
5293 {
-
5294 value = 0;
-
5295 parser::invalidate();
-
5296 }
-
5297
-
5298 public:
-
5299 uint16_t value;
-
5300 };
-
5301
-
5305 class http_url_path_segment : public parser
-
5306 {
-
5307 public:
-
5308 virtual bool match(
-
5309 _In_reads_or_z_(end) const char* text,
-
5310 _In_ size_t start = 0,
-
5311 _In_ size_t end = (size_t)-1,
-
5312 _In_ int flags = match_default)
-
5313 {
-
5314 assert(text || start >= end);
-
5315 interval.end = start;
-
5316 for (;;) {
-
5317 if (interval.end < end && text[interval.end]) {
-
5318 if ((unsigned int)text[interval.end] < 0x20 ||
-
5319 (unsigned int)text[interval.end] == 0x7f ||
-
5320 text[interval.end] == '?' ||
-
5321 text[interval.end] == '/' ||
-
5322 isspace(text[interval.end]))
-
5323 break;
-
5324 else
-
5325 interval.end++;
-
5326 }
-
5327 else
-
5328 break;
-
5329 }
-
5330 interval.start = start;
-
5331 return true;
-
5332 }
-
5333 };
-
5334
-
5338 class http_url_path : public parser
-
5339 {
-
5340 public:
-
5341 virtual bool match(
-
5342 _In_reads_or_z_(end) const char* text,
-
5343 _In_ size_t start = 0,
-
5344 _In_ size_t end = (size_t)-1,
-
5345 _In_ int flags = match_default)
-
5346 {
-
5347 assert(text || start >= end);
-
5348 http_url_path_segment s;
-
5349 interval.end = start;
-
5350 segments.clear();
-
5351 assert(text || interval.end >= end);
-
5352 if (interval.end < end && text[interval.end] != '/')
-
5353 goto error;
-
5354 interval.end++;
-
5355 s.match(text, interval.end, end, flags);
-
5356 segments.push_back(s);
-
5357 interval.end = s.interval.end;
-
5358 for (;;) {
-
5359 if (interval.end < end && text[interval.end]) {
-
5360 if (text[interval.end] == '/') {
-
5361 interval.end++;
-
5362 s.match(text, interval.end, end, flags);
-
5363 segments.push_back(s);
-
5364 interval.end = s.interval.end;
-
5365 }
-
5366 else
-
5367 break;
-
5368 }
-
5369 else
-
5370 break;
-
5371 }
-
5372 interval.start = start;
-
5373 return true;
-
5374
-
5375 error:
-
5376 segments.clear();
-
5377 interval.start = (interval.end = start) + 1;
-
5378 return false;
-
5379 }
-
5380
-
5381 virtual void invalidate()
-
5382 {
-
5383 segments.clear();
-
5384 parser::invalidate();
-
5385 }
-
5386
-
5387 public:
-
5388 std::vector<http_url_path_segment> segments;
-
5389 };
-
5390
-
5394 class http_url_parameter : public parser
-
5395 {
-
5396 public:
-
5397 virtual bool match(
-
5398 _In_reads_or_z_(end) const char* text,
-
5399 _In_ size_t start = 0,
-
5400 _In_ size_t end = (size_t)-1,
-
5401 _In_ int flags = match_default)
-
5402 {
-
5403 assert(text || start >= end);
-
5404 interval.end = start;
-
5405 name.start = interval.end;
-
5406 for (;;) {
-
5407 if (interval.end < end && text[interval.end]) {
-
5408 if ((unsigned int)text[interval.end] < 0x20 ||
-
5409 (unsigned int)text[interval.end] == 0x7f ||
-
5410 text[interval.end] == '&' ||
-
5411 text[interval.end] == '=' ||
-
5412 isspace(text[interval.end]))
-
5413 break;
-
5414 else
-
5415 interval.end++;
-
5416 }
-
5417 else
-
5418 break;
-
5419 }
-
5420 if (start < interval.end)
-
5421 name.end = interval.end;
-
5422 else
-
5423 goto error;
-
5424 if (text[interval.end] == '=') {
-
5425 interval.end++;
-
5426 value.start = interval.end;
-
5427 for (;;) {
-
5428 if (interval.end < end && text[interval.end]) {
-
5429 if ((unsigned int)text[interval.end] < 0x20 ||
-
5430 (unsigned int)text[interval.end] == 0x7f ||
-
5431 text[interval.end] == '&' ||
-
5432 isspace(text[interval.end]))
-
5433 break;
-
5434 else
-
5435 interval.end++;
-
5436 }
-
5437 else
-
5438 break;
-
5439 }
-
5440 value.end = interval.end;
-
5441 }
-
5442 else {
-
5443 value.start = 1;
-
5444 value.end = 0;
-
5445 }
-
5446 interval.start = start;
-
5447 return true;
-
5448
-
5449 error:
-
5450 name.start = 1;
-
5451 name.end = 0;
-
5452 value.start = 1;
-
5453 value.end = 0;
-
5454 interval.start = (interval.end = start) + 1;
-
5455 return false;
-
5456 }
-
5457
-
5458 virtual void invalidate()
-
5459 {
-
5460 name.start = 1;
-
5461 name.end = 0;
-
5462 value.start = 1;
-
5463 value.end = 0;
-
5464 parser::invalidate();
-
5465 }
-
5466
-
5467 public:
-
5468 stdex::interval<size_t> name;
-
5469 stdex::interval<size_t> value;
-
5470 };
-
5471
-
5475 class http_url : public parser
-
5476 {
-
5477 public:
-
5478 http_url(_In_ const std::locale& locale = std::locale()) :
-
5479 parser(locale),
-
5480 port(locale)
-
5481 {}
-
5482
-
5483 virtual bool match(
-
5484 _In_reads_or_z_(end) const char* text,
-
5485 _In_ size_t start = 0,
-
5486 _In_ size_t end = (size_t)-1,
-
5487 _In_ int flags = match_default)
-
5488 {
-
5489 assert(text || start >= end);
-
5490 interval.end = start;
-
5491
-
5492 if (interval.end + 7 <= end && stdex::strnicmp(text + interval.end, 7, "http://", (size_t)-1, m_locale) == 0) {
-
5493 interval.end += 7;
-
5494 if (server.match(text, interval.end, end, flags))
-
5495 interval.end = server.interval.end;
-
5496 else
-
5497 goto error;
-
5498 if (interval.end < end && text[interval.end] == ':') {
-
5499 interval.end++;
-
5500 if (port.match(text, interval.end, end, flags))
-
5501 interval.end = port.interval.end;
-
5502 }
-
5503 else {
-
5504 port.invalidate();
-
5505 port.value = 80;
-
5506 }
-
5507 }
-
5508 else {
-
5509 server.invalidate();
-
5510 port.invalidate();
-
5511 port.value = 80;
-
5512 }
-
5513
-
5514 if (path.match(text, interval.end, end, flags))
-
5515 interval.end = path.interval.end;
-
5516 else
-
5517 goto error;
-
5518
-
5519 params.clear();
+
4418 interval.end = start;
+
4419
+
4420 if (degree->match(text, interval.end, end, flags) &&
+
4421 degree_separator->match(text, degree->interval.end, end, flags))
+
4422 {
+
4423 // Degrees
+
4424 interval.end = degree_separator->interval.end;
+
4425 }
+
4426 else {
+
4427 degree->invalidate();
+
4428 degree_separator->invalidate();
+
4429 }
+
4430
+
4431 if (minute->match(text, interval.end, end, flags) &&
+
4432 minute->value < 60 &&
+
4433 minute_separator->match(text, minute->interval.end, end, flags))
+
4434 {
+
4435 // Minutes
+
4436 interval.end = minute_separator->interval.end;
+
4437 }
+
4438 else {
+
4439 minute->invalidate();
+
4440 minute_separator->invalidate();
+
4441 }
+
4442
+
4443 if (second && second->match(text, interval.end, end, flags) &&
+
4444 second->value < 60)
+
4445 {
+
4446 // Seconds
+
4447 interval.end = second->interval.end;
+
4448 if (second_separator && second_separator->match(text, interval.end, end, flags))
+
4449 interval.end = second_separator->interval.end;
+
4450 else
+
4451 if (second_separator) second_separator->invalidate();
+
4452 }
+
4453 else {
+
4454 if (second) second->invalidate();
+
4455 if (second_separator) second_separator->invalidate();
+
4456 }
+
4457
+
4458 if (degree->interval.start < degree->interval.end ||
+
4459 minute->interval.start < minute->interval.end ||
+
4460 second && second->interval.start < second->interval.end)
+
4461 {
+
4462 if (decimal && decimal->match(text, interval.end, end, flags)) {
+
4463 // Decimals
+
4464 interval.end = decimal->interval.end;
+
4465 }
+
4466 else if (decimal)
+
4467 decimal->invalidate();
+
4468 interval.start = start;
+
4469 return true;
+
4470 }
+
4471 if (decimal) decimal->invalidate();
+
4472 interval.start = (interval.end = start) + 1;
+
4473 return false;
+
4474 }
+
4475
+
4476 virtual void invalidate()
+
4477 {
+
4478 degree->invalidate();
+
4479 degree_separator->invalidate();
+
4480 minute->invalidate();
+
4481 minute_separator->invalidate();
+
4482 if (second) second->invalidate();
+
4483 if (second_separator) second_separator->invalidate();
+
4484 if (decimal) decimal->invalidate();
+
4485 basic_parser<T>::invalidate();
+
4486 }
+
4487
+
4488 public:
+
4489 std::shared_ptr<basic_integer10<T>> degree;
+
4490 std::shared_ptr<basic_parser<T>> degree_separator;
+
4491 std::shared_ptr<basic_integer10<T>> minute;
+
4492 std::shared_ptr<basic_parser<T>> minute_separator;
+
4493 std::shared_ptr<basic_integer10<T>> second;
+
4494 std::shared_ptr<basic_parser<T>> second_separator;
+
4495 std::shared_ptr<basic_parser<T>> decimal;
+
4496 };
+
4497
+
4498 using angle = basic_angle<char>;
+
4499 using wangle = basic_angle<wchar_t>;
+
4500#ifdef _UNICODE
+
4501 using RRegElKot = wangle;
+
4502#else
+
4503 using RRegElKot = angle;
+
4504#endif
+
4505 using sgml_angle = basic_angle<char>;
+
4506
+
4510 template <class T>
+
4511 class basic_phone_number : public basic_parser<T>
+
4512 {
+
4513 public:
+
4514 basic_phone_number(
+
4515 _In_ const std::shared_ptr<basic_parser<T>>& digit,
+
4516 _In_ const std::shared_ptr<basic_parser<T>>& plus_sign,
+
4517 _In_ const std::shared_ptr<basic_set<T>>& lparenthesis,
+
4518 _In_ const std::shared_ptr<basic_set<T>>& rparenthesis,
+
4519 _In_ const std::shared_ptr<basic_parser<T>>& separator,
+
4520 _In_ const std::shared_ptr<basic_parser<T>>& space,
+
4521 _In_ const std::locale& locale = std::locale()) :
+
4522 basic_parser<T>(locale),
+
4523 m_digit(digit),
+
4524 m_plus_sign(plus_sign),
+
4525 m_lparenthesis(lparenthesis),
+
4526 m_rparenthesis(rparenthesis),
+
4527 m_separator(separator),
+
4528 m_space(space)
+
4529 {}
+
4530
+
4531 virtual bool match(
+
4532 _In_reads_or_z_(end) const T* text,
+
4533 _In_ size_t start = 0,
+
4534 _In_ size_t end = (size_t)-1,
+
4535 _In_ int flags = match_default)
+
4536 {
+
4537 assert(text || start >= end);
+
4538
+
4539 size_t safe_digit_end = start, safe_value_size = 0;
+
4540 bool has_digits = false, after_digit = false, in_parentheses = false, after_parentheses = false;
+
4541 const int space_match_flags = flags & ~match_multiline; // Spaces in phone numbers must never be broken in new line.
+
4542
+
4543 interval.end = start;
+
4544 value.clear();
+
4545 m_lparenthesis->invalidate();
+
4546 m_rparenthesis->invalidate();
+
4547
+
4548 if (m_plus_sign && m_plus_sign->match(text, interval.end, end, flags)) {
+
4549 value.append(text + m_plus_sign->interval.start, text + m_plus_sign->interval.end);
+
4550 safe_value_size = value.size();
+
4551 interval.end = m_plus_sign->interval.end;
+
4552 }
+
4553
+
4554 for (;;) {
+
4555 assert(text || interval.end >= end);
+
4556 if (interval.end >= end || !text[interval.end])
+
4557 break;
+
4558 if (m_digit->match(text, interval.end, end, flags)) {
+
4559 // Digit
+
4560 value.append(text + m_digit->interval.start, text + m_digit->interval.end);
+
4561 interval.end = m_digit->interval.end;
+
4562 if (!in_parentheses) {
+
4563 safe_digit_end = interval.end;
+
4564 safe_value_size = value.size();
+
4565 has_digits = true;
+
4566 }
+
4567 after_digit = true;
+
4568 after_parentheses = false;
+
4569 }
+
4570 else if (
+
4571 m_lparenthesis && !m_lparenthesis->interval && // No left parenthesis yet
+
4572 m_rparenthesis && !m_rparenthesis->interval && // Right parenthesis after left
+
4573 m_lparenthesis->match(text, interval.end, end, flags))
+
4574 {
+
4575 // Left parenthesis
+
4576 value.append(text + m_lparenthesis->interval.start, m_lparenthesis->interval.size());
+
4577 interval.end = m_lparenthesis->interval.end;
+
4578 in_parentheses = true;
+
4579 after_digit = false;
+
4580 after_parentheses = false;
+
4581 }
+
4582 else if (
+
4583 in_parentheses && // After left parenthesis
+
4584 m_rparenthesis && !m_rparenthesis->interval && // No right parenthesis yet
+
4585 m_rparenthesis->match(text, interval.end, end, flags) &&
+
4586 m_lparenthesis->hit_offset == m_rparenthesis->hit_offset) // Left and right parentheses must match
+
4587 {
+
4588 // Right parenthesis
+
4589 value.append(text + m_rparenthesis->interval.start, text + m_rparenthesis->interval.end);
+
4590 interval.end = m_rparenthesis->interval.end;
+
4591 safe_digit_end = interval.end;
+
4592 safe_value_size = value.size();
+
4593 in_parentheses = false;
+
4594 after_digit = false;
+
4595 after_parentheses = true;
+
4596 }
+
4597 else if (
+
4598 after_digit &&
+
4599 !in_parentheses && // No separators inside parentheses
+
4600 !after_parentheses && // No separators following right parenthesis
+
4601 m_separator && m_separator->match(text, interval.end, end, flags))
+
4602 {
+
4603 // Separator
+
4604 interval.end = m_separator->interval.end;
+
4605 after_digit = false;
+
4606 after_parentheses = false;
+
4607 }
+
4608 else if (
+
4609 (after_digit || after_parentheses) &&
+
4610 m_space && m_space->match(text, interval.end, end, space_match_flags))
+
4611 {
+
4612 // Space
+
4613 interval.end = m_space->interval.end;
+
4614 after_digit = false;
+
4615 after_parentheses = false;
+
4616 }
+
4617 else
+
4618 break;
+
4619 }
+
4620 if (has_digits) {
+
4621 value.erase(safe_value_size);
+
4622 interval.start = start;
+
4623 interval.end = safe_digit_end;
+
4624 return true;
+
4625 }
+
4626 value.clear();
+
4627 interval.start = (interval.end = start) + 1;
+
4628 return false;
+
4629 }
+
4630
+
4631 virtual void invalidate()
+
4632 {
+
4633 value.clear();
+
4634 basic_parser<T>::invalidate();
+
4635 }
+
4636
+
4637 public:
+
4638 std::basic_string<T> value;
+
4639
+
4640 protected:
+
4641 std::shared_ptr<basic_parser<T>> m_digit;
+
4642 std::shared_ptr<basic_parser<T>> m_plus_sign;
+
4643 std::shared_ptr<basic_set<T>> m_lparenthesis;
+
4644 std::shared_ptr<basic_set<T>> m_rparenthesis;
+
4645 std::shared_ptr<basic_parser<T>> m_separator;
+
4646 std::shared_ptr<basic_parser<T>> m_space;
+
4647 };
+
4648
+
4649 using phone_number = basic_phone_number<char>;
+
4650 using wphone_number = basic_phone_number<wchar_t>;
+
4651#ifdef _UNICODE
+
4652 using tphone_number = wphone_number;
+
4653#else
+
4654 using tphone_number = phone_number;
+
4655#endif
+
4656 using sgml_phone_number = basic_phone_number<char>;
+
4657
+
4661 template <class T>
+
4662 class basic_chemical_formula : public basic_parser<T>
+
4663 {
+
4664 public:
+
4665 basic_chemical_formula(
+
4666 _In_ const std::shared_ptr<basic_parser<T>>& element,
+
4667 _In_ const std::shared_ptr<basic_parser<T>>& digit,
+
4668 _In_ const std::shared_ptr<basic_parser<T>>& sign,
+
4669 _In_ const std::locale& locale = std::locale()) :
+
4670 basic_parser<T>(locale),
+
4671 m_element(element),
+
4672 m_digit(digit),
+
4673 m_sign(sign),
+
4674 has_digits(false),
+
4675 has_charge(false)
+
4676 {}
+
4677
+
4678 virtual bool match(
+
4679 _In_reads_or_z_(end) const T* text,
+
4680 _In_ size_t start = 0,
+
4681 _In_ size_t end = (size_t)-1,
+
4682 _In_ int flags = match_default)
+
4683 {
+
4684 assert(text || start >= end);
+
4685
+
4686 has_digits = false;
+
4687 has_charge = false;
+
4688 interval.end = start;
+
4689
+
4690 const int element_match_flags = flags & ~match_case_insensitive; // Chemical elements are always case-sensitive.
+
4691 for (;;) {
+
4692 if (m_element->match(text, interval.end, end, element_match_flags)) {
+
4693 interval.end = m_element->interval.end;
+
4694 while (m_digit->match(text, interval.end, end, flags)) {
+
4695 interval.end = m_digit->interval.end;
+
4696 has_digits = true;
+
4697 }
+
4698 }
+
4699 else if (start < interval.end) {
+
4700 if (m_sign->match(text, interval.end, end, flags)) {
+
4701 interval.end = m_sign->interval.end;
+
4702 has_charge = true;
+
4703 }
+
4704 interval.start = start;
+
4705 return true;
+
4706 }
+
4707 else {
+
4708 interval.start = (interval.end = start) + 1;
+
4709 return false;
+
4710 }
+
4711 }
+
4712 }
+
4713
+
4714 virtual void invalidate()
+
4715 {
+
4716 has_digits = false;
+
4717 has_charge = false;
+
4718 basic_parser<T>::invalidate();
+
4719 }
+
4720
+
4721 public:
+
4722 bool has_digits;
+
4723 bool has_charge;
+
4724
+
4725 protected:
+
4726 std::shared_ptr<basic_parser<T>> m_element;
+
4727 std::shared_ptr<basic_parser<T>> m_digit;
+
4728 std::shared_ptr<basic_parser<T>> m_sign;
+
4729 };
+
4730
+
4731 using chemical_formula = basic_chemical_formula<char>;
+
4732 using wchemical_formula = basic_chemical_formula<wchar_t>;
+
4733#ifdef _UNICODE
+
4734 using tchemical_formula = wchemical_formula;
+
4735#else
+
4736 using tchemical_formula = chemical_formula;
+
4737#endif
+
4738 using sgml_chemical_formula = basic_chemical_formula<char>;
+
4739
+
4743 class http_line_break : public parser
+
4744 {
+
4745 public:
+
4746 virtual bool match(
+
4747 _In_reads_or_z_(end) const char* text,
+
4748 _In_ size_t start = 0,
+
4749 _In_ size_t end = (size_t)-1,
+
4750 _In_ int flags = match_default)
+
4751 {
+
4752 assert(text || start >= end);
+
4753 interval.end = start;
+
4754
+
4755 assert(text || interval.end >= end);
+
4756 if (interval.end < end && text[interval.end]) {
+
4757 if (text[interval.end] == '\r') {
+
4758 interval.end++;
+
4759 if (interval.end < end && text[interval.end] == '\n') {
+
4760 interval.start = start;
+
4761 interval.end++;
+
4762 return true;
+
4763 }
+
4764 }
+
4765 else if (text[interval.end] == '\n') {
+
4766 interval.start = start;
+
4767 interval.end++;
+
4768 return true;
+
4769 }
+
4770 }
+
4771 interval.start = (interval.end = start) + 1;
+
4772 return false;
+
4773 }
+
4774 };
+
4775
+
4779 class http_space : public parser
+
4780 {
+
4781 public:
+
4782 virtual bool match(
+
4783 _In_reads_or_z_(end) const char* text,
+
4784 _In_ size_t start = 0,
+
4785 _In_ size_t end = (size_t)-1,
+
4786 _In_ int flags = match_default)
+
4787 {
+
4788 assert(text || start >= end);
+
4789 interval.end = start;
+
4790 if (m_line_break.match(text, interval.end, end, flags)) {
+
4791 interval.end = m_line_break.interval.end;
+
4792 if (interval.end < end && text[interval.end] && isspace(text[interval.end])) {
+
4793 interval.start = start;
+
4794 interval.end++;
+
4795 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
+
4796 return true;
+
4797 }
+
4798 }
+
4799 else if (interval.end < end && text[interval.end] && isspace(text[interval.end])) {
+
4800 interval.start = start;
+
4801 interval.end++;
+
4802 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
+
4803 return true;
+
4804 }
+
4805 interval.start = (interval.end = start) + 1;
+
4806 return false;
+
4807 }
+
4808
+
4809 protected:
+
4810 http_line_break m_line_break;
+
4811 };
+
4812
+
4816 class http_text_char : public parser
+
4817 {
+
4818 public:
+
4819 virtual bool match(
+
4820 _In_reads_or_z_(end) const char* text,
+
4821 _In_ size_t start = 0,
+
4822 _In_ size_t end = (size_t)-1,
+
4823 _In_ int flags = match_default)
+
4824 {
+
4825 assert(text || start >= end);
+
4826 interval.end = start;
+
4827
+
4828 assert(text || interval.end >= end);
+
4829 if (m_space.match(text, interval.end, end, flags)) {
+
4830 interval.start = start;
+
4831 interval.end = m_space.interval.end;
+
4832 return true;
+
4833 }
+
4834 else if (interval.end < end && text[interval.end] && text[interval.end] >= 0x20) {
+
4835 interval.start = start;
+
4836 interval.end++;
+
4837 return true;
+
4838 }
+
4839 interval.start = (interval.end = start) + 1;
+
4840 return false;
+
4841 }
+
4842
+
4843 protected:
+
4844 http_space m_space;
+
4845 };
+
4846
+
4850 class http_token : public parser
+
4851 {
+
4852 public:
+
4853 virtual bool match(
+
4854 _In_reads_or_z_(end) const char* text,
+
4855 _In_ size_t start = 0,
+
4856 _In_ size_t end = (size_t)-1,
+
4857 _In_ int flags = match_default)
+
4858 {
+
4859 assert(text || start >= end);
+
4860 interval.end = start;
+
4861 for (;;) {
+
4862 if (interval.end < end && text[interval.end]) {
+
4863 if ((unsigned int)text[interval.end] < 0x20 ||
+
4864 (unsigned int)text[interval.end] == 0x7f ||
+
4865 text[interval.end] == '(' ||
+
4866 text[interval.end] == ')' ||
+
4867 text[interval.end] == '<' ||
+
4868 text[interval.end] == '>' ||
+
4869 text[interval.end] == '@' ||
+
4870 text[interval.end] == ',' ||
+
4871 text[interval.end] == ';' ||
+
4872 text[interval.end] == ':' ||
+
4873 text[interval.end] == '\\' ||
+
4874 text[interval.end] == '\"' ||
+
4875 text[interval.end] == '/' ||
+
4876 text[interval.end] == '[' ||
+
4877 text[interval.end] == ']' ||
+
4878 text[interval.end] == '?' ||
+
4879 text[interval.end] == '=' ||
+
4880 text[interval.end] == '{' ||
+
4881 text[interval.end] == '}' ||
+
4882 isspace(text[interval.end]))
+
4883 break;
+
4884 else
+
4885 interval.end++;
+
4886 }
+
4887 else
+
4888 break;
+
4889 }
+
4890 if (start < interval.end) {
+
4891 interval.start = start;
+
4892 return true;
+
4893 }
+
4894 else {
+
4895 interval.start = (interval.end = start) + 1;
+
4896 return false;
+
4897 }
+
4898 }
+
4899 };
+
4900
+
4904 class http_quoted_string : public parser
+
4905 {
+
4906 public:
+
4907 virtual bool match(
+
4908 _In_reads_or_z_(end) const char* text,
+
4909 _In_ size_t start = 0,
+
4910 _In_ size_t end = (size_t)-1,
+
4911 _In_ int flags = match_default)
+
4912 {
+
4913 assert(text || start >= end);
+
4914 interval.end = start;
+
4915 if (interval.end < end && text[interval.end] != '"')
+
4916 goto error;
+
4917 interval.end++;
+
4918 content.start = interval.end;
+
4919 for (;;) {
+
4920 assert(text || interval.end >= end);
+
4921 if (interval.end < end && text[interval.end]) {
+
4922 if (text[interval.end] == '"') {
+
4923 content.end = interval.end;
+
4924 interval.end++;
+
4925 break;
+
4926 }
+
4927 else if (text[interval.end] == '\\') {
+
4928 interval.end++;
+
4929 if (interval.end < end && text[interval.end]) {
+
4930 interval.end++;
+
4931 }
+
4932 else
+
4933 goto error;
+
4934 }
+
4935 else if (m_chr.match(text, interval.end, end, flags))
+
4936 interval.end++;
+
4937 else
+
4938 goto error;
+
4939 }
+
4940 else
+
4941 goto error;
+
4942 }
+
4943 interval.start = start;
+
4944 return true;
+
4945
+
4946 error:
+
4947 content.start = 1;
+
4948 content.end = 0;
+
4949 interval.start = (interval.end = start) + 1;
+
4950 return false;
+
4951 }
+
4952
+
4953 virtual void invalidate()
+
4954 {
+
4955 content.start = 1;
+
4956 content.end = 0;
+
4957 parser::invalidate();
+
4958 }
+
4959
+
4960 public:
+
4961 stdex::interval<size_t> content;
+
4962
+
4963 protected:
+
4964 http_text_char m_chr;
+
4965 };
+
4966
+
4970 class http_value : public parser
+
4971 {
+
4972 public:
+
4973 virtual bool match(
+
4974 _In_reads_or_z_(end) const char* text,
+
4975 _In_ size_t start = 0,
+
4976 _In_ size_t end = (size_t)-1,
+
4977 _In_ int flags = match_default)
+
4978 {
+
4979 assert(text || start >= end);
+
4980 interval.end = start;
+
4981 if (string.match(text, interval.end, end, flags)) {
+
4982 token.invalidate();
+
4983 interval.end = string.interval.end;
+
4984 interval.start = start;
+
4985 return true;
+
4986 }
+
4987 else if (token.match(text, interval.end, end, flags)) {
+
4988 string.invalidate();
+
4989 interval.end = token.interval.end;
+
4990 interval.start = start;
+
4991 return true;
+
4992 }
+
4993 else {
+
4994 interval.start = (interval.end = start) + 1;
+
4995 return false;
+
4996 }
+
4997 }
+
4998
+
4999 virtual void invalidate()
+
5000 {
+
5001 string.invalidate();
+
5002 token.invalidate();
+
5003 parser::invalidate();
+
5004 }
+
5005
+
5006 public:
+
5007 http_quoted_string string;
+
5008 http_token token;
+
5009 };
+
5010
+
5014 class http_parameter : public parser
+
5015 {
+
5016 public:
+
5017 virtual bool match(
+
5018 _In_reads_or_z_(end) const char* text,
+
5019 _In_ size_t start = 0,
+
5020 _In_ size_t end = (size_t)-1,
+
5021 _In_ int flags = match_default)
+
5022 {
+
5023 assert(text || start >= end);
+
5024 interval.end = start;
+
5025 if (name.match(text, interval.end, end, flags))
+
5026 interval.end = name.interval.end;
+
5027 else
+
5028 goto error;
+
5029 while (m_space.match(text, interval.end, end, flags))
+
5030 interval.end = m_space.interval.end;
+
5031 assert(text || interval.end >= end);
+
5032 if (interval.end < end && text[interval.end] == '=')
+
5033 interval.end++;
+
5034 else
+
5035 while (m_space.match(text, interval.end, end, flags))
+
5036 interval.end = m_space.interval.end;
+
5037 if (value.match(text, interval.end, end, flags))
+
5038 interval.end = value.interval.end;
+
5039 else
+
5040 goto error;
+
5041 interval.start = start;
+
5042 return true;
+
5043
+
5044 error:
+
5045 name.invalidate();
+
5046 value.invalidate();
+
5047 interval.start = (interval.end = start) + 1;
+
5048 return false;
+
5049 }
+
5050
+
5051 virtual void invalidate()
+
5052 {
+
5053 name.invalidate();
+
5054 value.invalidate();
+
5055 parser::invalidate();
+
5056 }
+
5057
+
5058 public:
+
5059 http_token name;
+
5060 http_value value;
+
5061
+
5062 protected:
+
5063 http_space m_space;
+
5064 };
+
5065
+
5069 class http_any_type : public parser
+
5070 {
+
5071 public:
+
5072 virtual bool match(
+
5073 _In_reads_or_z_(end) const char* text,
+
5074 _In_ size_t start = 0,
+
5075 _In_ size_t end = (size_t)-1,
+
5076 _In_ int flags = match_default)
+
5077 {
+
5078 assert(text || start >= end);
+
5079 if (start + 2 < end &&
+
5080 text[start] == '*' &&
+
5081 text[start + 1] == '/' &&
+
5082 text[start + 2] == '*')
+
5083 {
+
5084 interval.end = (interval.start = start) + 3;
+
5085 return true;
+
5086 }
+
5087 else if (start < end && text[start] == '*') {
+
5088 interval.end = (interval.start = start) + 1;
+
5089 return true;
+
5090 }
+
5091 else {
+
5092 interval.start = (interval.end = start) + 1;
+
5093 return false;
+
5094 }
+
5095 }
+
5096 };
+
5097
+
5101 class http_media_range : public parser
+
5102 {
+
5103 public:
+
5104 virtual bool match(
+
5105 _In_reads_or_z_(end) const char* text,
+
5106 _In_ size_t start = 0,
+
5107 _In_ size_t end = (size_t)-1,
+
5108 _In_ int flags = match_default)
+
5109 {
+
5110 assert(text || start >= end);
+
5111 interval.end = start;
+
5112 if (type.match(text, interval.end, end, flags))
+
5113 interval.end = type.interval.end;
+
5114 else
+
5115 goto error;
+
5116 while (m_space.match(text, interval.end, end, flags))
+
5117 interval.end = m_space.interval.end;
+
5118 if (interval.end < end && text[interval.end] == '/')
+
5119 interval.end++;
+
5120 else
+
5121 goto error;
+
5122 while (m_space.match(text, interval.end, end, flags))
+
5123 interval.end = m_space.interval.end;
+
5124 if (subtype.match(text, interval.end, end, flags))
+
5125 interval.end = subtype.interval.end;
+
5126 else
+
5127 goto error;
+
5128 interval.start = start;
+
5129 return true;
+
5130
+
5131 error:
+
5132 type.invalidate();
+
5133 subtype.invalidate();
+
5134 interval.start = (interval.end = start) + 1;
+
5135 return false;
+
5136 }
+
5137
+
5138 virtual void invalidate()
+
5139 {
+
5140 type.invalidate();
+
5141 subtype.invalidate();
+
5142 parser::invalidate();
+
5143 }
+
5144
+
5145 public:
+
5146 http_token type;
+
5147 http_token subtype;
+
5148
+
5149 protected:
+
5150 http_space m_space;
+
5151 };
+
5152
+
5156 class http_media_type : public http_media_range
+
5157 {
+
5158 public:
+
5159 virtual bool match(
+
5160 _In_reads_or_z_(end) const char* text,
+
5161 _In_ size_t start = 0,
+
5162 _In_ size_t end = (size_t)-1,
+
5163 _In_ int flags = match_default)
+
5164 {
+
5165 assert(text || start >= end);
+
5166 if (!http_media_range::match(text, start, end, flags))
+
5167 goto error;
+
5168 params.clear();
+
5169 for (;;) {
+
5170 if (interval.end < end && text[interval.end]) {
+
5171 if (m_space.match(text, interval.end, end, flags))
+
5172 interval.end = m_space.interval.end;
+
5173 else if (text[interval.end] == ';') {
+
5174 interval.end++;
+
5175 while (m_space.match(text, interval.end, end, flags))
+
5176 interval.end = m_space.interval.end;
+
5177 http_parameter param;
+
5178 if (param.match(text, interval.end, end, flags)) {
+
5179 interval.end = param.interval.end;
+
5180 params.push_back(std::move(param));
+
5181 }
+
5182 else
+
5183 break;
+
5184 }
+
5185 else
+
5186 break;
+
5187 }
+
5188 else
+
5189 break;
+
5190 }
+
5191 interval.end = params.empty() ? subtype.interval.end : params.back().interval.end;
+
5192 return true;
+
5193
+
5194 error:
+
5195 http_media_range::invalidate();
+
5196 params.clear();
+
5197 interval.start = (interval.end = start) + 1;
+
5198 return false;
+
5199 }
+
5200
+
5201 virtual void invalidate()
+
5202 {
+
5203 params.clear();
+
5204 http_media_range::invalidate();
+
5205 }
+
5206
+
5207 public:
+
5208 std::list<http_parameter> params;
+
5209 };
+
5210
+
5214 class http_url_server : public parser
+
5215 {
+
5216 public:
+
5217 virtual bool match(
+
5218 _In_reads_or_z_(end) const char* text,
+
5219 _In_ size_t start = 0,
+
5220 _In_ size_t end = (size_t)-1,
+
5221 _In_ int flags = match_default)
+
5222 {
+
5223 assert(text || start >= end);
+
5224 interval.end = start;
+
5225 for (;;) {
+
5226 if (interval.end < end && text[interval.end]) {
+
5227 if ((unsigned int)text[interval.end] < 0x20 ||
+
5228 (unsigned int)text[interval.end] == 0x7f ||
+
5229 text[interval.end] == ':' ||
+
5230 text[interval.end] == '/' ||
+
5231 isspace(text[interval.end]))
+
5232 break;
+
5233 else
+
5234 interval.end++;
+
5235 }
+
5236 else
+
5237 break;
+
5238 }
+
5239 if (start < interval.end) {
+
5240 interval.start = start;
+
5241 return true;
+
5242 }
+
5243 interval.start = (interval.end = start) + 1;
+
5244 return false;
+
5245 }
+
5246 };
+
5247
+
5251 class http_url_port : public parser
+
5252 {
+
5253 public:
+
5254 http_url_port(_In_ const std::locale& locale = std::locale()) :
+
5255 parser(locale),
+
5256 value(0)
+
5257 {}
+
5258
+
5259 virtual bool match(
+
5260 _In_reads_or_z_(end) const char* text,
+
5261 _In_ size_t start = 0,
+
5262 _In_ size_t end = (size_t)-1,
+
5263 _In_ int flags = match_default)
+
5264 {
+
5265 assert(text || start >= end);
+
5266 value = 0;
+
5267 interval.end = start;
+
5268 for (;;) {
+
5269 if (interval.end < end && text[interval.end]) {
+
5270 if ('0' <= text[interval.end] && text[interval.end] <= '9') {
+
5271 size_t _value = (size_t)value * 10 + text[interval.end] - '0';
+
5272 if (_value > (uint16_t)-1) {
+
5273 value = 0;
+
5274 interval.start = (interval.end = start) + 1;
+
5275 return false;
+
5276 }
+
5277 value = (uint16_t)_value;
+
5278 interval.end++;
+
5279 }
+
5280 else
+
5281 break;
+
5282 }
+
5283 else
+
5284 break;
+
5285 }
+
5286 if (start < interval.end) {
+
5287 interval.start = start;
+
5288 return true;
+
5289 }
+
5290 interval.start = (interval.end = start) + 1;
+
5291 return false;
+
5292 }
+
5293
+
5294 virtual void invalidate()
+
5295 {
+
5296 value = 0;
+
5297 parser::invalidate();
+
5298 }
+
5299
+
5300 public:
+
5301 uint16_t value;
+
5302 };
+
5303
+
5307 class http_url_path_segment : public parser
+
5308 {
+
5309 public:
+
5310 virtual bool match(
+
5311 _In_reads_or_z_(end) const char* text,
+
5312 _In_ size_t start = 0,
+
5313 _In_ size_t end = (size_t)-1,
+
5314 _In_ int flags = match_default)
+
5315 {
+
5316 assert(text || start >= end);
+
5317 interval.end = start;
+
5318 for (;;) {
+
5319 if (interval.end < end && text[interval.end]) {
+
5320 if ((unsigned int)text[interval.end] < 0x20 ||
+
5321 (unsigned int)text[interval.end] == 0x7f ||
+
5322 text[interval.end] == '?' ||
+
5323 text[interval.end] == '/' ||
+
5324 isspace(text[interval.end]))
+
5325 break;
+
5326 else
+
5327 interval.end++;
+
5328 }
+
5329 else
+
5330 break;
+
5331 }
+
5332 interval.start = start;
+
5333 return true;
+
5334 }
+
5335 };
+
5336
+
5340 class http_url_path : public parser
+
5341 {
+
5342 public:
+
5343 virtual bool match(
+
5344 _In_reads_or_z_(end) const char* text,
+
5345 _In_ size_t start = 0,
+
5346 _In_ size_t end = (size_t)-1,
+
5347 _In_ int flags = match_default)
+
5348 {
+
5349 assert(text || start >= end);
+
5350 http_url_path_segment s;
+
5351 interval.end = start;
+
5352 segments.clear();
+
5353 assert(text || interval.end >= end);
+
5354 if (interval.end < end && text[interval.end] != '/')
+
5355 goto error;
+
5356 interval.end++;
+
5357 s.match(text, interval.end, end, flags);
+
5358 segments.push_back(s);
+
5359 interval.end = s.interval.end;
+
5360 for (;;) {
+
5361 if (interval.end < end && text[interval.end]) {
+
5362 if (text[interval.end] == '/') {
+
5363 interval.end++;
+
5364 s.match(text, interval.end, end, flags);
+
5365 segments.push_back(s);
+
5366 interval.end = s.interval.end;
+
5367 }
+
5368 else
+
5369 break;
+
5370 }
+
5371 else
+
5372 break;
+
5373 }
+
5374 interval.start = start;
+
5375 return true;
+
5376
+
5377 error:
+
5378 segments.clear();
+
5379 interval.start = (interval.end = start) + 1;
+
5380 return false;
+
5381 }
+
5382
+
5383 virtual void invalidate()
+
5384 {
+
5385 segments.clear();
+
5386 parser::invalidate();
+
5387 }
+
5388
+
5389 public:
+
5390 std::vector<http_url_path_segment> segments;
+
5391 };
+
5392
+
5396 class http_url_parameter : public parser
+
5397 {
+
5398 public:
+
5399 virtual bool match(
+
5400 _In_reads_or_z_(end) const char* text,
+
5401 _In_ size_t start = 0,
+
5402 _In_ size_t end = (size_t)-1,
+
5403 _In_ int flags = match_default)
+
5404 {
+
5405 assert(text || start >= end);
+
5406 interval.end = start;
+
5407 name.start = interval.end;
+
5408 for (;;) {
+
5409 if (interval.end < end && text[interval.end]) {
+
5410 if ((unsigned int)text[interval.end] < 0x20 ||
+
5411 (unsigned int)text[interval.end] == 0x7f ||
+
5412 text[interval.end] == '&' ||
+
5413 text[interval.end] == '=' ||
+
5414 isspace(text[interval.end]))
+
5415 break;
+
5416 else
+
5417 interval.end++;
+
5418 }
+
5419 else
+
5420 break;
+
5421 }
+
5422 if (start < interval.end)
+
5423 name.end = interval.end;
+
5424 else
+
5425 goto error;
+
5426 if (text[interval.end] == '=') {
+
5427 interval.end++;
+
5428 value.start = interval.end;
+
5429 for (;;) {
+
5430 if (interval.end < end && text[interval.end]) {
+
5431 if ((unsigned int)text[interval.end] < 0x20 ||
+
5432 (unsigned int)text[interval.end] == 0x7f ||
+
5433 text[interval.end] == '&' ||
+
5434 isspace(text[interval.end]))
+
5435 break;
+
5436 else
+
5437 interval.end++;
+
5438 }
+
5439 else
+
5440 break;
+
5441 }
+
5442 value.end = interval.end;
+
5443 }
+
5444 else {
+
5445 value.start = 1;
+
5446 value.end = 0;
+
5447 }
+
5448 interval.start = start;
+
5449 return true;
+
5450
+
5451 error:
+
5452 name.start = 1;
+
5453 name.end = 0;
+
5454 value.start = 1;
+
5455 value.end = 0;
+
5456 interval.start = (interval.end = start) + 1;
+
5457 return false;
+
5458 }
+
5459
+
5460 virtual void invalidate()
+
5461 {
+
5462 name.start = 1;
+
5463 name.end = 0;
+
5464 value.start = 1;
+
5465 value.end = 0;
+
5466 parser::invalidate();
+
5467 }
+
5468
+
5469 public:
+
5470 stdex::interval<size_t> name;
+
5471 stdex::interval<size_t> value;
+
5472 };
+
5473
+
5477 class http_url : public parser
+
5478 {
+
5479 public:
+
5480 http_url(_In_ const std::locale& locale = std::locale()) :
+
5481 parser(locale),
+
5482 port(locale)
+
5483 {}
+
5484
+
5485 virtual bool match(
+
5486 _In_reads_or_z_(end) const char* text,
+
5487 _In_ size_t start = 0,
+
5488 _In_ size_t end = (size_t)-1,
+
5489 _In_ int flags = match_default)
+
5490 {
+
5491 assert(text || start >= end);
+
5492 interval.end = start;
+
5493
+
5494 if (interval.end + 7 <= end && stdex::strnicmp(text + interval.end, 7, "http://", (size_t)-1, m_locale) == 0) {
+
5495 interval.end += 7;
+
5496 if (server.match(text, interval.end, end, flags))
+
5497 interval.end = server.interval.end;
+
5498 else
+
5499 goto error;
+
5500 if (interval.end < end && text[interval.end] == ':') {
+
5501 interval.end++;
+
5502 if (port.match(text, interval.end, end, flags))
+
5503 interval.end = port.interval.end;
+
5504 }
+
5505 else {
+
5506 port.invalidate();
+
5507 port.value = 80;
+
5508 }
+
5509 }
+
5510 else {
+
5511 server.invalidate();
+
5512 port.invalidate();
+
5513 port.value = 80;
+
5514 }
+
5515
+
5516 if (path.match(text, interval.end, end, flags))
+
5517 interval.end = path.interval.end;
+
5518 else
+
5519 goto error;
5520
-
5521 if (interval.end < end && text[interval.end] == '?') {
-
5522 interval.end++;
-
5523 for (;;) {
-
5524 if (interval.end < end && text[interval.end]) {
-
5525 if ((unsigned int)text[interval.end] < 0x20 ||
-
5526 (unsigned int)text[interval.end] == 0x7f ||
-
5527 isspace(text[interval.end]))
-
5528 break;
-
5529 else if (text[interval.end] == '&')
-
5530 interval.end++;
-
5531 else {
-
5532 http_url_parameter param;
-
5533 if (param.match(text, interval.end, end, flags)) {
-
5534 interval.end = param.interval.end;
-
5535 params.push_back(std::move(param));
-
5536 }
-
5537 else
-
5538 break;
-
5539 }
-
5540 }
-
5541 else
-
5542 break;
-
5543 }
-
5544 }
-
5545
-
5546 interval.start = start;
-
5547 return true;
-
5548
-
5549 error:
-
5550 server.invalidate();
-
5551 port.invalidate();
-
5552 path.invalidate();
-
5553 params.clear();
-
5554 interval.start = (interval.end = start) + 1;
-
5555 return false;
-
5556 }
-
5557
-
5558 virtual void invalidate()
-
5559 {
-
5560 server.invalidate();
-
5561 port.invalidate();
-
5562 path.invalidate();
-
5563 params.clear();
-
5564 parser::invalidate();
-
5565 }
-
5566
-
5567 public:
-
5568 http_url_server server;
-
5569 http_url_port port;
-
5570 http_url_path path;
-
5571 std::list<http_url_parameter> params;
-
5572 };
-
5573
-
5577 class http_language : public parser
-
5578 {
-
5579 public:
-
5580 virtual bool match(
-
5581 _In_reads_or_z_(end) const char* text,
-
5582 _In_ size_t start = 0,
-
5583 _In_ size_t end = (size_t)-1,
-
5584 _In_ int flags = match_default)
-
5585 {
-
5586 assert(text || start >= end);
-
5587 interval.end = start;
-
5588 components.clear();
-
5589 for (;;) {
-
5590 if (interval.end < end && text[interval.end]) {
-
5591 stdex::interval<size_t> k;
-
5592 k.end = interval.end;
-
5593 for (;;) {
-
5594 if (k.end < end && text[k.end]) {
-
5595 if (isalpha(text[k.end]))
-
5596 k.end++;
-
5597 else
-
5598 break;
-
5599 }
-
5600 else
-
5601 break;
-
5602 }
-
5603 if (interval.end < k.end) {
-
5604 k.start = interval.end;
-
5605 interval.end = k.end;
-
5606 components.push_back(k);
-
5607 }
-
5608 else
-
5609 break;
-
5610 if (interval.end < end && text[interval.end] == '-')
-
5611 interval.end++;
-
5612 else
-
5613 break;
-
5614 }
-
5615 else
-
5616 break;
-
5617 }
-
5618 if (!components.empty()) {
-
5619 interval.start = start;
-
5620 interval.end = components.back().end;
-
5621 return true;
-
5622 }
-
5623 interval.start = (interval.end = start) + 1;
-
5624 return false;
-
5625 }
-
5626
-
5627 virtual void invalidate()
-
5628 {
-
5629 components.clear();
-
5630 parser::invalidate();
-
5631 }
-
5632
-
5633 public:
-
5634 std::vector<stdex::interval<size_t>> components;
-
5635 };
-
5636
-
5640 class http_weight : public parser
-
5641 {
-
5642 public:
-
5643 http_weight(_In_ const std::locale& locale = std::locale()) :
-
5644 parser(locale),
-
5645 value(1.0f)
-
5646 {}
-
5647
-
5648 virtual bool match(
-
5649 _In_reads_or_z_(end) const char* text,
-
5650 _In_ size_t start = 0,
-
5651 _In_ size_t end = (size_t)-1,
-
5652 _In_ int flags = match_default)
-
5653 {
-
5654 assert(text || start >= end);
-
5655 size_t celi_del = 0, decimalni_del = 0, decimalni_del_n = 1;
-
5656 interval.end = start;
-
5657 for (;;) {
-
5658 if (interval.end < end && text[interval.end]) {
-
5659 if ('0' <= text[interval.end] && text[interval.end] <= '9') {
-
5660 celi_del = celi_del * 10 + text[interval.end] - '0';
-
5661 interval.end++;
-
5662 }
-
5663 else if (text[interval.end] == '.') {
-
5664 interval.end++;
-
5665 for (;;) {
-
5666 if (interval.end < end && text[interval.end]) {
-
5667 if ('0' <= text[interval.end] && text[interval.end] <= '9') {
-
5668 decimalni_del = decimalni_del * 10 + text[interval.end] - '0';
-
5669 decimalni_del_n *= 10;
-
5670 interval.end++;
-
5671 }
-
5672 else
-
5673 break;
-
5674 }
-
5675 else
-
5676 break;
-
5677 }
-
5678 break;
-
5679 }
-
5680 else
-
5681 break;
-
5682 }
-
5683 else
-
5684 break;
-
5685 }
-
5686 if (start < interval.end) {
-
5687 value = (float)((double)celi_del + (double)decimalni_del / decimalni_del_n);
-
5688 interval.start = start;
-
5689 return true;
-
5690 }
-
5691 value = 1.0f;
-
5692 interval.start = (interval.end = start) + 1;
-
5693 return false;
-
5694 }
-
5695
-
5696 virtual void invalidate()
-
5697 {
-
5698 value = 1.0f;
-
5699 parser::invalidate();
-
5700 }
-
5701
-
5702 public:
-
5703 float value;
-
5704 };
-
5705
-
5709 class http_asterisk : public parser
-
5710 {
-
5711 public:
-
5712 virtual bool match(
-
5713 _In_reads_or_z_(end) const char* text,
-
5714 _In_ size_t start = 0,
-
5715 _In_ size_t end = (size_t)-1,
-
5716 _In_ int flags = match_default)
-
5717 {
-
5718 assert(text || end <= start);
-
5719 if (start < end && text[start] == '*') {
-
5720 interval.end = (interval.start = start) + 1;
-
5721 return true;
-
5722 }
-
5723 interval.start = (interval.end = start) + 1;
-
5724 return false;
-
5725 }
-
5726 };
-
5727
-
5731 template <class T, class T_asterisk = http_asterisk>
-
5732 class http_weighted_value : public parser
-
5733 {
-
5734 public:
-
5735 http_weighted_value(_In_ const std::locale& locale = std::locale()) :
-
5736 parser(locale),
-
5737 factor(locale)
-
5738 {}
-
5739
-
5740 virtual bool match(
-
5741 _In_reads_or_z_(end) const char* text,
-
5742 _In_ size_t start = 0,
-
5743 _In_ size_t end = (size_t)-1,
-
5744 _In_ int flags = match_default)
-
5745 {
-
5746 assert(text || start >= end);
-
5747 size_t konec_vrednosti;
-
5748 interval.end = start;
-
5749 if (asterisk.match(text, interval.end, end, flags)) {
-
5750 interval.end = konec_vrednosti = asterisk.interval.end;
-
5751 value.invalidate();
-
5752 }
-
5753 else if (value.match(text, interval.end, end, flags)) {
-
5754 interval.end = konec_vrednosti = value.interval.end;
-
5755 asterisk.invalidate();
-
5756 }
-
5757 else {
-
5758 asterisk.invalidate();
-
5759 value.invalidate();
-
5760 interval.start = (interval.end = start) + 1;
-
5761 return false;
-
5762 }
-
5763
-
5764 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
-
5765 if (interval.end < end && text[interval.end] == ';') {
-
5766 interval.end++;
-
5767 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
-
5768 if (interval.end < end && (text[interval.end] == 'q' || text[interval.end] == 'Q')) {
-
5769 interval.end++;
-
5770 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
-
5771 if (interval.end < end && text[interval.end] == '=') {
-
5772 interval.end++;
-
5773 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
-
5774 if (factor.match(text, interval.end, end, flags))
-
5775 interval.end = factor.interval.end;
-
5776 }
-
5777 }
-
5778 }
-
5779 if (!factor.interval) {
-
5780 factor.invalidate();
-
5781 interval.end = konec_vrednosti;
-
5782 }
-
5783 interval.start = start;
-
5784 return true;
-
5785 }
-
5786
-
5787 virtual void invalidate()
-
5788 {
-
5789 asterisk.invalidate();
-
5790 value.invalidate();
-
5791 factor.invalidate();
-
5792 parser::invalidate();
-
5793 }
-
5794
-
5795 public:
-
5796 T_asterisk asterisk;
-
5797 T value;
-
5798 http_weight factor;
-
5799 };
-
5800
-
5804 class http_cookie_parameter : public parser
-
5805 {
-
5806 public:
-
5807 virtual bool match(
-
5808 _In_reads_or_z_(end) const char* text,
-
5809 _In_ size_t start = 0,
-
5810 _In_ size_t end = (size_t)-1,
-
5811 _In_ int flags = match_default)
-
5812 {
-
5813 assert(text || start >= end);
-
5814 interval.end = start;
-
5815 if (interval.end < end && text[interval.end] == '$')
-
5816 interval.end++;
-
5817 else
-
5818 goto error;
-
5819 if (name.match(text, interval.end, end, flags))
-
5820 interval.end = name.interval.end;
-
5821 else
-
5822 goto error;
-
5823 while (m_space.match(text, interval.end, end, flags))
-
5824 interval.end = m_space.interval.end;
-
5825 if (interval.end < end && text[interval.end] == '=')
-
5826 interval.end++;
-
5827 else
-
5828 goto error;
-
5829 while (m_space.match(text, interval.end, end, flags))
-
5830 interval.end = m_space.interval.end;
-
5831 if (value.match(text, interval.end, end, flags))
-
5832 interval.end = value.interval.end;
-
5833 else
-
5834 goto error;
-
5835 interval.start = start;
-
5836 return true;
-
5837
-
5838 error:
-
5839 name.invalidate();
-
5840 value.invalidate();
-
5841 interval.start = (interval.end = start) + 1;
-
5842 return false;
-
5843 }
-
5844
-
5845 virtual void invalidate()
-
5846 {
-
5847 name.invalidate();
-
5848 value.invalidate();
-
5849 parser::invalidate();
-
5850 }
-
5851
-
5852 public:
-
5853 http_token name;
-
5854 http_value value;
-
5855
-
5856 protected:
-
5857 http_space m_space;
-
5858 };
-
5859
-
5863 class http_cookie : public parser
-
5864 {
-
5865 public:
-
5866 virtual bool match(
-
5867 _In_reads_or_z_(end) const char* text,
-
5868 _In_ size_t start = 0,
-
5869 _In_ size_t end = (size_t)-1,
-
5870 _In_ int flags = match_default)
-
5871 {
-
5872 assert(text || start >= end);
-
5873 interval.end = start;
-
5874 if (name.match(text, interval.end, end, flags))
-
5875 interval.end = name.interval.end;
-
5876 else
-
5877 goto error;
-
5878 while (m_space.match(text, interval.end, end, flags))
-
5879 interval.end = m_space.interval.end;
-
5880 if (interval.end < end && text[interval.end] == '=')
-
5881 interval.end++;
-
5882 else
-
5883 goto error;
-
5884 while (m_space.match(text, interval.end, end, flags))
-
5885 interval.end = m_space.interval.end;
-
5886 if (value.match(text, interval.end, end, flags))
-
5887 interval.end = value.interval.end;
-
5888 else
-
5889 goto error;
-
5890 params.clear();
-
5891 for (;;) {
-
5892 if (interval.end < end && text[interval.end]) {
-
5893 if (m_space.match(text, interval.end, end, flags))
-
5894 interval.end = m_space.interval.end;
-
5895 else if (text[interval.end] == ';') {
-
5896 interval.end++;
-
5897 while (m_space.match(text, interval.end, end, flags))
-
5898 interval.end = m_space.interval.end;
-
5899 http_cookie_parameter param;
-
5900 if (param.match(text, interval.end, end, flags)) {
-
5901 interval.end = param.interval.end;
-
5902 params.push_back(std::move(param));
-
5903 }
-
5904 else
-
5905 break;
-
5906 }
-
5907 else
-
5908 break;
-
5909 }
-
5910 else
-
5911 break;
-
5912 }
-
5913 interval.start = start;
-
5914 interval.end = params.empty() ? value.interval.end : params.back().interval.end;
-
5915 return true;
-
5916
-
5917 error:
-
5918 name.invalidate();
-
5919 value.invalidate();
-
5920 params.clear();
-
5921 interval.start = (interval.end = start) + 1;
-
5922 return false;
-
5923 }
-
5924
-
5925 virtual void invalidate()
-
5926 {
-
5927 name.invalidate();
-
5928 value.invalidate();
-
5929 params.clear();
-
5930 parser::invalidate();
-
5931 }
-
5932
-
5933 public:
-
5934 http_token name;
-
5935 http_value value;
-
5936 std::list<http_cookie_parameter> params;
-
5937
-
5938 protected:
-
5939 http_space m_space;
-
5940 };
-
5941
-
5945 class http_agent : public parser
-
5946 {
-
5947 public:
-
5948 virtual bool match(
-
5949 _In_reads_or_z_(end) const char* text,
-
5950 _In_ size_t start = 0,
-
5951 _In_ size_t end = (size_t)-1,
-
5952 _In_ int flags = match_default)
-
5953 {
-
5954 assert(text || start >= end);
-
5955 interval.end = start;
-
5956 type.start = interval.end;
-
5957 for (;;) {
-
5958 if (interval.end < end && text[interval.end]) {
-
5959 if (text[interval.end] == '/') {
-
5960 type.end = interval.end;
-
5961 interval.end++;
-
5962 version.start = interval.end;
-
5963 for (;;) {
-
5964 if (interval.end < end && text[interval.end]) {
-
5965 if (isspace(text[interval.end])) {
-
5966 version.end = interval.end;
-
5967 break;
-
5968 }
-
5969 else
-
5970 interval.end++;
-
5971 }
-
5972 else {
-
5973 version.end = interval.end;
-
5974 break;
-
5975 }
-
5976 }
-
5977 break;
-
5978 }
-
5979 else if (isspace(text[interval.end])) {
-
5980 type.end = interval.end;
-
5981 break;
-
5982 }
-
5983 else
-
5984 interval.end++;
-
5985 }
-
5986 else {
-
5987 type.end = interval.end;
-
5988 break;
-
5989 }
-
5990 }
-
5991 if (start < interval.end) {
-
5992 interval.start = start;
-
5993 return true;
-
5994 }
-
5995 type.start = 1;
-
5996 type.end = 0;
-
5997 version.start = 1;
-
5998 version.end = 0;
-
5999 interval.start = 1;
-
6000 interval.end = 0;
-
6001 return false;
-
6002 }
-
6003
-
6004 virtual void invalidate()
-
6005 {
-
6006 type.start = 1;
-
6007 type.end = 0;
-
6008 version.start = 1;
-
6009 version.end = 0;
-
6010 parser::invalidate();
-
6011 }
-
6012
-
6013 public:
-
6014 stdex::interval<size_t> type;
-
6015 stdex::interval<size_t> version;
-
6016 };
-
6017
-
6021 class http_protocol : public parser
-
6022 {
-
6023 public:
-
6024 http_protocol(_In_ const std::locale& locale = std::locale()) :
-
6025 parser(locale),
-
6026 version(0x009)
-
6027 {}
-
6028
-
6029 virtual bool match(
-
6030 _In_reads_or_z_(end) const char* text,
-
6031 _In_ size_t start = 0,
-
6032 _In_ size_t end = (size_t)-1,
-
6033 _In_ int flags = match_default)
-
6034 {
-
6035 assert(text || start >= end);
-
6036 interval.end = start;
-
6037 type.start = interval.end;
-
6038 for (;;) {
-
6039 if (interval.end < end && text[interval.end]) {
-
6040 if (text[interval.end] == '/') {
-
6041 type.end = interval.end;
-
6042 interval.end++;
-
6043 break;
-
6044 }
-
6045 else if (isspace(text[interval.end]))
-
6046 goto error;
-
6047 else
-
6048 interval.end++;
-
6049 }
-
6050 else {
-
6051 type.end = interval.end;
-
6052 goto error;
-
6053 }
-
6054 }
-
6055 version_maj.start = interval.end;
-
6056 for (;;) {
-
6057 if (interval.end < end && text[interval.end]) {
-
6058 if (text[interval.end] == '.') {
-
6059 version_maj.end = interval.end;
-
6060 interval.end++;
-
6061 version_min.start = interval.end;
-
6062 for (;;) {
-
6063 if (interval.end < end && text[interval.end]) {
-
6064 if (isspace(text[interval.end])) {
-
6065 version_min.end = interval.end;
-
6066 version =
-
6067 (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100 +
-
6068 (uint16_t)strtoui(text + version_min.start, version_min.size(), nullptr, 10);
-
6069 break;
-
6070 }
-
6071 else
-
6072 interval.end++;
-
6073 }
-
6074 else
-
6075 goto error;
-
6076 }
-
6077 break;
-
6078 }
-
6079 else if (isspace(text[interval.end])) {
-
6080 version_maj.end = interval.end;
-
6081 version_min.start = 1;
-
6082 version_min.end = 0;
-
6083 version = (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100;
-
6084 break;
-
6085 }
-
6086 else
-
6087 interval.end++;
-
6088 }
-
6089 else
-
6090 goto error;
-
6091 }
-
6092 interval.start = start;
-
6093 return true;
-
6094
-
6095 error:
-
6096 type.start = 1;
-
6097 type.end = 0;
-
6098 version_maj.start = 1;
-
6099 version_maj.end = 0;
-
6100 version_min.start = 1;
-
6101 version_min.end = 0;
-
6102 version = 0x009;
-
6103 interval.start = 1;
-
6104 interval.end = 0;
-
6105 return false;
-
6106 }
-
6107
-
6108 virtual void invalidate()
-
6109 {
-
6110 type.start = 1;
-
6111 type.end = 0;
-
6112 version_maj.start = 1;
-
6113 version_maj.end = 0;
-
6114 version_min.start = 1;
-
6115 version_min.end = 0;
-
6116 version = 0x009;
-
6117 parser::invalidate();
-
6118 }
-
6119
-
6120 public:
-
6121 stdex::interval<size_t> type;
-
6122 stdex::interval<size_t> version_maj;
-
6123 stdex::interval<size_t> version_min;
-
6124 uint16_t version;
-
6125 };
-
6126
-
6130 class http_request : public parser
-
6131 {
-
6132 public:
-
6133 http_request(_In_ const std::locale& locale = std::locale()) :
-
6134 parser(locale),
-
6135 url(locale),
-
6136 protocol(locale)
-
6137 {}
-
6138
-
6139 virtual bool match(
-
6140 _In_reads_or_z_(end) const char* text,
-
6141 _In_ size_t start = 0,
-
6142 _In_ size_t end = (size_t)-1,
-
6143 _In_ int flags = match_default)
-
6144 {
-
6145 assert(text || start >= end);
-
6146 interval.end = start;
-
6147
-
6148 for (;;) {
-
6149 if (m_line_break.match(text, interval.end, end, flags))
-
6150 goto error;
-
6151 else if (interval.end < end && text[interval.end]) {
-
6152 if (isspace(text[interval.end]))
-
6153 interval.end++;
-
6154 else
-
6155 break;
-
6156 }
-
6157 else
-
6158 goto error;
-
6159 }
-
6160 verb.start = interval.end;
-
6161 for (;;) {
-
6162 if (m_line_break.match(text, interval.end, end, flags))
-
6163 goto error;
-
6164 else if (interval.end < end && text[interval.end]) {
-
6165 if (isspace(text[interval.end])) {
-
6166 verb.end = interval.end;
-
6167 interval.end++;
-
6168 break;
-
6169 }
-
6170 else
-
6171 interval.end++;
-
6172 }
-
6173 else
-
6174 goto error;
-
6175 }
-
6176
-
6177 for (;;) {
-
6178 if (m_line_break.match(text, interval.end, end, flags))
-
6179 goto error;
-
6180 else if (interval.end < end && text[interval.end]) {
-
6181 if (isspace(text[interval.end]))
-
6182 interval.end++;
-
6183 else
-
6184 break;
-
6185 }
-
6186 else
-
6187 goto error;
-
6188 }
-
6189 if (url.match(text, interval.end, end, flags))
-
6190 interval.end = url.interval.end;
-
6191 else
-
6192 goto error;
-
6193
-
6194 protocol.invalidate();
-
6195 for (;;) {
-
6196 if (m_line_break.match(text, interval.end, end, flags)) {
-
6197 interval.end = m_line_break.interval.end;
-
6198 goto end;
-
6199 }
-
6200 else if (interval.end < end && text[interval.end]) {
-
6201 if (isspace(text[interval.end]))
-
6202 interval.end++;
-
6203 else
-
6204 break;
-
6205 }
-
6206 else
-
6207 goto end;
-
6208 }
-
6209 for (;;) {
-
6210 if (m_line_break.match(text, interval.end, end, flags)) {
-
6211 interval.end = m_line_break.interval.end;
-
6212 goto end;
-
6213 }
-
6214 else if (protocol.match(text, interval.end, end, flags)) {
-
6215 interval.end = protocol.interval.end;
-
6216 break;
-
6217 }
-
6218 else
-
6219 goto end;
-
6220 }
-
6221
-
6222 for (;;) {
-
6223 if (m_line_break.match(text, interval.end, end, flags)) {
-
6224 interval.end = m_line_break.interval.end;
-
6225 break;
-
6226 }
-
6227 else if (interval.end < end && text[interval.end])
-
6228 interval.end++;
-
6229 else
-
6230 goto end;
-
6231 }
-
6232
-
6233 end:
-
6234 interval.start = start;
-
6235 return true;
-
6236
-
6237 error:
-
6238 verb.start = 1;
-
6239 verb.end = 0;
-
6240 url.invalidate();
-
6241 protocol.invalidate();
-
6242 interval.start = 1;
-
6243 interval.end = 0;
-
6244 return false;
-
6245 }
-
6246
-
6247 virtual void invalidate()
-
6248 {
-
6249 verb.start = 1;
-
6250 verb.end = 0;
-
6251 url.invalidate();
-
6252 protocol.invalidate();
-
6253 parser::invalidate();
-
6254 }
-
6255
-
6256 public:
-
6257 stdex::interval<size_t> verb;
-
6258 http_url url;
-
6259 http_protocol protocol;
-
6260
-
6261 protected:
-
6262 http_line_break m_line_break;
-
6263 };
-
6264
-
6268 class http_header : public parser
-
6269 {
-
6270 public:
-
6271 virtual bool match(
-
6272 _In_reads_or_z_(end) const char* text,
-
6273 _In_ size_t start = 0,
-
6274 _In_ size_t end = (size_t)-1,
-
6275 _In_ int flags = match_default)
-
6276 {
-
6277 assert(text || start >= end);
-
6278 interval.end = start;
-
6279
-
6280 if (m_line_break.match(text, interval.end, end, flags) ||
-
6281 interval.end < end && text[interval.end] && isspace(text[interval.end]))
-
6282 goto error;
-
6283 name.start = interval.end;
-
6284 for (;;) {
-
6285 if (m_line_break.match(text, interval.end, end, flags))
-
6286 goto error;
-
6287 else if (interval.end < end && text[interval.end]) {
-
6288 if (isspace(text[interval.end])) {
-
6289 name.end = interval.end;
-
6290 interval.end++;
-
6291 for (;;) {
-
6292 if (m_line_break.match(text, interval.end, end, flags))
-
6293 goto error;
-
6294 else if (interval.end < end && text[interval.end]) {
-
6295 if (isspace(text[interval.end]))
-
6296 interval.end++;
-
6297 else
-
6298 break;
-
6299 }
-
6300 else
-
6301 goto error;
-
6302 }
-
6303 if (interval.end < end && text[interval.end] == ':') {
-
6304 interval.end++;
-
6305 break;
-
6306 }
-
6307 else
-
6308 goto error;
-
6309 break;
-
6310 }
-
6311 else if (text[interval.end] == ':') {
-
6312 name.end = interval.end;
-
6313 interval.end++;
-
6314 break;
-
6315 }
-
6316 else
-
6317 interval.end++;
-
6318 }
-
6319 else
-
6320 goto error;
-
6321 }
-
6322 value.start = (size_t)-1;
-
6323 value.end = 0;
-
6324 for (;;) {
-
6325 if (m_line_break.match(text, interval.end, end, flags)) {
-
6326 interval.end = m_line_break.interval.end;
-
6327 if (!m_line_break.match(text, interval.end, end, flags) &&
-
6328 interval.end < end && text[interval.end] && isspace(text[interval.end]))
-
6329 interval.end++;
-
6330 else
-
6331 break;
-
6332 }
-
6333 else if (interval.end < end && text[interval.end]) {
-
6334 if (isspace(text[interval.end]))
-
6335 interval.end++;
-
6336 else {
-
6337 if (value.start == (size_t)-1) value.start = interval.end;
-
6338 value.end = ++interval.end;
-
6339 }
-
6340 }
-
6341 else
-
6342 break;
-
6343 }
-
6344 interval.start = start;
-
6345 return true;
-
6346
-
6347 error:
-
6348 name.start = 1;
-
6349 name.end = 0;
-
6350 value.start = 1;
-
6351 value.end = 0;
-
6352 interval.start = 1;
-
6353 interval.end = 0;
-
6354 return false;
-
6355 }
-
6356
-
6357 virtual void invalidate()
-
6358 {
-
6359 name.start = 1;
-
6360 name.end = 0;
-
6361 value.start = 1;
-
6362 value.end = 0;
-
6363 parser::invalidate();
-
6364 }
-
6365
-
6366 public:
-
6367 stdex::interval<size_t> name;
-
6368 stdex::interval<size_t> value;
-
6369
-
6370 protected:
-
6371 http_line_break m_line_break;
-
6372 };
-
6373
-
6377 template <class T>
-
6378 class http_value_collection : public T
-
6379 {
-
6380 public:
-
6381 void insert(
-
6382 _In_reads_or_z_(end) const char* text,
-
6383 _In_ size_t start = 0,
-
6384 _In_ size_t end = (size_t)-1,
-
6385 _In_ int flags = match_default)
-
6386 {
-
6387 while (start < end) {
-
6388 while (start < end && text[start] && isspace(text[start])) start++;
-
6389 if (start < end && text[start] == ',') {
-
6390 start++;
-
6391 while (start < end&& text[start] && isspace(text[start])) start++;
-
6392 }
-
6393 T::key_type el;
-
6394 if (el.match(text, start, end, flags)) {
-
6395 start = el.interval.end;
-
6396 T::insert(std::move(el));
-
6397 }
-
6398 else
-
6399 break;
-
6400 }
-
6401 }
-
6402 };
-
6403
-
6404 template <class T>
-
6405 struct http_factor_more {
-
6406 constexpr bool operator()(const T& a, const T& b) const noexcept
-
6407 {
-
6408 return a.factor.value > b.factor.value;
-
6409 }
-
6410 };
-
6411
-
6415 template <class T, class _Alloc = std::allocator<T>>
-
6416 using http_weighted_collection = http_value_collection<std::multiset<T, http_factor_more<T>, _Alloc>>;
-
6417
-
6421 template <class T>
-
6422 class basic_json_string : public basic_parser<T>
-
6423 {
-
6424 public:
-
6425 basic_json_string(
-
6426 _In_ const std::shared_ptr<basic_parser<T>>& quote,
-
6427 _In_ const std::shared_ptr<basic_parser<T>>& chr,
-
6428 _In_ const std::shared_ptr<basic_parser<T>>& escape,
-
6429 _In_ const std::shared_ptr<basic_parser<T>>& sol,
-
6430 _In_ const std::shared_ptr<basic_parser<T>>& bs,
-
6431 _In_ const std::shared_ptr<basic_parser<T>>& ff,
-
6432 _In_ const std::shared_ptr<basic_parser<T>>& lf,
-
6433 _In_ const std::shared_ptr<basic_parser<T>>& cr,
-
6434 _In_ const std::shared_ptr<basic_parser<T>>& htab,
-
6435 _In_ const std::shared_ptr<basic_parser<T>>& uni,
-
6436 _In_ const std::shared_ptr<basic_integer16<T>>& hex,
-
6437 _In_ const std::locale& locale = std::locale()) :
-
6438 basic_parser<T>(locale),
-
6439 m_quote(quote),
-
6440 m_chr(chr),
-
6441 m_escape(escape),
-
6442 m_sol(sol),
-
6443 m_bs(bs),
-
6444 m_ff(ff),
-
6445 m_lf(lf),
-
6446 m_cr(cr),
-
6447 m_htab(htab),
-
6448 m_uni(uni),
-
6449 m_hex(hex)
-
6450 {}
-
6451
-
6452 virtual bool match(
-
6453 _In_reads_or_z_(end) const T* text,
-
6454 _In_ size_t start = 0,
-
6455 _In_ size_t end = (size_t)-1,
-
6456 _In_ int flags = match_default)
-
6457 {
-
6458 assert(text || start >= end);
-
6459 interval.end = start;
-
6460 if (m_quote->match(text, interval.end, end, flags)) {
-
6461 interval.end = m_quote->interval.end;
-
6462 value.clear();
-
6463 for (;;) {
-
6464 if (m_quote->match(text, interval.end, end, flags)) {
-
6465 interval.start = start;
-
6466 interval.end = m_quote->interval.end;
-
6467 return true;
-
6468 }
-
6469 if (m_escape->match(text, interval.end, end, flags)) {
-
6470 if (m_quote->match(text, m_escape->interval.end, end, flags)) {
-
6471 value += '"'; interval.end = m_quote->interval.end;
-
6472 continue;
-
6473 }
-
6474 if (m_sol->match(text, m_escape->interval.end, end, flags)) {
-
6475 value += '/'; interval.end = m_sol->interval.end;
-
6476 continue;
-
6477 }
-
6478 if (m_bs->match(text, m_escape->interval.end, end, flags)) {
-
6479 value += '\b'; interval.end = m_bs->interval.end;
-
6480 continue;
-
6481 }
-
6482 if (m_ff->match(text, m_escape->interval.end, end, flags)) {
-
6483 value += '\f'; interval.end = m_ff->interval.end;
-
6484 continue;
-
6485 }
-
6486 if (m_lf->match(text, m_escape->interval.end, end, flags)) {
-
6487 value += '\n'; interval.end = m_lf->interval.end;
-
6488 continue;
-
6489 }
-
6490 if (m_cr->match(text, m_escape->interval.end, end, flags)) {
-
6491 value += '\r'; interval.end = m_cr->interval.end;
-
6492 continue;
-
6493 }
-
6494 if (m_htab->match(text, m_escape->interval.end, end, flags)) {
-
6495 value += '\t'; interval.end = m_htab->interval.end;
-
6496 continue;
-
6497 }
-
6498 if (
-
6499 m_uni->match(text, m_escape->interval.end, end, flags) &&
-
6500 m_hex->match(text, m_uni->interval.end, std::min(m_uni->interval.end + 4, end), flags | match_case_insensitive) &&
-
6501 m_hex->interval.size() == 4 /* JSON requests 4-digit Unicode sequneces: \u.... */)
-
6502 {
-
6503 assert(m_hex->value <= 0xffff);
-
6504 if (sizeof(T) == 1) {
-
6505 if (m_hex->value > 0x7ff) {
-
6506 value += (T)(0xe0 | (m_hex->value >> 12) & 0x0f);
-
6507 value += (T)(0x80 | (m_hex->value >> 6) & 0x3f);
-
6508 value += (T)(0x80 | m_hex->value & 0x3f);
-
6509 }
-
6510 else if (m_hex->value > 0x7f) {
-
6511 value += (T)(0xc0 | (m_hex->value >> 6) & 0x1f);
-
6512 value += (T)(0x80 | m_hex->value & 0x3f);
-
6513 }
-
6514 else
-
6515 value += (T)(m_hex->value & 0x7f);
-
6516 }
-
6517 else
-
6518 value += (T)m_hex->value;
-
6519 interval.end = m_hex->interval.end;
-
6520 continue;
-
6521 }
-
6522 if (m_escape->match(text, m_escape->interval.end, end, flags)) {
-
6523 value += '\\'; interval.end = m_escape->interval.end;
-
6524 continue;
-
6525 }
-
6526 }
-
6527 if (m_chr->match(text, interval.end, end, flags)) {
-
6528 value.Prilepi(text + m_chr->interval.start, m_chr->interval.size());
-
6529 interval.end = m_chr->interval.end;
-
6530 continue;
-
6531 }
-
6532 break;
-
6533 }
-
6534 }
-
6535 value.clear();
-
6536 interval.start = (interval.end = start) + 1;
-
6537 return false;
-
6538 }
-
6539
-
6540 virtual void invalidate()
-
6541 {
-
6542 value.clear();
-
6543 basic_parser<T>::invalidate();
-
6544 }
-
6545
-
6546 public:
-
6547 std::basic_string<T> value;
-
6548
-
6549 protected:
-
6550 std::shared_ptr<basic_parser<T>> m_quote;
-
6551 std::shared_ptr<basic_parser<T>> m_chr;
-
6552 std::shared_ptr<basic_parser<T>> m_escape;
-
6553 std::shared_ptr<basic_parser<T>> m_sol;
-
6554 std::shared_ptr<basic_parser<T>> m_bs;
-
6555 std::shared_ptr<basic_parser<T>> m_ff;
-
6556 std::shared_ptr<basic_parser<T>> m_lf;
-
6557 std::shared_ptr<basic_parser<T>> m_cr;
-
6558 std::shared_ptr<basic_parser<T>> m_htab;
-
6559 std::shared_ptr<basic_parser<T>> m_uni;
-
6560 std::shared_ptr<basic_integer16<T>> m_hex;
-
6561 };
-
6562
-
6563 using json_string = basic_json_string<char>;
-
6564 using wjson_string = basic_json_string<wchar_t>;
-
6565#ifdef _UNICODE
-
6566 using tjson_string = wjson_string;
-
6567#else
-
6568 using tjson_string = json_string;
-
6569#endif
-
6570 }
-
6571}
-
6572
-
6573#undef ENUM_FLAG_OPERATOR
-
6574#undef ENUM_FLAGS
-
6575
-
6576#ifdef _MSC_VER
-
6577#pragma warning(pop)
-
6578#endif
-
stdex::parser::basic_angle
Test for angle in d°mm'ss.dddd form.
Definition parser.hpp:4387
-
stdex::parser::basic_any_cu
Test for any code unit.
Definition parser.hpp:214
-
stdex::parser::basic_bol
Test for beginning of line.
Definition parser.hpp:608
-
stdex::parser::basic_branch
Test for any.
Definition parser.hpp:1050
-
stdex::parser::basic_chemical_formula
Test for chemical formula.
Definition parser.hpp:4661
-
stdex::parser::basic_cu_set
Test for any code unit from a given string of code units.
Definition parser.hpp:713
-
stdex::parser::basic_cu
Test for specific code unit.
Definition parser.hpp:284
-
stdex::parser::basic_date
Test for date.
Definition parser.hpp:4017
-
stdex::parser::basic_dns_domain_char
Test for valid DNS domain character.
Definition parser.hpp:2798
-
stdex::parser::basic_dns_domain_char::allow_on_edge
bool allow_on_edge
Is character allowed at the beginning or an end of a DNS domain?
Definition parser.hpp:2836
-
stdex::parser::basic_dns_name
Test for DNS domain/hostname.
Definition parser.hpp:2898
-
stdex::parser::basic_dns_name::m_allow_absolute
bool m_allow_absolute
May DNS names end with a dot (absolute name)?
Definition parser.hpp:2962
-
stdex::parser::basic_email_address
Test for e-mail address.
Definition parser.hpp:3786
-
stdex::parser::basic_emoticon
Test for emoticon.
Definition parser.hpp:3894
-
stdex::parser::basic_emoticon::apex
std::shared_ptr< basic_parser< T > > apex
apex/eyebrows/halo (e.g. O, 0)
Definition parser.hpp:3983
-
stdex::parser::basic_emoticon::eyes
std::shared_ptr< basic_parser< T > > eyes
eyes (e.g. :, ;, >, |, B)
Definition parser.hpp:3984
-
stdex::parser::basic_emoticon::mouth
std::shared_ptr< basic_set< T > > mouth
mouth (e.g. ), ), (, (, |, P, D, p, d)
Definition parser.hpp:3986
-
stdex::parser::basic_emoticon::nose
std::shared_ptr< basic_parser< T > > nose
nose (e.g. -, o)
Definition parser.hpp:3985
-
stdex::parser::basic_emoticon::emoticon
std::shared_ptr< basic_parser< T > > emoticon
emoticon as a whole (e.g. 😀, 🤔, 😶)
Definition parser.hpp:3982
-
stdex::parser::basic_eol
Test for end of line.
Definition parser.hpp:646
-
stdex::parser::basic_fraction
Test for fraction.
Definition parser.hpp:1679
-
stdex::parser::basic_integer10
Test for decimal integer.
Definition parser.hpp:1288
-
stdex::parser::basic_integer10ts
Test for decimal integer possibly containing thousand separators.
Definition parser.hpp:1373
-
stdex::parser::basic_integer10ts::has_separators
bool has_separators
Did integer have any separators?
Definition parser.hpp:1433
-
stdex::parser::basic_integer10ts::digit_count
size_t digit_count
Total number of digits in integer.
Definition parser.hpp:1432
-
stdex::parser::basic_integer16
Test for hexadecimal integer.
Definition parser.hpp:1454
-
stdex::parser::basic_integer
Base class for integer testing.
Definition parser.hpp:1266
-
stdex::parser::basic_integer::value
size_t value
Calculated value of the numeral.
Definition parser.hpp:1280
-
stdex::parser::basic_ipv4_address
Test for IPv4 address.
Definition parser.hpp:2338
-
stdex::parser::basic_ipv4_address::components
stdex::interval< size_t > components[4]
Individual component intervals.
Definition parser.hpp:2453
-
stdex::parser::basic_ipv4_address::value
struct in_addr value
IPv4 address value.
Definition parser.hpp:2454
-
stdex::parser::basic_ipv6_address
Test for IPv6 address.
Definition parser.hpp:2557
-
stdex::parser::basic_ipv6_address::scope_id
std::shared_ptr< basic_parser< T > > scope_id
Scope ID (e.g. NIC index with link-local addresses)
Definition parser.hpp:2761
-
stdex::parser::basic_ipv6_address::components
stdex::interval< size_t > components[8]
Individual component intervals.
Definition parser.hpp:2759
-
stdex::parser::basic_ipv6_address::value
struct in6_addr value
IPv6 address value.
Definition parser.hpp:2760
-
stdex::parser::basic_ipv6_scope_id_char
Test for valid IPv6 address scope ID character.
Definition parser.hpp:2485
-
stdex::parser::basic_iterations
Test for repeating.
Definition parser.hpp:903
-
stdex::parser::basic_iterations::m_greedy
bool m_greedy
try to match as long sequence as possible
Definition parser.hpp:942
-
stdex::parser::basic_iterations::m_el
std::shared_ptr< basic_parser< T > > m_el
repeating element
Definition parser.hpp:939
-
stdex::parser::basic_iterations::m_min_iterations
size_t m_min_iterations
minimum number of iterations
Definition parser.hpp:940
-
stdex::parser::basic_iterations::m_max_iterations
size_t m_max_iterations
maximum number of iterations
Definition parser.hpp:941
-
stdex::parser::basic_json_string
Test for JSON string.
Definition parser.hpp:6423
-
stdex::parser::basic_mixed_numeral
Test for mixed numeral.
Definition parser.hpp:1914
-
stdex::parser::basic_mixed_numeral::fraction
std::shared_ptr< basic_parser< T > > fraction
fraction
Definition parser.hpp:2020
-
stdex::parser::basic_mixed_numeral::special_sign
std::shared_ptr< basic_parser< T > > special_sign
Special sign (e.g. plus-minus '±')
Definition parser.hpp:2018
-
stdex::parser::basic_mixed_numeral::negative_sign
std::shared_ptr< basic_parser< T > > negative_sign
Negative sign.
Definition parser.hpp:2017
-
stdex::parser::basic_mixed_numeral::positive_sign
std::shared_ptr< basic_parser< T > > positive_sign
Positive sign.
Definition parser.hpp:2016
-
stdex::parser::basic_mixed_numeral::integer
std::shared_ptr< basic_parser< T > > integer
Integer part.
Definition parser.hpp:2019
-
stdex::parser::basic_monetary_numeral
Test for monetary numeral.
Definition parser.hpp:2209
-
stdex::parser::basic_monetary_numeral::positive_sign
std::shared_ptr< basic_parser< T > > positive_sign
Positive sign.
Definition parser.hpp:2315
-
stdex::parser::basic_monetary_numeral::decimal_separator
std::shared_ptr< basic_parser< T > > decimal_separator
Decimal separator.
Definition parser.hpp:2320
-
stdex::parser::basic_monetary_numeral::currency
std::shared_ptr< basic_parser< T > > currency
Currency part.
Definition parser.hpp:2318
-
stdex::parser::basic_monetary_numeral::decimal
std::shared_ptr< basic_parser< T > > decimal
Decimal part.
Definition parser.hpp:2321
-
stdex::parser::basic_monetary_numeral::integer
std::shared_ptr< basic_parser< T > > integer
Integer part.
Definition parser.hpp:2319
-
stdex::parser::basic_monetary_numeral::negative_sign
std::shared_ptr< basic_parser< T > > negative_sign
Negative sign.
Definition parser.hpp:2316
-
stdex::parser::basic_monetary_numeral::special_sign
std::shared_ptr< basic_parser< T > > special_sign
Special sign (e.g. plus-minus '±')
Definition parser.hpp:2317
-
stdex::parser::basic_noop
"No-op" match
Definition parser.hpp:182
-
stdex::parser::basic_parser
Base template for all parsers.
Definition parser.hpp:63
-
stdex::parser::basic_parser::interval
interval< size_t > interval
Region of the last match.
Definition parser.hpp:162
-
stdex::parser::basic_permutation
Test for permutation.
Definition parser.hpp:1190
-
stdex::parser::basic_phone_number
Test for phone number.
Definition parser.hpp:4510
-
stdex::parser::basic_phone_number::value
std::basic_string< T > value
Normalized phone number.
Definition parser.hpp:4636
-
stdex::parser::basic_punct_cu
Test for any punctuation code unit.
Definition parser.hpp:456
-
stdex::parser::basic_roman_numeral
Test for Roman numeral.
Definition parser.hpp:1563
-
stdex::parser::basic_scientific_numeral
Test for scientific numeral.
Definition parser.hpp:2040
-
stdex::parser::basic_scientific_numeral::special_sign
std::shared_ptr< basic_parser< T > > special_sign
Special sign (e.g. plus-minus '±')
Definition parser.hpp:2184
-
stdex::parser::basic_scientific_numeral::exponent_symbol
std::shared_ptr< basic_parser< T > > exponent_symbol
Exponent symbol (e.g. 'e')
Definition parser.hpp:2188
-
stdex::parser::basic_scientific_numeral::positive_sign
std::shared_ptr< basic_parser< T > > positive_sign
Positive sign.
Definition parser.hpp:2182
-
stdex::parser::basic_scientific_numeral::negative_sign
std::shared_ptr< basic_parser< T > > negative_sign
Negative sign.
Definition parser.hpp:2183
-
stdex::parser::basic_scientific_numeral::value
double value
Calculated value of the numeral.
Definition parser.hpp:2192
-
stdex::parser::basic_scientific_numeral::negative_exp_sign
std::shared_ptr< basic_parser< T > > negative_exp_sign
Negative exponent sign (e.g. '-')
Definition parser.hpp:2190
-
stdex::parser::basic_scientific_numeral::decimal
std::shared_ptr< basic_integer< T > > decimal
Decimal part.
Definition parser.hpp:2187
-
stdex::parser::basic_scientific_numeral::positive_exp_sign
std::shared_ptr< basic_parser< T > > positive_exp_sign
Positive exponent sign (e.g. '+')
Definition parser.hpp:2189
-
stdex::parser::basic_scientific_numeral::exponent
std::shared_ptr< basic_integer< T > > exponent
Exponent part.
Definition parser.hpp:2191
-
stdex::parser::basic_scientific_numeral::decimal_separator
std::shared_ptr< basic_parser< T > > decimal_separator
Decimal separator.
Definition parser.hpp:2186
-
stdex::parser::basic_scientific_numeral::integer
std::shared_ptr< basic_integer< T > > integer
Integer part.
Definition parser.hpp:2185
-
stdex::parser::basic_score
Test for match score.
Definition parser.hpp:1742
-
stdex::parser::basic_sequence
Test for sequence.
Definition parser.hpp:999
-
stdex::parser::basic_set
Definition parser.hpp:681
-
stdex::parser::basic_signed_numeral
Test for signed numeral.
Definition parser.hpp:1828
-
stdex::parser::basic_signed_numeral::special_sign
std::shared_ptr< basic_parser< T > > special_sign
Special sign (e.g. plus-minus '±')
Definition parser.hpp:1896
-
stdex::parser::basic_signed_numeral::negative_sign
std::shared_ptr< basic_parser< T > > negative_sign
Negative sign.
Definition parser.hpp:1895
-
stdex::parser::basic_signed_numeral::positive_sign
std::shared_ptr< basic_parser< T > > positive_sign
Positive sign.
Definition parser.hpp:1894
-
stdex::parser::basic_signed_numeral::number
std::shared_ptr< basic_parser< T > > number
Number.
Definition parser.hpp:1897
-
stdex::parser::basic_space_cu
Test for any space code unit.
Definition parser.hpp:377
-
stdex::parser::basic_space_or_punct_cu
Test for any space or punctuation code unit.
Definition parser.hpp:530
-
stdex::parser::basic_string_branch
Test for any string.
Definition parser.hpp:1118
-
stdex::parser::basic_string
Test for given string.
Definition parser.hpp:808
-
stdex::parser::basic_time
Test for time.
Definition parser.hpp:4284
-
stdex::parser::basic_url_password_char
Test for valid URL password character.
Definition parser.hpp:3080
-
stdex::parser::basic_url_path_char
Test for valid URL path character.
Definition parser.hpp:3180
-
stdex::parser::basic_url_path
Test for URL path.
Definition parser.hpp:3288
-
stdex::parser::basic_url_username_char
Test for valid URL username character.
Definition parser.hpp:2981
-
stdex::parser::basic_url
Test for URL.
Definition parser.hpp:3429
-
stdex::parser::http_agent
Test for HTTP agent.
Definition parser.hpp:5946
-
stdex::parser::http_any_type
Test for HTTP any type.
Definition parser.hpp:5068
-
stdex::parser::http_asterisk
Test for HTTP asterisk.
Definition parser.hpp:5710
- - - - - -
stdex::parser::http_header
Test for HTTP header.
Definition parser.hpp:6269
-
stdex::parser::http_language
Test for HTTP language (RFC1766)
Definition parser.hpp:5578
-
stdex::parser::http_line_break
Test for HTTP line break (RFC2616: CRLF | LF)
Definition parser.hpp:4742
-
stdex::parser::http_media_range
Test for HTTP media range (RFC2616: media-range)
Definition parser.hpp:5100
-
stdex::parser::http_media_type
Test for HTTP media type (RFC2616: media-type)
Definition parser.hpp:5155
-
stdex::parser::http_parameter
Test for HTTP parameter (RFC2616: parameter)
Definition parser.hpp:5013
-
stdex::parser::http_parameter::name
http_token name
Parameter name.
Definition parser.hpp:5057
-
stdex::parser::http_parameter::value
http_value value
Parameter value.
Definition parser.hpp:5058
-
stdex::parser::http_protocol
Test for HTTP protocol.
Definition parser.hpp:6022
-
stdex::parser::http_protocol::version
uint16_t version
HTTP protocol version: 0x100 = 1.0, 0x101 = 1.1...
Definition parser.hpp:6124
-
stdex::parser::http_quoted_string
Test for HTTP quoted string (RFC2616: quoted-string)
Definition parser.hpp:4903
-
stdex::parser::http_quoted_string::content
stdex::interval< size_t > content
String content (without quotes)
Definition parser.hpp:4959
-
stdex::parser::http_request
Test for HTTP request.
Definition parser.hpp:6131
-
stdex::parser::http_space
Test for HTTP space (RFC2616: LWS)
Definition parser.hpp:4778
-
stdex::parser::http_text_char
Test for HTTP text character (RFC2616: TEXT)
Definition parser.hpp:4815
-
stdex::parser::http_token
Test for HTTP token (RFC2616: token - tolerates non-ASCII)
Definition parser.hpp:4849
-
stdex::parser::http_url_parameter
Test for HTTP URL parameter.
Definition parser.hpp:5395
-
stdex::parser::http_url_path_segment
Test for HTTP URL path segment.
Definition parser.hpp:5306
-
stdex::parser::http_url_path
Test for HTTP URL path segment.
Definition parser.hpp:5339
-
stdex::parser::http_url_path::segments
std::vector< http_url_path_segment > segments
Path segments.
Definition parser.hpp:5388
-
stdex::parser::http_url_port
Test for HTTP URL port.
Definition parser.hpp:5250
-
stdex::parser::http_url_server
Test for HTTP URL server.
Definition parser.hpp:5213
-
stdex::parser::http_url
Test for HTTP URL.
Definition parser.hpp:5476
-
stdex::parser::http_value_collection
Collection of HTTP values.
Definition parser.hpp:6379
-
stdex::parser::http_value
Test for HTTP value (RFC2616: value)
Definition parser.hpp:4969
-
stdex::parser::http_value::string
http_quoted_string string
Value when matched as quoted string.
Definition parser.hpp:5005
-
stdex::parser::http_value::token
http_token token
Value when matched as token.
Definition parser.hpp:5006
-
stdex::parser::http_weight
Test for HTTP weight factor.
Definition parser.hpp:5641
-
stdex::parser::http_weight::value
float value
Calculated value of the weight factor.
Definition parser.hpp:5703
-
stdex::parser::http_weighted_value
Test for HTTP weighted value.
Definition parser.hpp:5733
-
stdex::parser::parser_collection
Base template for collection-holding parsers.
Definition parser.hpp:959
-
stdex::parser::sgml_any_cp
Test for any SGML code point.
Definition parser.hpp:246
-
stdex::parser::sgml_cp_set
Test for any SGML code point from a given string of SGML code points.
Definition parser.hpp:765
-
stdex::parser::sgml_cp
Test for specific SGML code point.
Definition parser.hpp:333
-
stdex::parser::sgml_dns_domain_char
Test for valid DNS domain SGML character.
Definition parser.hpp:2854
-
stdex::parser::sgml_ipv6_scope_id_char
Test for valid IPv6 address scope ID SGML character.
Definition parser.hpp:2523
-
stdex::parser::sgml_punct_cp
Test for any SGML punctuation code point.
Definition parser.hpp:497
-
stdex::parser::sgml_space_cp
Test for any SGML space code point.
Definition parser.hpp:420
-
stdex::parser::sgml_space_or_punct_cp
Test for any SGML space or punctuation code point.
Definition parser.hpp:573
-
stdex::parser::sgml_string
Test for SGML given string.
Definition parser.hpp:855
-
stdex::parser::sgml_url_password_char
Test for valid URL password SGML character.
Definition parser.hpp:3132
-
stdex::parser::sgml_url_path_char
Test for valid URL path SGML character.
Definition parser.hpp:3236
-
stdex::parser::sgml_url_username_char
Test for valid URL username SGML character.
Definition parser.hpp:3032
+
5521 params.clear();
+
5522
+
5523 if (interval.end < end && text[interval.end] == '?') {
+
5524 interval.end++;
+
5525 for (;;) {
+
5526 if (interval.end < end && text[interval.end]) {
+
5527 if ((unsigned int)text[interval.end] < 0x20 ||
+
5528 (unsigned int)text[interval.end] == 0x7f ||
+
5529 isspace(text[interval.end]))
+
5530 break;
+
5531 else if (text[interval.end] == '&')
+
5532 interval.end++;
+
5533 else {
+
5534 http_url_parameter param;
+
5535 if (param.match(text, interval.end, end, flags)) {
+
5536 interval.end = param.interval.end;
+
5537 params.push_back(std::move(param));
+
5538 }
+
5539 else
+
5540 break;
+
5541 }
+
5542 }
+
5543 else
+
5544 break;
+
5545 }
+
5546 }
+
5547
+
5548 interval.start = start;
+
5549 return true;
+
5550
+
5551 error:
+
5552 server.invalidate();
+
5553 port.invalidate();
+
5554 path.invalidate();
+
5555 params.clear();
+
5556 interval.start = (interval.end = start) + 1;
+
5557 return false;
+
5558 }
+
5559
+
5560 virtual void invalidate()
+
5561 {
+
5562 server.invalidate();
+
5563 port.invalidate();
+
5564 path.invalidate();
+
5565 params.clear();
+
5566 parser::invalidate();
+
5567 }
+
5568
+
5569 public:
+
5570 http_url_server server;
+
5571 http_url_port port;
+
5572 http_url_path path;
+
5573 std::list<http_url_parameter> params;
+
5574 };
+
5575
+
5579 class http_language : public parser
+
5580 {
+
5581 public:
+
5582 virtual bool match(
+
5583 _In_reads_or_z_(end) const char* text,
+
5584 _In_ size_t start = 0,
+
5585 _In_ size_t end = (size_t)-1,
+
5586 _In_ int flags = match_default)
+
5587 {
+
5588 assert(text || start >= end);
+
5589 interval.end = start;
+
5590 components.clear();
+
5591 for (;;) {
+
5592 if (interval.end < end && text[interval.end]) {
+
5593 stdex::interval<size_t> k;
+
5594 k.end = interval.end;
+
5595 for (;;) {
+
5596 if (k.end < end && text[k.end]) {
+
5597 if (isalpha(text[k.end]))
+
5598 k.end++;
+
5599 else
+
5600 break;
+
5601 }
+
5602 else
+
5603 break;
+
5604 }
+
5605 if (interval.end < k.end) {
+
5606 k.start = interval.end;
+
5607 interval.end = k.end;
+
5608 components.push_back(k);
+
5609 }
+
5610 else
+
5611 break;
+
5612 if (interval.end < end && text[interval.end] == '-')
+
5613 interval.end++;
+
5614 else
+
5615 break;
+
5616 }
+
5617 else
+
5618 break;
+
5619 }
+
5620 if (!components.empty()) {
+
5621 interval.start = start;
+
5622 interval.end = components.back().end;
+
5623 return true;
+
5624 }
+
5625 interval.start = (interval.end = start) + 1;
+
5626 return false;
+
5627 }
+
5628
+
5629 virtual void invalidate()
+
5630 {
+
5631 components.clear();
+
5632 parser::invalidate();
+
5633 }
+
5634
+
5635 public:
+
5636 std::vector<stdex::interval<size_t>> components;
+
5637 };
+
5638
+
5642 class http_weight : public parser
+
5643 {
+
5644 public:
+
5645 http_weight(_In_ const std::locale& locale = std::locale()) :
+
5646 parser(locale),
+
5647 value(1.0f)
+
5648 {}
+
5649
+
5650 virtual bool match(
+
5651 _In_reads_or_z_(end) const char* text,
+
5652 _In_ size_t start = 0,
+
5653 _In_ size_t end = (size_t)-1,
+
5654 _In_ int flags = match_default)
+
5655 {
+
5656 assert(text || start >= end);
+
5657 size_t celi_del = 0, decimalni_del = 0, decimalni_del_n = 1;
+
5658 interval.end = start;
+
5659 for (;;) {
+
5660 if (interval.end < end && text[interval.end]) {
+
5661 if ('0' <= text[interval.end] && text[interval.end] <= '9') {
+
5662 celi_del = celi_del * 10 + text[interval.end] - '0';
+
5663 interval.end++;
+
5664 }
+
5665 else if (text[interval.end] == '.') {
+
5666 interval.end++;
+
5667 for (;;) {
+
5668 if (interval.end < end && text[interval.end]) {
+
5669 if ('0' <= text[interval.end] && text[interval.end] <= '9') {
+
5670 decimalni_del = decimalni_del * 10 + text[interval.end] - '0';
+
5671 decimalni_del_n *= 10;
+
5672 interval.end++;
+
5673 }
+
5674 else
+
5675 break;
+
5676 }
+
5677 else
+
5678 break;
+
5679 }
+
5680 break;
+
5681 }
+
5682 else
+
5683 break;
+
5684 }
+
5685 else
+
5686 break;
+
5687 }
+
5688 if (start < interval.end) {
+
5689 value = (float)((double)celi_del + (double)decimalni_del / decimalni_del_n);
+
5690 interval.start = start;
+
5691 return true;
+
5692 }
+
5693 value = 1.0f;
+
5694 interval.start = (interval.end = start) + 1;
+
5695 return false;
+
5696 }
+
5697
+
5698 virtual void invalidate()
+
5699 {
+
5700 value = 1.0f;
+
5701 parser::invalidate();
+
5702 }
+
5703
+
5704 public:
+
5705 float value;
+
5706 };
+
5707
+
5711 class http_asterisk : public parser
+
5712 {
+
5713 public:
+
5714 virtual bool match(
+
5715 _In_reads_or_z_(end) const char* text,
+
5716 _In_ size_t start = 0,
+
5717 _In_ size_t end = (size_t)-1,
+
5718 _In_ int flags = match_default)
+
5719 {
+
5720 assert(text || end <= start);
+
5721 if (start < end && text[start] == '*') {
+
5722 interval.end = (interval.start = start) + 1;
+
5723 return true;
+
5724 }
+
5725 interval.start = (interval.end = start) + 1;
+
5726 return false;
+
5727 }
+
5728 };
+
5729
+
5733 template <class T, class T_asterisk = http_asterisk>
+
5734 class http_weighted_value : public parser
+
5735 {
+
5736 public:
+
5737 http_weighted_value(_In_ const std::locale& locale = std::locale()) :
+
5738 parser(locale),
+
5739 factor(locale)
+
5740 {}
+
5741
+
5742 virtual bool match(
+
5743 _In_reads_or_z_(end) const char* text,
+
5744 _In_ size_t start = 0,
+
5745 _In_ size_t end = (size_t)-1,
+
5746 _In_ int flags = match_default)
+
5747 {
+
5748 assert(text || start >= end);
+
5749 size_t konec_vrednosti;
+
5750 interval.end = start;
+
5751 if (asterisk.match(text, interval.end, end, flags)) {
+
5752 interval.end = konec_vrednosti = asterisk.interval.end;
+
5753 value.invalidate();
+
5754 }
+
5755 else if (value.match(text, interval.end, end, flags)) {
+
5756 interval.end = konec_vrednosti = value.interval.end;
+
5757 asterisk.invalidate();
+
5758 }
+
5759 else {
+
5760 asterisk.invalidate();
+
5761 value.invalidate();
+
5762 interval.start = (interval.end = start) + 1;
+
5763 return false;
+
5764 }
+
5765
+
5766 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
+
5767 if (interval.end < end && text[interval.end] == ';') {
+
5768 interval.end++;
+
5769 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
+
5770 if (interval.end < end && (text[interval.end] == 'q' || text[interval.end] == 'Q')) {
+
5771 interval.end++;
+
5772 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
+
5773 if (interval.end < end && text[interval.end] == '=') {
+
5774 interval.end++;
+
5775 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
+
5776 if (factor.match(text, interval.end, end, flags))
+
5777 interval.end = factor.interval.end;
+
5778 }
+
5779 }
+
5780 }
+
5781 if (!factor.interval) {
+
5782 factor.invalidate();
+
5783 interval.end = konec_vrednosti;
+
5784 }
+
5785 interval.start = start;
+
5786 return true;
+
5787 }
+
5788
+
5789 virtual void invalidate()
+
5790 {
+
5791 asterisk.invalidate();
+
5792 value.invalidate();
+
5793 factor.invalidate();
+
5794 parser::invalidate();
+
5795 }
+
5796
+
5797 public:
+
5798 T_asterisk asterisk;
+
5799 T value;
+
5800 http_weight factor;
+
5801 };
+
5802
+
5806 class http_cookie_parameter : public parser
+
5807 {
+
5808 public:
+
5809 virtual bool match(
+
5810 _In_reads_or_z_(end) const char* text,
+
5811 _In_ size_t start = 0,
+
5812 _In_ size_t end = (size_t)-1,
+
5813 _In_ int flags = match_default)
+
5814 {
+
5815 assert(text || start >= end);
+
5816 interval.end = start;
+
5817 if (interval.end < end && text[interval.end] == '$')
+
5818 interval.end++;
+
5819 else
+
5820 goto error;
+
5821 if (name.match(text, interval.end, end, flags))
+
5822 interval.end = name.interval.end;
+
5823 else
+
5824 goto error;
+
5825 while (m_space.match(text, interval.end, end, flags))
+
5826 interval.end = m_space.interval.end;
+
5827 if (interval.end < end && text[interval.end] == '=')
+
5828 interval.end++;
+
5829 else
+
5830 goto error;
+
5831 while (m_space.match(text, interval.end, end, flags))
+
5832 interval.end = m_space.interval.end;
+
5833 if (value.match(text, interval.end, end, flags))
+
5834 interval.end = value.interval.end;
+
5835 else
+
5836 goto error;
+
5837 interval.start = start;
+
5838 return true;
+
5839
+
5840 error:
+
5841 name.invalidate();
+
5842 value.invalidate();
+
5843 interval.start = (interval.end = start) + 1;
+
5844 return false;
+
5845 }
+
5846
+
5847 virtual void invalidate()
+
5848 {
+
5849 name.invalidate();
+
5850 value.invalidate();
+
5851 parser::invalidate();
+
5852 }
+
5853
+
5854 public:
+
5855 http_token name;
+
5856 http_value value;
+
5857
+
5858 protected:
+
5859 http_space m_space;
+
5860 };
+
5861
+
5865 class http_cookie : public parser
+
5866 {
+
5867 public:
+
5868 virtual bool match(
+
5869 _In_reads_or_z_(end) const char* text,
+
5870 _In_ size_t start = 0,
+
5871 _In_ size_t end = (size_t)-1,
+
5872 _In_ int flags = match_default)
+
5873 {
+
5874 assert(text || start >= end);
+
5875 interval.end = start;
+
5876 if (name.match(text, interval.end, end, flags))
+
5877 interval.end = name.interval.end;
+
5878 else
+
5879 goto error;
+
5880 while (m_space.match(text, interval.end, end, flags))
+
5881 interval.end = m_space.interval.end;
+
5882 if (interval.end < end && text[interval.end] == '=')
+
5883 interval.end++;
+
5884 else
+
5885 goto error;
+
5886 while (m_space.match(text, interval.end, end, flags))
+
5887 interval.end = m_space.interval.end;
+
5888 if (value.match(text, interval.end, end, flags))
+
5889 interval.end = value.interval.end;
+
5890 else
+
5891 goto error;
+
5892 params.clear();
+
5893 for (;;) {
+
5894 if (interval.end < end && text[interval.end]) {
+
5895 if (m_space.match(text, interval.end, end, flags))
+
5896 interval.end = m_space.interval.end;
+
5897 else if (text[interval.end] == ';') {
+
5898 interval.end++;
+
5899 while (m_space.match(text, interval.end, end, flags))
+
5900 interval.end = m_space.interval.end;
+
5901 http_cookie_parameter param;
+
5902 if (param.match(text, interval.end, end, flags)) {
+
5903 interval.end = param.interval.end;
+
5904 params.push_back(std::move(param));
+
5905 }
+
5906 else
+
5907 break;
+
5908 }
+
5909 else
+
5910 break;
+
5911 }
+
5912 else
+
5913 break;
+
5914 }
+
5915 interval.start = start;
+
5916 interval.end = params.empty() ? value.interval.end : params.back().interval.end;
+
5917 return true;
+
5918
+
5919 error:
+
5920 name.invalidate();
+
5921 value.invalidate();
+
5922 params.clear();
+
5923 interval.start = (interval.end = start) + 1;
+
5924 return false;
+
5925 }
+
5926
+
5927 virtual void invalidate()
+
5928 {
+
5929 name.invalidate();
+
5930 value.invalidate();
+
5931 params.clear();
+
5932 parser::invalidate();
+
5933 }
+
5934
+
5935 public:
+
5936 http_token name;
+
5937 http_value value;
+
5938 std::list<http_cookie_parameter> params;
+
5939
+
5940 protected:
+
5941 http_space m_space;
+
5942 };
+
5943
+
5947 class http_agent : public parser
+
5948 {
+
5949 public:
+
5950 virtual bool match(
+
5951 _In_reads_or_z_(end) const char* text,
+
5952 _In_ size_t start = 0,
+
5953 _In_ size_t end = (size_t)-1,
+
5954 _In_ int flags = match_default)
+
5955 {
+
5956 assert(text || start >= end);
+
5957 interval.end = start;
+
5958 type.start = interval.end;
+
5959 for (;;) {
+
5960 if (interval.end < end && text[interval.end]) {
+
5961 if (text[interval.end] == '/') {
+
5962 type.end = interval.end;
+
5963 interval.end++;
+
5964 version.start = interval.end;
+
5965 for (;;) {
+
5966 if (interval.end < end && text[interval.end]) {
+
5967 if (isspace(text[interval.end])) {
+
5968 version.end = interval.end;
+
5969 break;
+
5970 }
+
5971 else
+
5972 interval.end++;
+
5973 }
+
5974 else {
+
5975 version.end = interval.end;
+
5976 break;
+
5977 }
+
5978 }
+
5979 break;
+
5980 }
+
5981 else if (isspace(text[interval.end])) {
+
5982 type.end = interval.end;
+
5983 break;
+
5984 }
+
5985 else
+
5986 interval.end++;
+
5987 }
+
5988 else {
+
5989 type.end = interval.end;
+
5990 break;
+
5991 }
+
5992 }
+
5993 if (start < interval.end) {
+
5994 interval.start = start;
+
5995 return true;
+
5996 }
+
5997 type.start = 1;
+
5998 type.end = 0;
+
5999 version.start = 1;
+
6000 version.end = 0;
+
6001 interval.start = 1;
+
6002 interval.end = 0;
+
6003 return false;
+
6004 }
+
6005
+
6006 virtual void invalidate()
+
6007 {
+
6008 type.start = 1;
+
6009 type.end = 0;
+
6010 version.start = 1;
+
6011 version.end = 0;
+
6012 parser::invalidate();
+
6013 }
+
6014
+
6015 public:
+
6016 stdex::interval<size_t> type;
+
6017 stdex::interval<size_t> version;
+
6018 };
+
6019
+
6023 class http_protocol : public parser
+
6024 {
+
6025 public:
+
6026 http_protocol(_In_ const std::locale& locale = std::locale()) :
+
6027 parser(locale),
+
6028 version(0x009)
+
6029 {}
+
6030
+
6031 virtual bool match(
+
6032 _In_reads_or_z_(end) const char* text,
+
6033 _In_ size_t start = 0,
+
6034 _In_ size_t end = (size_t)-1,
+
6035 _In_ int flags = match_default)
+
6036 {
+
6037 assert(text || start >= end);
+
6038 interval.end = start;
+
6039 type.start = interval.end;
+
6040 for (;;) {
+
6041 if (interval.end < end && text[interval.end]) {
+
6042 if (text[interval.end] == '/') {
+
6043 type.end = interval.end;
+
6044 interval.end++;
+
6045 break;
+
6046 }
+
6047 else if (isspace(text[interval.end]))
+
6048 goto error;
+
6049 else
+
6050 interval.end++;
+
6051 }
+
6052 else {
+
6053 type.end = interval.end;
+
6054 goto error;
+
6055 }
+
6056 }
+
6057 version_maj.start = interval.end;
+
6058 for (;;) {
+
6059 if (interval.end < end && text[interval.end]) {
+
6060 if (text[interval.end] == '.') {
+
6061 version_maj.end = interval.end;
+
6062 interval.end++;
+
6063 version_min.start = interval.end;
+
6064 for (;;) {
+
6065 if (interval.end < end && text[interval.end]) {
+
6066 if (isspace(text[interval.end])) {
+
6067 version_min.end = interval.end;
+
6068 version =
+
6069 (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100 +
+
6070 (uint16_t)strtoui(text + version_min.start, version_min.size(), nullptr, 10);
+
6071 break;
+
6072 }
+
6073 else
+
6074 interval.end++;
+
6075 }
+
6076 else
+
6077 goto error;
+
6078 }
+
6079 break;
+
6080 }
+
6081 else if (isspace(text[interval.end])) {
+
6082 version_maj.end = interval.end;
+
6083 version_min.start = 1;
+
6084 version_min.end = 0;
+
6085 version = (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100;
+
6086 break;
+
6087 }
+
6088 else
+
6089 interval.end++;
+
6090 }
+
6091 else
+
6092 goto error;
+
6093 }
+
6094 interval.start = start;
+
6095 return true;
+
6096
+
6097 error:
+
6098 type.start = 1;
+
6099 type.end = 0;
+
6100 version_maj.start = 1;
+
6101 version_maj.end = 0;
+
6102 version_min.start = 1;
+
6103 version_min.end = 0;
+
6104 version = 0x009;
+
6105 interval.start = 1;
+
6106 interval.end = 0;
+
6107 return false;
+
6108 }
+
6109
+
6110 virtual void invalidate()
+
6111 {
+
6112 type.start = 1;
+
6113 type.end = 0;
+
6114 version_maj.start = 1;
+
6115 version_maj.end = 0;
+
6116 version_min.start = 1;
+
6117 version_min.end = 0;
+
6118 version = 0x009;
+
6119 parser::invalidate();
+
6120 }
+
6121
+
6122 public:
+
6123 stdex::interval<size_t> type;
+
6124 stdex::interval<size_t> version_maj;
+
6125 stdex::interval<size_t> version_min;
+
6126 uint16_t version;
+
6127 };
+
6128
+
6132 class http_request : public parser
+
6133 {
+
6134 public:
+
6135 http_request(_In_ const std::locale& locale = std::locale()) :
+
6136 parser(locale),
+
6137 url(locale),
+
6138 protocol(locale)
+
6139 {}
+
6140
+
6141 virtual bool match(
+
6142 _In_reads_or_z_(end) const char* text,
+
6143 _In_ size_t start = 0,
+
6144 _In_ size_t end = (size_t)-1,
+
6145 _In_ int flags = match_default)
+
6146 {
+
6147 assert(text || start >= end);
+
6148 interval.end = start;
+
6149
+
6150 for (;;) {
+
6151 if (m_line_break.match(text, interval.end, end, flags))
+
6152 goto error;
+
6153 else if (interval.end < end && text[interval.end]) {
+
6154 if (isspace(text[interval.end]))
+
6155 interval.end++;
+
6156 else
+
6157 break;
+
6158 }
+
6159 else
+
6160 goto error;
+
6161 }
+
6162 verb.start = interval.end;
+
6163 for (;;) {
+
6164 if (m_line_break.match(text, interval.end, end, flags))
+
6165 goto error;
+
6166 else if (interval.end < end && text[interval.end]) {
+
6167 if (isspace(text[interval.end])) {
+
6168 verb.end = interval.end;
+
6169 interval.end++;
+
6170 break;
+
6171 }
+
6172 else
+
6173 interval.end++;
+
6174 }
+
6175 else
+
6176 goto error;
+
6177 }
+
6178
+
6179 for (;;) {
+
6180 if (m_line_break.match(text, interval.end, end, flags))
+
6181 goto error;
+
6182 else if (interval.end < end && text[interval.end]) {
+
6183 if (isspace(text[interval.end]))
+
6184 interval.end++;
+
6185 else
+
6186 break;
+
6187 }
+
6188 else
+
6189 goto error;
+
6190 }
+
6191 if (url.match(text, interval.end, end, flags))
+
6192 interval.end = url.interval.end;
+
6193 else
+
6194 goto error;
+
6195
+
6196 protocol.invalidate();
+
6197 for (;;) {
+
6198 if (m_line_break.match(text, interval.end, end, flags)) {
+
6199 interval.end = m_line_break.interval.end;
+
6200 goto end;
+
6201 }
+
6202 else if (interval.end < end && text[interval.end]) {
+
6203 if (isspace(text[interval.end]))
+
6204 interval.end++;
+
6205 else
+
6206 break;
+
6207 }
+
6208 else
+
6209 goto end;
+
6210 }
+
6211 for (;;) {
+
6212 if (m_line_break.match(text, interval.end, end, flags)) {
+
6213 interval.end = m_line_break.interval.end;
+
6214 goto end;
+
6215 }
+
6216 else if (protocol.match(text, interval.end, end, flags)) {
+
6217 interval.end = protocol.interval.end;
+
6218 break;
+
6219 }
+
6220 else
+
6221 goto end;
+
6222 }
+
6223
+
6224 for (;;) {
+
6225 if (m_line_break.match(text, interval.end, end, flags)) {
+
6226 interval.end = m_line_break.interval.end;
+
6227 break;
+
6228 }
+
6229 else if (interval.end < end && text[interval.end])
+
6230 interval.end++;
+
6231 else
+
6232 goto end;
+
6233 }
+
6234
+
6235 end:
+
6236 interval.start = start;
+
6237 return true;
+
6238
+
6239 error:
+
6240 verb.start = 1;
+
6241 verb.end = 0;
+
6242 url.invalidate();
+
6243 protocol.invalidate();
+
6244 interval.start = 1;
+
6245 interval.end = 0;
+
6246 return false;
+
6247 }
+
6248
+
6249 virtual void invalidate()
+
6250 {
+
6251 verb.start = 1;
+
6252 verb.end = 0;
+
6253 url.invalidate();
+
6254 protocol.invalidate();
+
6255 parser::invalidate();
+
6256 }
+
6257
+
6258 public:
+
6259 stdex::interval<size_t> verb;
+
6260 http_url url;
+
6261 http_protocol protocol;
+
6262
+
6263 protected:
+
6264 http_line_break m_line_break;
+
6265 };
+
6266
+
6270 class http_header : public parser
+
6271 {
+
6272 public:
+
6273 virtual bool match(
+
6274 _In_reads_or_z_(end) const char* text,
+
6275 _In_ size_t start = 0,
+
6276 _In_ size_t end = (size_t)-1,
+
6277 _In_ int flags = match_default)
+
6278 {
+
6279 assert(text || start >= end);
+
6280 interval.end = start;
+
6281
+
6282 if (m_line_break.match(text, interval.end, end, flags) ||
+
6283 interval.end < end && text[interval.end] && isspace(text[interval.end]))
+
6284 goto error;
+
6285 name.start = interval.end;
+
6286 for (;;) {
+
6287 if (m_line_break.match(text, interval.end, end, flags))
+
6288 goto error;
+
6289 else if (interval.end < end && text[interval.end]) {
+
6290 if (isspace(text[interval.end])) {
+
6291 name.end = interval.end;
+
6292 interval.end++;
+
6293 for (;;) {
+
6294 if (m_line_break.match(text, interval.end, end, flags))
+
6295 goto error;
+
6296 else if (interval.end < end && text[interval.end]) {
+
6297 if (isspace(text[interval.end]))
+
6298 interval.end++;
+
6299 else
+
6300 break;
+
6301 }
+
6302 else
+
6303 goto error;
+
6304 }
+
6305 if (interval.end < end && text[interval.end] == ':') {
+
6306 interval.end++;
+
6307 break;
+
6308 }
+
6309 else
+
6310 goto error;
+
6311 break;
+
6312 }
+
6313 else if (text[interval.end] == ':') {
+
6314 name.end = interval.end;
+
6315 interval.end++;
+
6316 break;
+
6317 }
+
6318 else
+
6319 interval.end++;
+
6320 }
+
6321 else
+
6322 goto error;
+
6323 }
+
6324 value.start = (size_t)-1;
+
6325 value.end = 0;
+
6326 for (;;) {
+
6327 if (m_line_break.match(text, interval.end, end, flags)) {
+
6328 interval.end = m_line_break.interval.end;
+
6329 if (!m_line_break.match(text, interval.end, end, flags) &&
+
6330 interval.end < end && text[interval.end] && isspace(text[interval.end]))
+
6331 interval.end++;
+
6332 else
+
6333 break;
+
6334 }
+
6335 else if (interval.end < end && text[interval.end]) {
+
6336 if (isspace(text[interval.end]))
+
6337 interval.end++;
+
6338 else {
+
6339 if (value.start == (size_t)-1) value.start = interval.end;
+
6340 value.end = ++interval.end;
+
6341 }
+
6342 }
+
6343 else
+
6344 break;
+
6345 }
+
6346 interval.start = start;
+
6347 return true;
+
6348
+
6349 error:
+
6350 name.start = 1;
+
6351 name.end = 0;
+
6352 value.start = 1;
+
6353 value.end = 0;
+
6354 interval.start = 1;
+
6355 interval.end = 0;
+
6356 return false;
+
6357 }
+
6358
+
6359 virtual void invalidate()
+
6360 {
+
6361 name.start = 1;
+
6362 name.end = 0;
+
6363 value.start = 1;
+
6364 value.end = 0;
+
6365 parser::invalidate();
+
6366 }
+
6367
+
6368 public:
+
6369 stdex::interval<size_t> name;
+
6370 stdex::interval<size_t> value;
+
6371
+
6372 protected:
+
6373 http_line_break m_line_break;
+
6374 };
+
6375
+
6379 template <class T>
+
6380 class http_value_collection : public T
+
6381 {
+
6382 public:
+
6383 void insert(
+
6384 _In_reads_or_z_(end) const char* text,
+
6385 _In_ size_t start = 0,
+
6386 _In_ size_t end = (size_t)-1,
+
6387 _In_ int flags = match_default)
+
6388 {
+
6389 while (start < end) {
+
6390 while (start < end && text[start] && isspace(text[start])) start++;
+
6391 if (start < end && text[start] == ',') {
+
6392 start++;
+
6393 while (start < end&& text[start] && isspace(text[start])) start++;
+
6394 }
+
6395 T::key_type el;
+
6396 if (el.match(text, start, end, flags)) {
+
6397 start = el.interval.end;
+
6398 T::insert(std::move(el));
+
6399 }
+
6400 else
+
6401 break;
+
6402 }
+
6403 }
+
6404 };
+
6405
+
6406 template <class T>
+
6407 struct http_factor_more {
+
6408 constexpr bool operator()(const T& a, const T& b) const noexcept
+
6409 {
+
6410 return a.factor.value > b.factor.value;
+
6411 }
+
6412 };
+
6413
+
6417 template <class T, class _Alloc = std::allocator<T>>
+
6418 using http_weighted_collection = http_value_collection<std::multiset<T, http_factor_more<T>, _Alloc>>;
+
6419
+
6423 template <class T>
+
6424 class basic_json_string : public basic_parser<T>
+
6425 {
+
6426 public:
+
6427 basic_json_string(
+
6428 _In_ const std::shared_ptr<basic_parser<T>>& quote,
+
6429 _In_ const std::shared_ptr<basic_parser<T>>& chr,
+
6430 _In_ const std::shared_ptr<basic_parser<T>>& escape,
+
6431 _In_ const std::shared_ptr<basic_parser<T>>& sol,
+
6432 _In_ const std::shared_ptr<basic_parser<T>>& bs,
+
6433 _In_ const std::shared_ptr<basic_parser<T>>& ff,
+
6434 _In_ const std::shared_ptr<basic_parser<T>>& lf,
+
6435 _In_ const std::shared_ptr<basic_parser<T>>& cr,
+
6436 _In_ const std::shared_ptr<basic_parser<T>>& htab,
+
6437 _In_ const std::shared_ptr<basic_parser<T>>& uni,
+
6438 _In_ const std::shared_ptr<basic_integer16<T>>& hex,
+
6439 _In_ const std::locale& locale = std::locale()) :
+
6440 basic_parser<T>(locale),
+
6441 m_quote(quote),
+
6442 m_chr(chr),
+
6443 m_escape(escape),
+
6444 m_sol(sol),
+
6445 m_bs(bs),
+
6446 m_ff(ff),
+
6447 m_lf(lf),
+
6448 m_cr(cr),
+
6449 m_htab(htab),
+
6450 m_uni(uni),
+
6451 m_hex(hex)
+
6452 {}
+
6453
+
6454 virtual bool match(
+
6455 _In_reads_or_z_(end) const T* text,
+
6456 _In_ size_t start = 0,
+
6457 _In_ size_t end = (size_t)-1,
+
6458 _In_ int flags = match_default)
+
6459 {
+
6460 assert(text || start >= end);
+
6461 interval.end = start;
+
6462 if (m_quote->match(text, interval.end, end, flags)) {
+
6463 interval.end = m_quote->interval.end;
+
6464 value.clear();
+
6465 for (;;) {
+
6466 if (m_quote->match(text, interval.end, end, flags)) {
+
6467 interval.start = start;
+
6468 interval.end = m_quote->interval.end;
+
6469 return true;
+
6470 }
+
6471 if (m_escape->match(text, interval.end, end, flags)) {
+
6472 if (m_quote->match(text, m_escape->interval.end, end, flags)) {
+
6473 value += '"'; interval.end = m_quote->interval.end;
+
6474 continue;
+
6475 }
+
6476 if (m_sol->match(text, m_escape->interval.end, end, flags)) {
+
6477 value += '/'; interval.end = m_sol->interval.end;
+
6478 continue;
+
6479 }
+
6480 if (m_bs->match(text, m_escape->interval.end, end, flags)) {
+
6481 value += '\b'; interval.end = m_bs->interval.end;
+
6482 continue;
+
6483 }
+
6484 if (m_ff->match(text, m_escape->interval.end, end, flags)) {
+
6485 value += '\f'; interval.end = m_ff->interval.end;
+
6486 continue;
+
6487 }
+
6488 if (m_lf->match(text, m_escape->interval.end, end, flags)) {
+
6489 value += '\n'; interval.end = m_lf->interval.end;
+
6490 continue;
+
6491 }
+
6492 if (m_cr->match(text, m_escape->interval.end, end, flags)) {
+
6493 value += '\r'; interval.end = m_cr->interval.end;
+
6494 continue;
+
6495 }
+
6496 if (m_htab->match(text, m_escape->interval.end, end, flags)) {
+
6497 value += '\t'; interval.end = m_htab->interval.end;
+
6498 continue;
+
6499 }
+
6500 if (
+
6501 m_uni->match(text, m_escape->interval.end, end, flags) &&
+
6502 m_hex->match(text, m_uni->interval.end, std::min(m_uni->interval.end + 4, end), flags | match_case_insensitive) &&
+
6503 m_hex->interval.size() == 4 /* JSON requests 4-digit Unicode sequneces: \u.... */)
+
6504 {
+
6505 assert(m_hex->value <= 0xffff);
+
6506 if (sizeof(T) == 1) {
+
6507 if (m_hex->value > 0x7ff) {
+
6508 value += (T)(0xe0 | (m_hex->value >> 12) & 0x0f);
+
6509 value += (T)(0x80 | (m_hex->value >> 6) & 0x3f);
+
6510 value += (T)(0x80 | m_hex->value & 0x3f);
+
6511 }
+
6512 else if (m_hex->value > 0x7f) {
+
6513 value += (T)(0xc0 | (m_hex->value >> 6) & 0x1f);
+
6514 value += (T)(0x80 | m_hex->value & 0x3f);
+
6515 }
+
6516 else
+
6517 value += (T)(m_hex->value & 0x7f);
+
6518 }
+
6519 else
+
6520 value += (T)m_hex->value;
+
6521 interval.end = m_hex->interval.end;
+
6522 continue;
+
6523 }
+
6524 if (m_escape->match(text, m_escape->interval.end, end, flags)) {
+
6525 value += '\\'; interval.end = m_escape->interval.end;
+
6526 continue;
+
6527 }
+
6528 }
+
6529 if (m_chr->match(text, interval.end, end, flags)) {
+
6530 value.Prilepi(text + m_chr->interval.start, m_chr->interval.size());
+
6531 interval.end = m_chr->interval.end;
+
6532 continue;
+
6533 }
+
6534 break;
+
6535 }
+
6536 }
+
6537 value.clear();
+
6538 interval.start = (interval.end = start) + 1;
+
6539 return false;
+
6540 }
+
6541
+
6542 virtual void invalidate()
+
6543 {
+
6544 value.clear();
+
6545 basic_parser<T>::invalidate();
+
6546 }
+
6547
+
6548 public:
+
6549 std::basic_string<T> value;
+
6550
+
6551 protected:
+
6552 std::shared_ptr<basic_parser<T>> m_quote;
+
6553 std::shared_ptr<basic_parser<T>> m_chr;
+
6554 std::shared_ptr<basic_parser<T>> m_escape;
+
6555 std::shared_ptr<basic_parser<T>> m_sol;
+
6556 std::shared_ptr<basic_parser<T>> m_bs;
+
6557 std::shared_ptr<basic_parser<T>> m_ff;
+
6558 std::shared_ptr<basic_parser<T>> m_lf;
+
6559 std::shared_ptr<basic_parser<T>> m_cr;
+
6560 std::shared_ptr<basic_parser<T>> m_htab;
+
6561 std::shared_ptr<basic_parser<T>> m_uni;
+
6562 std::shared_ptr<basic_integer16<T>> m_hex;
+
6563 };
+
6564
+
6565 using json_string = basic_json_string<char>;
+
6566 using wjson_string = basic_json_string<wchar_t>;
+
6567#ifdef _UNICODE
+
6568 using tjson_string = wjson_string;
+
6569#else
+
6570 using tjson_string = json_string;
+
6571#endif
+
6572 }
+
6573}
+
6574
+
6575#undef ENUM_FLAG_OPERATOR
+
6576#undef ENUM_FLAGS
+
6577
+
6578#ifdef _MSC_VER
+
6579#pragma warning(pop)
+
6580#endif
+
stdex::parser::basic_angle
Test for angle in d°mm'ss.dddd form.
Definition parser.hpp:4389
+
stdex::parser::basic_any_cu
Test for any code unit.
Definition parser.hpp:216
+
stdex::parser::basic_bol
Test for beginning of line.
Definition parser.hpp:610
+
stdex::parser::basic_branch
Test for any.
Definition parser.hpp:1052
+
stdex::parser::basic_chemical_formula
Test for chemical formula.
Definition parser.hpp:4663
+
stdex::parser::basic_cu_set
Test for any code unit from a given string of code units.
Definition parser.hpp:715
+
stdex::parser::basic_cu
Test for specific code unit.
Definition parser.hpp:286
+
stdex::parser::basic_date
Test for date.
Definition parser.hpp:4019
+
stdex::parser::basic_dns_domain_char
Test for valid DNS domain character.
Definition parser.hpp:2800
+
stdex::parser::basic_dns_domain_char::allow_on_edge
bool allow_on_edge
Is character allowed at the beginning or an end of a DNS domain?
Definition parser.hpp:2838
+
stdex::parser::basic_dns_name
Test for DNS domain/hostname.
Definition parser.hpp:2900
+
stdex::parser::basic_dns_name::m_allow_absolute
bool m_allow_absolute
May DNS names end with a dot (absolute name)?
Definition parser.hpp:2964
+
stdex::parser::basic_email_address
Test for e-mail address.
Definition parser.hpp:3788
+
stdex::parser::basic_emoticon
Test for emoticon.
Definition parser.hpp:3896
+
stdex::parser::basic_emoticon::apex
std::shared_ptr< basic_parser< T > > apex
apex/eyebrows/halo (e.g. O, 0)
Definition parser.hpp:3985
+
stdex::parser::basic_emoticon::eyes
std::shared_ptr< basic_parser< T > > eyes
eyes (e.g. :, ;, >, |, B)
Definition parser.hpp:3986
+
stdex::parser::basic_emoticon::mouth
std::shared_ptr< basic_set< T > > mouth
mouth (e.g. ), ), (, (, |, P, D, p, d)
Definition parser.hpp:3988
+
stdex::parser::basic_emoticon::nose
std::shared_ptr< basic_parser< T > > nose
nose (e.g. -, o)
Definition parser.hpp:3987
+
stdex::parser::basic_emoticon::emoticon
std::shared_ptr< basic_parser< T > > emoticon
emoticon as a whole (e.g. 😀, 🤔, 😶)
Definition parser.hpp:3984
+
stdex::parser::basic_eol
Test for end of line.
Definition parser.hpp:648
+
stdex::parser::basic_fraction
Test for fraction.
Definition parser.hpp:1681
+
stdex::parser::basic_integer10
Test for decimal integer.
Definition parser.hpp:1290
+
stdex::parser::basic_integer10ts
Test for decimal integer possibly containing thousand separators.
Definition parser.hpp:1375
+
stdex::parser::basic_integer10ts::has_separators
bool has_separators
Did integer have any separators?
Definition parser.hpp:1435
+
stdex::parser::basic_integer10ts::digit_count
size_t digit_count
Total number of digits in integer.
Definition parser.hpp:1434
+
stdex::parser::basic_integer16
Test for hexadecimal integer.
Definition parser.hpp:1456
+
stdex::parser::basic_integer
Base class for integer testing.
Definition parser.hpp:1268
+
stdex::parser::basic_integer::value
size_t value
Calculated value of the numeral.
Definition parser.hpp:1282
+
stdex::parser::basic_ipv4_address
Test for IPv4 address.
Definition parser.hpp:2340
+
stdex::parser::basic_ipv4_address::components
stdex::interval< size_t > components[4]
Individual component intervals.
Definition parser.hpp:2455
+
stdex::parser::basic_ipv4_address::value
struct in_addr value
IPv4 address value.
Definition parser.hpp:2456
+
stdex::parser::basic_ipv6_address
Test for IPv6 address.
Definition parser.hpp:2559
+
stdex::parser::basic_ipv6_address::scope_id
std::shared_ptr< basic_parser< T > > scope_id
Scope ID (e.g. NIC index with link-local addresses)
Definition parser.hpp:2763
+
stdex::parser::basic_ipv6_address::components
stdex::interval< size_t > components[8]
Individual component intervals.
Definition parser.hpp:2761
+
stdex::parser::basic_ipv6_address::value
struct in6_addr value
IPv6 address value.
Definition parser.hpp:2762
+
stdex::parser::basic_ipv6_scope_id_char
Test for valid IPv6 address scope ID character.
Definition parser.hpp:2487
+
stdex::parser::basic_iterations
Test for repeating.
Definition parser.hpp:905
+
stdex::parser::basic_iterations::m_greedy
bool m_greedy
try to match as long sequence as possible
Definition parser.hpp:944
+
stdex::parser::basic_iterations::m_el
std::shared_ptr< basic_parser< T > > m_el
repeating element
Definition parser.hpp:941
+
stdex::parser::basic_iterations::m_min_iterations
size_t m_min_iterations
minimum number of iterations
Definition parser.hpp:942
+
stdex::parser::basic_iterations::m_max_iterations
size_t m_max_iterations
maximum number of iterations
Definition parser.hpp:943
+
stdex::parser::basic_json_string
Test for JSON string.
Definition parser.hpp:6425
+
stdex::parser::basic_mixed_numeral
Test for mixed numeral.
Definition parser.hpp:1916
+
stdex::parser::basic_mixed_numeral::fraction
std::shared_ptr< basic_parser< T > > fraction
fraction
Definition parser.hpp:2022
+
stdex::parser::basic_mixed_numeral::special_sign
std::shared_ptr< basic_parser< T > > special_sign
Special sign (e.g. plus-minus '±')
Definition parser.hpp:2020
+
stdex::parser::basic_mixed_numeral::negative_sign
std::shared_ptr< basic_parser< T > > negative_sign
Negative sign.
Definition parser.hpp:2019
+
stdex::parser::basic_mixed_numeral::positive_sign
std::shared_ptr< basic_parser< T > > positive_sign
Positive sign.
Definition parser.hpp:2018
+
stdex::parser::basic_mixed_numeral::integer
std::shared_ptr< basic_parser< T > > integer
Integer part.
Definition parser.hpp:2021
+
stdex::parser::basic_monetary_numeral
Test for monetary numeral.
Definition parser.hpp:2211
+
stdex::parser::basic_monetary_numeral::positive_sign
std::shared_ptr< basic_parser< T > > positive_sign
Positive sign.
Definition parser.hpp:2317
+
stdex::parser::basic_monetary_numeral::decimal_separator
std::shared_ptr< basic_parser< T > > decimal_separator
Decimal separator.
Definition parser.hpp:2322
+
stdex::parser::basic_monetary_numeral::currency
std::shared_ptr< basic_parser< T > > currency
Currency part.
Definition parser.hpp:2320
+
stdex::parser::basic_monetary_numeral::decimal
std::shared_ptr< basic_parser< T > > decimal
Decimal part.
Definition parser.hpp:2323
+
stdex::parser::basic_monetary_numeral::integer
std::shared_ptr< basic_parser< T > > integer
Integer part.
Definition parser.hpp:2321
+
stdex::parser::basic_monetary_numeral::negative_sign
std::shared_ptr< basic_parser< T > > negative_sign
Negative sign.
Definition parser.hpp:2318
+
stdex::parser::basic_monetary_numeral::special_sign
std::shared_ptr< basic_parser< T > > special_sign
Special sign (e.g. plus-minus '±')
Definition parser.hpp:2319
+
stdex::parser::basic_noop
"No-op" match
Definition parser.hpp:184
+
stdex::parser::basic_parser
Base template for all parsers.
Definition parser.hpp:65
+
stdex::parser::basic_parser::interval
interval< size_t > interval
Region of the last match.
Definition parser.hpp:164
+
stdex::parser::basic_permutation
Test for permutation.
Definition parser.hpp:1192
+
stdex::parser::basic_phone_number
Test for phone number.
Definition parser.hpp:4512
+
stdex::parser::basic_phone_number::value
std::basic_string< T > value
Normalized phone number.
Definition parser.hpp:4638
+
stdex::parser::basic_punct_cu
Test for any punctuation code unit.
Definition parser.hpp:458
+
stdex::parser::basic_roman_numeral
Test for Roman numeral.
Definition parser.hpp:1565
+
stdex::parser::basic_scientific_numeral
Test for scientific numeral.
Definition parser.hpp:2042
+
stdex::parser::basic_scientific_numeral::special_sign
std::shared_ptr< basic_parser< T > > special_sign
Special sign (e.g. plus-minus '±')
Definition parser.hpp:2186
+
stdex::parser::basic_scientific_numeral::exponent_symbol
std::shared_ptr< basic_parser< T > > exponent_symbol
Exponent symbol (e.g. 'e')
Definition parser.hpp:2190
+
stdex::parser::basic_scientific_numeral::positive_sign
std::shared_ptr< basic_parser< T > > positive_sign
Positive sign.
Definition parser.hpp:2184
+
stdex::parser::basic_scientific_numeral::negative_sign
std::shared_ptr< basic_parser< T > > negative_sign
Negative sign.
Definition parser.hpp:2185
+
stdex::parser::basic_scientific_numeral::value
double value
Calculated value of the numeral.
Definition parser.hpp:2194
+
stdex::parser::basic_scientific_numeral::negative_exp_sign
std::shared_ptr< basic_parser< T > > negative_exp_sign
Negative exponent sign (e.g. '-')
Definition parser.hpp:2192
+
stdex::parser::basic_scientific_numeral::decimal
std::shared_ptr< basic_integer< T > > decimal
Decimal part.
Definition parser.hpp:2189
+
stdex::parser::basic_scientific_numeral::positive_exp_sign
std::shared_ptr< basic_parser< T > > positive_exp_sign
Positive exponent sign (e.g. '+')
Definition parser.hpp:2191
+
stdex::parser::basic_scientific_numeral::exponent
std::shared_ptr< basic_integer< T > > exponent
Exponent part.
Definition parser.hpp:2193
+
stdex::parser::basic_scientific_numeral::decimal_separator
std::shared_ptr< basic_parser< T > > decimal_separator
Decimal separator.
Definition parser.hpp:2188
+
stdex::parser::basic_scientific_numeral::integer
std::shared_ptr< basic_integer< T > > integer
Integer part.
Definition parser.hpp:2187
+
stdex::parser::basic_score
Test for match score.
Definition parser.hpp:1744
+
stdex::parser::basic_sequence
Test for sequence.
Definition parser.hpp:1001
+
stdex::parser::basic_set
Definition parser.hpp:683
+
stdex::parser::basic_signed_numeral
Test for signed numeral.
Definition parser.hpp:1830
+
stdex::parser::basic_signed_numeral::special_sign
std::shared_ptr< basic_parser< T > > special_sign
Special sign (e.g. plus-minus '±')
Definition parser.hpp:1898
+
stdex::parser::basic_signed_numeral::negative_sign
std::shared_ptr< basic_parser< T > > negative_sign
Negative sign.
Definition parser.hpp:1897
+
stdex::parser::basic_signed_numeral::positive_sign
std::shared_ptr< basic_parser< T > > positive_sign
Positive sign.
Definition parser.hpp:1896
+
stdex::parser::basic_signed_numeral::number
std::shared_ptr< basic_parser< T > > number
Number.
Definition parser.hpp:1899
+
stdex::parser::basic_space_cu
Test for any space code unit.
Definition parser.hpp:379
+
stdex::parser::basic_space_or_punct_cu
Test for any space or punctuation code unit.
Definition parser.hpp:532
+
stdex::parser::basic_string_branch
Test for any string.
Definition parser.hpp:1120
+
stdex::parser::basic_string
Test for given string.
Definition parser.hpp:810
+
stdex::parser::basic_time
Test for time.
Definition parser.hpp:4286
+
stdex::parser::basic_url_password_char
Test for valid URL password character.
Definition parser.hpp:3082
+
stdex::parser::basic_url_path_char
Test for valid URL path character.
Definition parser.hpp:3182
+
stdex::parser::basic_url_path
Test for URL path.
Definition parser.hpp:3290
+
stdex::parser::basic_url_username_char
Test for valid URL username character.
Definition parser.hpp:2983
+
stdex::parser::basic_url
Test for URL.
Definition parser.hpp:3431
+
stdex::parser::http_agent
Test for HTTP agent.
Definition parser.hpp:5948
+
stdex::parser::http_any_type
Test for HTTP any type.
Definition parser.hpp:5070
+
stdex::parser::http_asterisk
Test for HTTP asterisk.
Definition parser.hpp:5712
+ + + + + +
stdex::parser::http_header
Test for HTTP header.
Definition parser.hpp:6271
+
stdex::parser::http_language
Test for HTTP language (RFC1766)
Definition parser.hpp:5580
+
stdex::parser::http_line_break
Test for HTTP line break (RFC2616: CRLF | LF)
Definition parser.hpp:4744
+
stdex::parser::http_media_range
Test for HTTP media range (RFC2616: media-range)
Definition parser.hpp:5102
+
stdex::parser::http_media_type
Test for HTTP media type (RFC2616: media-type)
Definition parser.hpp:5157
+
stdex::parser::http_parameter
Test for HTTP parameter (RFC2616: parameter)
Definition parser.hpp:5015
+
stdex::parser::http_parameter::name
http_token name
Parameter name.
Definition parser.hpp:5059
+
stdex::parser::http_parameter::value
http_value value
Parameter value.
Definition parser.hpp:5060
+
stdex::parser::http_protocol
Test for HTTP protocol.
Definition parser.hpp:6024
+
stdex::parser::http_protocol::version
uint16_t version
HTTP protocol version: 0x100 = 1.0, 0x101 = 1.1...
Definition parser.hpp:6126
+
stdex::parser::http_quoted_string
Test for HTTP quoted string (RFC2616: quoted-string)
Definition parser.hpp:4905
+
stdex::parser::http_quoted_string::content
stdex::interval< size_t > content
String content (without quotes)
Definition parser.hpp:4961
+
stdex::parser::http_request
Test for HTTP request.
Definition parser.hpp:6133
+
stdex::parser::http_space
Test for HTTP space (RFC2616: LWS)
Definition parser.hpp:4780
+
stdex::parser::http_text_char
Test for HTTP text character (RFC2616: TEXT)
Definition parser.hpp:4817
+
stdex::parser::http_token
Test for HTTP token (RFC2616: token - tolerates non-ASCII)
Definition parser.hpp:4851
+
stdex::parser::http_url_parameter
Test for HTTP URL parameter.
Definition parser.hpp:5397
+
stdex::parser::http_url_path_segment
Test for HTTP URL path segment.
Definition parser.hpp:5308
+
stdex::parser::http_url_path
Test for HTTP URL path segment.
Definition parser.hpp:5341
+
stdex::parser::http_url_path::segments
std::vector< http_url_path_segment > segments
Path segments.
Definition parser.hpp:5390
+
stdex::parser::http_url_port
Test for HTTP URL port.
Definition parser.hpp:5252
+
stdex::parser::http_url_server
Test for HTTP URL server.
Definition parser.hpp:5215
+
stdex::parser::http_url
Test for HTTP URL.
Definition parser.hpp:5478
+
stdex::parser::http_value_collection
Collection of HTTP values.
Definition parser.hpp:6381
+
stdex::parser::http_value
Test for HTTP value (RFC2616: value)
Definition parser.hpp:4971
+
stdex::parser::http_value::string
http_quoted_string string
Value when matched as quoted string.
Definition parser.hpp:5007
+
stdex::parser::http_value::token
http_token token
Value when matched as token.
Definition parser.hpp:5008
+
stdex::parser::http_weight
Test for HTTP weight factor.
Definition parser.hpp:5643
+
stdex::parser::http_weight::value
float value
Calculated value of the weight factor.
Definition parser.hpp:5705
+
stdex::parser::http_weighted_value
Test for HTTP weighted value.
Definition parser.hpp:5735
+
stdex::parser::parser_collection
Base template for collection-holding parsers.
Definition parser.hpp:961
+
stdex::parser::sgml_any_cp
Test for any SGML code point.
Definition parser.hpp:248
+
stdex::parser::sgml_cp_set
Test for any SGML code point from a given string of SGML code points.
Definition parser.hpp:767
+
stdex::parser::sgml_cp
Test for specific SGML code point.
Definition parser.hpp:335
+
stdex::parser::sgml_dns_domain_char
Test for valid DNS domain SGML character.
Definition parser.hpp:2856
+
stdex::parser::sgml_ipv6_scope_id_char
Test for valid IPv6 address scope ID SGML character.
Definition parser.hpp:2525
+
stdex::parser::sgml_punct_cp
Test for any SGML punctuation code point.
Definition parser.hpp:499
+
stdex::parser::sgml_space_cp
Test for any SGML space code point.
Definition parser.hpp:422
+
stdex::parser::sgml_space_or_punct_cp
Test for any SGML space or punctuation code point.
Definition parser.hpp:575
+
stdex::parser::sgml_string
Test for SGML given string.
Definition parser.hpp:857
+
stdex::parser::sgml_url_password_char
Test for valid URL password SGML character.
Definition parser.hpp:3134
+
stdex::parser::sgml_url_path_char
Test for valid URL path SGML character.
Definition parser.hpp:3238
+
stdex::parser::sgml_url_username_char
Test for valid URL username SGML character.
Definition parser.hpp:3034
stdex::interval
Numerical interval.
Definition interval.hpp:18
stdex::interval::size
T size() const
Returns interval size.
Definition interval.hpp:47
stdex::interval::end
T end
interval end
Definition interval.hpp:20
stdex::interval::interval
interval() noexcept
Constructs an invalid interval.
Definition interval.hpp:25
stdex::interval::start
T start
interval start
Definition interval.hpp:19
-
stdex::parser::http_factor_more
Definition parser.hpp:6405
+
stdex::parser::http_factor_more
Definition parser.hpp:6407
diff --git a/pch_8h_source.html b/pch_8h_source.html index e16cb72b1..a7ef09249 100644 --- a/pch_8h_source.html +++ b/pch_8h_source.html @@ -105,7 +105,7 @@ $(function() { diff --git a/progress_8hpp_source.html b/progress_8hpp_source.html index 8efb15694..90a71f600 100644 --- a/progress_8hpp_source.html +++ b/progress_8hpp_source.html @@ -282,7 +282,7 @@ $(function() { diff --git a/sal_8hpp_source.html b/sal_8hpp_source.html index ba49e986a..d9eb84617 100644 --- a/sal_8hpp_source.html +++ b/sal_8hpp_source.html @@ -143,7 +143,7 @@ $(function() { diff --git a/sgml_8hpp_source.html b/sgml_8hpp_source.html index e1bf8f226..7ff050b68 100644 --- a/sgml_8hpp_source.html +++ b/sgml_8hpp_source.html @@ -423,7 +423,7 @@ $(function() { diff --git a/sgml__unicode_8hpp_source.html b/sgml__unicode_8hpp_source.html index f72c42925..9469d72b5 100644 --- a/sgml__unicode_8hpp_source.html +++ b/sgml__unicode_8hpp_source.html @@ -3170,7 +3170,7 @@ $(function() { diff --git a/string_8hpp_source.html b/string_8hpp_source.html index 4bb1f9f16..33fbe1e7d 100644 --- a/string_8hpp_source.html +++ b/string_8hpp_source.html @@ -691,7 +691,7 @@ $(function() { diff --git a/structstdex_1_1interval-members.html b/structstdex_1_1interval-members.html index 5ff198b44..82aa447fa 100644 --- a/structstdex_1_1interval-members.html +++ b/structstdex_1_1interval-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/structstdex_1_1interval.html b/structstdex_1_1interval.html index 0cd789a19..af83df444 100644 --- a/structstdex_1_1interval.html +++ b/structstdex_1_1interval.html @@ -384,7 +384,7 @@ template<class T > diff --git a/structstdex_1_1mapping-members.html b/structstdex_1_1mapping-members.html index 8cf778680..8760a1b0d 100644 --- a/structstdex_1_1mapping-members.html +++ b/structstdex_1_1mapping-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/structstdex_1_1mapping.html b/structstdex_1_1mapping.html index 300c0528f..085c688bd 100644 --- a/structstdex_1_1mapping.html +++ b/structstdex_1_1mapping.html @@ -283,7 +283,7 @@ template<class T > diff --git a/structstdex_1_1no__delete-members.html b/structstdex_1_1no__delete-members.html index a6d34f332..6e373179d 100644 --- a/structstdex_1_1no__delete-members.html +++ b/structstdex_1_1no__delete-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/structstdex_1_1no__delete.html b/structstdex_1_1no__delete.html index 839ce4cb8..5609acc6f 100644 --- a/structstdex_1_1no__delete.html +++ b/structstdex_1_1no__delete.html @@ -105,7 +105,7 @@ struct stdex::no_delete< T >

Noop deleter.

diff --git a/structstdex_1_1no__delete_3_01_t_0f_0e_4-members.html b/structstdex_1_1no__delete_3_01_t_0f_0e_4-members.html index 420e0d758..aaf3087c0 100644 --- a/structstdex_1_1no__delete_3_01_t_0f_0e_4-members.html +++ b/structstdex_1_1no__delete_3_01_t_0f_0e_4-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/structstdex_1_1no__delete_3_01_t_0f_0e_4.html b/structstdex_1_1no__delete_3_01_t_0f_0e_4.html index acd51b62e..b2233bee7 100644 --- a/structstdex_1_1no__delete_3_01_t_0f_0e_4.html +++ b/structstdex_1_1no__delete_3_01_t_0f_0e_4.html @@ -106,7 +106,7 @@ struct stdex::no_delete< T[]>

Noop array deleter.

diff --git a/structstdex_1_1parser_1_1http__factor__more-members.html b/structstdex_1_1parser_1_1http__factor__more-members.html index 0039abc01..d46605610 100644 --- a/structstdex_1_1parser_1_1http__factor__more-members.html +++ b/structstdex_1_1parser_1_1http__factor__more-members.html @@ -84,7 +84,7 @@ $(function() { diff --git a/structstdex_1_1parser_1_1http__factor__more.html b/structstdex_1_1parser_1_1http__factor__more.html index c9b84067c..536887c98 100644 --- a/structstdex_1_1parser_1_1http__factor__more.html +++ b/structstdex_1_1parser_1_1http__factor__more.html @@ -93,7 +93,7 @@ constexpr bool operator()< diff --git a/unicode_8hpp_source.html b/unicode_8hpp_source.html index fa8149eaa..ce2ab8a70 100644 --- a/unicode_8hpp_source.html +++ b/unicode_8hpp_source.html @@ -208,7 +208,7 @@ $(function() { diff --git a/vector__queue_8hpp_source.html b/vector__queue_8hpp_source.html index 40a07fde0..d1644f4f1 100644 --- a/vector__queue_8hpp_source.html +++ b/vector__queue_8hpp_source.html @@ -386,7 +386,7 @@ $(function() {